List:Commits« Previous MessageNext Message »
From:Gleb Shchepa Date:May 25 2011 2:35pm
Subject:bzr push into mysql-trunk branch (gleb.shchepa:3357 to 3358)
View as plain text  
 3358 Gleb Shchepa	2011-05-25
      WL4897: Add EXPLAIN INSERT/UPDATE/DELETE
      
      Post-review modifications.
     @ client/mysqltest.cc
        Guilhem's patch for MTR --explain-protocol
     @ mysql-test/include/explain_non_select.inc
        Additional tests for WL4897.
     @ mysql-test/r/case.result
        Minor changes ("explain" column message reordering) after WL4897.
     @ mysql-test/r/explain.result
        Minor changes ("explain" column message reordering) after WL4897.
     @ mysql-test/r/explain_non_select.result
        Additional tests for WL4897.
     @ mysql-test/r/func_gconcat.result
        Minor changes ("explain" column message reordering) after WL4897.
     @ mysql-test/r/key.result
        Minor changes ("explain" column message reordering) after WL4897.
     @ mysql-test/r/optimizer_switch.result
        Minor changes ("explain" column message reordering) after WL4897.
     @ mysql-test/r/udf.result
        Minor changes ("explain" column message reordering) after WL4897.
     @ mysql-test/t/explain_non_select.test
        Additional tests for WL4897.
     @ sql/opt_explain.cc
        + The memroot_str helper class has been added to remove intermediate
          buff_* and str_* member variables of Explain_* classes.
        * Refactoring of explain_key_and_len and explain_extra methods of
          Explain_table and Explain_join classes.
        * Minor changes
     @ sql/opt_explain.h
        Minor changes and renamings.
     @ sql/opt_range.h
        Update of the Copyright.
     @ sql/sql_class.h
        Minor changes.
     @ sql/sql_delete.cc
        Common exit path for new code branches has been added.
     @ sql/sql_insert.cc
        Common exit path for new code branches has been added.
     @ sql/sql_parse.cc
        Renaming.
     @ sql/sql_select.cc
        Renaming.
     @ sql/sql_update.cc
        Common exit path for new code branches has been added.
     @ sql/sql_view.cc
        Permission check for views has been added.
     @ sql/sql_yacc.yy
        Refactoring.

    modified:
      client/mysqltest.cc
      mysql-test/include/explain_non_select.inc
      mysql-test/r/case.result
      mysql-test/r/explain.result
      mysql-test/r/explain_non_select.result
      mysql-test/r/func_gconcat.result
      mysql-test/r/key.result
      mysql-test/r/optimizer_switch.result
      mysql-test/r/udf.result
      mysql-test/t/explain_non_select.test
      sql/opt_explain.cc
      sql/opt_explain.h
      sql/opt_range.h
      sql/sql_class.h
      sql/sql_delete.cc
      sql/sql_insert.cc
      sql/sql_parse.cc
      sql/sql_select.cc
      sql/sql_update.cc
      sql/sql_view.cc
      sql/sql_yacc.yy
 3357 Gleb Shchepa	2011-03-30
      WL#4897: Add EXPLAIN INSERT/UPDATE/DELETE
      
      WL#4897 implements EXPLAIN command for INSERT, REPLACE and
      single- and multi-table UPDATE and DELETE queries.
     @ mysql-test/include/explain_non_select.inc
        Coverage and regresstion tests and sanity checks for WL#4897.
     @ mysql-test/r/explain_non_select.result
        Coverage and regresstion tests and sanity checks for WL#4897.
     @ mysql-test/t/explain_non_select.test
        Coverage and regresstion tests and sanity checks for WL#4897.
     @ sql/CMakeLists.txt
        New opt_explain.cc source file has been added.
     @ sql/opt_explain.cc
        WL#4897: Add EXPLAIN INSERT/UPDATE/DELETE
        
        The select_describe() functions has been refactored into
        msg_describe() and select_describe () global functions and
        a few local auxiliary classes: Explain, Explain_msg,
        Explain_table_base, Explain_union and Explain_join.
        
        Also the functionality of select_describe() has been
        improved to serve top-JOIN-less EXPLAIN queries (EXPLAIN
        single-table UPDATE and DELETE) with the help of the new
        global table_describe() function and auxiliary Explain_table
        class.
        
        explain_send class and explain_data_modification() function
        have been added to adapt select_insert, multi_update and
        multi_delete classes to work in EXPLAIN context (to
        implement EXPLAIN INSERT...SELECT and EXPLAIN multi-table
        UPDATE and DELETE commands).
     @ sql/opt_explain.h
        WL#4897: Add EXPLAIN INSERT/UPDATE/DELETE
        
        Signatures of new msg_describe(), bool table_describe() and
        explain_data_modification() functions have been added.
        
        Modified declaration for the select_describe() function has
        been moved there from the sql_select.cc file.
     @ sql/opt_range.h
        WL#4897: Add EXPLAIN INSERT/UPDATE/DELETE
        
        Minor change: unnecessary friending of the select_describe()
        function has been removed.
     @ sql/sql_class.h
        WL#4897: Add EXPLAIN INSERT/UPDATE/DELETE
        
        The select_result::reset_offset_limit_cnt() method has been added
        to reset protected offset_limit_cnt field.
     @ sql/sql_delete.cc
        WL#4897: Add EXPLAIN INSERT/UPDATE/DELETE
        
        The mysql_delete() function has been improved to work in the
        EXPLAIN multi-table DELETE context to produce EXPLAIN instead
        table data modification.
     @ sql/sql_insert.cc
        WL#4897: Add EXPLAIN INSERT/UPDATE/DELETE
        
        The mysql_insert() function has been improved to work in the
        EXPLAIN INSERT...SELECT context to produce EXPLAIN instead
        table data modification.
     @ sql/sql_parse.cc
        WL#4897: Add EXPLAIN INSERT/UPDATE/DELETE
        
        INSERT...SELECT, REPLACE...SELECT and multi-table UPDATE/DELETE
        handlers have been improved to work with EXPLAIN of these
        queries.
     @ sql/sql_select.cc
        WL#4897: Add EXPLAIN INSERT/UPDATE/DELETE
        
        The select_describe() function has been moved to opt_explain.{h,cc}
        files and refactored.
     @ sql/sql_show.cc
        WL#4897: Add EXPLAIN INSERT/UPDATE/DELETE
        
        Minor cleanup.
     @ sql/sql_update.cc
        WL#4897: Add EXPLAIN INSERT/UPDATE/DELETE
        
        The mysql_delete() function has been improved to work in the
        EXPLAIN multi-table UPDATE context to produce EXPLAIN instead
        table data modification.
     @ sql/sql_yacc.yy
        WL#4897: Add EXPLAIN INSERT/UPDATE/DELETE
        
        New EXPLAIN INSERT/REPLACE/UPDATE/DELETE syntax has been added.

    added:
      mysql-test/include/explain_non_select.inc
      mysql-test/r/explain_non_select.result
      mysql-test/t/explain_non_select.test
      sql/opt_explain.cc
      sql/opt_explain.h
    modified:
      sql/CMakeLists.txt
      sql/opt_range.h
      sql/sql_class.h
      sql/sql_delete.cc
      sql/sql_insert.cc
      sql/sql_parse.cc
      sql/sql_select.cc
      sql/sql_show.cc
      sql/sql_update.cc
      sql/sql_yacc.yy
=== modified file 'client/mysqltest.cc'
--- a/client/mysqltest.cc	2011-03-22 15:40:32 +0000
+++ b/client/mysqltest.cc	2011-05-25 14:16:06 +0000
@@ -201,6 +201,7 @@ static char *opt_plugin_dir= 0;
 static my_regex_t ps_re;     /* the query can be run using PS protocol */
 static my_regex_t sp_re;     /* the query can be run as a SP */
 static my_regex_t view_re;   /* the query can be run as a view*/
+static my_regex_t explain_re;/* the query can be converted to EXPLAIN */
 
 static void init_re(void);
 static int match_re(my_regex_t *, char *);
@@ -6389,7 +6390,7 @@ static struct my_option my_long_options[
   {"view-protocol", OPT_VIEW_PROTOCOL, "Use views for select.",
    &view_protocol, &view_protocol, 0,
    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-  {"explain-protocol", OPT_EXPLAIN_PROTOCOL, "Explains all select.",
+  {"explain-protocol", OPT_EXPLAIN_PROTOCOL, "Explains all select/update/etc.",
    &explain_protocol, &explain_protocol, 0,
    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"connect_timeout", OPT_CONNECT_TIMEOUT,
@@ -7880,7 +7881,7 @@ void run_explain(struct st_connection *c
 {
   if (explain_protocol_enabled &&
       !command->expected_errors.count &&
-      match_re(&view_re, command->query))
+      match_re(&explain_re, command->query))
   {
     st_command save_command= *command;
     DYNAMIC_STRING query_str;
@@ -7890,6 +7891,7 @@ void run_explain(struct st_connection *c
     init_dynamic_string(&query_str, "EXPLAIN EXTENDED ", 256, 256);
     dynstr_append_mem(&query_str, command->query,
                       command->end - command->query);
+    
     command->query= query_str.str;
     command->query_len= query_str.length;
     command->end= strend(command->query);
@@ -7963,9 +7965,16 @@ void init_re(void)
     "^("
     "[[:space:]]*SELECT[[:space:]])";
 
+
+  /* Filter for queries that can be converted to EXPLAIN */
+  const char *explain_re_str =
+    "^("
+    "[[:space:]]*(SELECT|DELETE|UPDATE|INSERT|REPLACE)[[:space:]])";
+
   init_re_comp(&ps_re, ps_re_str);
   init_re_comp(&sp_re, sp_re_str);
   init_re_comp(&view_re, view_re_str);
+  init_re_comp(&explain_re, explain_re_str);
 }
 
 
@@ -8629,8 +8638,15 @@ int main(int argc, char **argv)
 	  strmake(command->require_file, save_file, sizeof(save_file) - 1);
 	  save_file[0]= 0;
 	}
-	run_query(cur_con, command, flags);
+        /*
+          Gleb:
+          I run EXPLAIN _before_ the query. If query is UPDATE/DELETE is
+          matters: a DELETE may delete rows, and then EXPLAIN DELETE will
+          usually terminate quickly with "no matching rows". To make it more
+          interesting, EXPLAIN is now first.
+        */
 	run_explain(cur_con, command, flags);
+	run_query(cur_con, command, flags);
 	command_executed++;
         command->last_argument= command->end;
 

=== modified file 'mysql-test/include/explain_non_select.inc'
--- a/mysql-test/include/explain_non_select.inc	2011-03-30 16:48:25 +0000
+++ b/mysql-test/include/explain_non_select.inc	2011-05-25 14:16:06 +0000
@@ -15,14 +15,22 @@ if (`SELECT ROW_COUNT() > 0`) {
 --die Unexpected ROW_COUNT() <> 0
 }
 
+FLUSH STATUS;
+FLUSH TABLES;
 --eval EXPLAIN EXTENDED $query
 if (`SELECT ROW_COUNT() > 0`) {
 --echo # Erroneous query: EXPLAIN EXTENDED $query
 --die Unexpected ROW_COUNT() <> 0
 }
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+                   Variable_name LIKE 'Handler_read_%') AND Value <> 0;
 
 if ($select) {
+FLUSH STATUS;
+FLUSH TABLES;
 --eval EXPLAIN EXTENDED $select
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+                   Variable_name LIKE 'Handler_read_%') AND Value <> 0;
 }
 
 --disable_query_log

=== modified file 'mysql-test/r/case.result'
--- a/mysql-test/r/case.result	2010-08-19 11:55:35 +0000
+++ b/mysql-test/r/case.result	2011-05-25 14:16:06 +0000
@@ -64,7 +64,7 @@ fcase	count(*)
 3	1
 explain extended select case a when 1 then 2 when 2 then 3 else 0 end as fcase, count(*) from t1 group by fcase;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
-1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	4	100.00	Using temporary; Using filesort
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	4	100.00	Using filesort; Using temporary
 Warnings:
 Note	1003	select (case `test`.`t1`.`a` when 1 then 2 when 2 then 3 else 0 end) AS `fcase`,count(0) AS `count(*)` from `test`.`t1` group by (case `test`.`t1`.`a` when 1 then 2 when 2 then 3 else 0 end)
 select case a when 1 then "one" when 2 then "two" else "nothing" end as fcase, count(*) from t1 group by fcase;

=== modified file 'mysql-test/r/explain.result'
--- a/mysql-test/r/explain.result	2010-12-17 11:28:59 +0000
+++ b/mysql-test/r/explain.result	2011-05-25 14:16:06 +0000
@@ -115,7 +115,7 @@ EXPLAIN EXTENDED SELECT 1
 FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
-2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
+2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using filesort; Using temporary
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer (BNL, incremental buffers)
 Warnings:
 Note	1003	select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
@@ -123,7 +123,7 @@ EXPLAIN EXTENDED SELECT 1
 FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
-2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
+2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using filesort; Using temporary
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer (BNL, incremental buffers)
 Warnings:
 Note	1003	select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
@@ -133,7 +133,7 @@ prepare s1 from
 execute s1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
-2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
+2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using filesort; Using temporary
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer (BNL, incremental buffers)
 Warnings:
 Note	1003	select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
@@ -143,14 +143,14 @@ prepare s1 from
 execute s1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
-2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
+2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using filesort; Using temporary
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer (BNL, incremental buffers)
 Warnings:
 Note	1003	select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
 execute s1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
-2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
+2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using filesort; Using temporary
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer (BNL, incremental buffers)
 Warnings:
 Note	1003	select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`

=== modified file 'mysql-test/r/explain_non_select.result'
--- a/mysql-test/r/explain_non_select.result	2011-03-30 16:48:25 +0000
+++ b/mysql-test/r/explain_non_select.result	2011-05-25 14:16:06 +0000
@@ -1,3 +1,4 @@
+SET SESSION DEFAULT_STORAGE_ENGINE = MyISAM;
 CREATE TABLE t1 (a INT);
 INSERT INTO t1 VALUES (1), (2), (3);
 #
@@ -7,14 +8,24 @@ INSERT INTO t1 VALUES (1), (2), (3);
 EXPLAIN UPDATE t1 SET a = 10 WHERE a < 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a < 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1     WHERE a < 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` < 10)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	4
@@ -33,14 +44,24 @@ INSERT INTO t1 VALUES (1), (2), (3);
 EXPLAIN DELETE   FROM t1 WHERE a < 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 WHERE a < 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a < 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` < 10)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	4
@@ -59,14 +80,24 @@ INSERT INTO t1 VALUES (1), (2), (3);
 EXPLAIN DELETE   FROM t1 USING t1 WHERE a = 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 USING t1 WHERE a = 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1          WHERE a = 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = 1)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	4
@@ -88,16 +119,26 @@ EXPLAIN UPDATE        t1, t2 SET t1.a =
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	Using where
 1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	3	Using join buffer (BNL, incremental buffers)
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE        t1, t2 SET t1.a = 10 WHERE t1.a = 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
 1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	Using join buffer (BNL, incremental buffers)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1, t2               WHERE t1.a = 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
 1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	Using join buffer (BNL, incremental buffers)
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` join `test`.`t2` where (`test`.`t1`.`a` = 1)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	8
@@ -120,11 +161,19 @@ id	select_type	table	type	possible_keys
 1	PRIMARY	t11	ALL	NULL	NULL	NULL	NULL	3	Using where
 1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	3	Using join buffer (BNL, incremental buffers)
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	3	
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE        t1 t11, (SELECT * FROM t2) t12 SET t11.a = 10 WHERE t11.a = 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t11	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
 1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	3	100.00	Using join buffer (BNL, incremental buffers)
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_rnd_next	4
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 t11, (SELECT * FROM t2) t12                WHERE t11.a = 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t11	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
@@ -132,6 +181,10 @@ id	select_type	table	type	possible_keys
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	
 Warnings:
 Note	1003	select `test`.`t11`.`a` AS `a`,`t12`.`b` AS `b` from `test`.`t1` `t11` join (select `test`.`t2`.`b` AS `b` from `test`.`t2`) `t12` where (`test`.`t11`.`a` = 1)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_rnd_next	4
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	12
@@ -154,16 +207,26 @@ EXPLAIN UPDATE        t1 SET a = 10 WHER
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	Using where
 2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	3	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE        t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
 2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1            WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where; FirstMatch(t1); Using join buffer (BNL, incremental buffers)
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where (`test`.`t2`.`b` < 3)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	8
@@ -185,12 +248,19 @@ EXPLAIN UPDATE        t1 SET a = 10 WHER
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	Using where
 2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	3	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE        t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
 2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
 Warnings:
 Note	1276	Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1            WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
@@ -198,6 +268,9 @@ id	select_type	table	type	possible_keys
 Warnings:
 Note	1276	Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
 Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`b` = `test`.`t1`.`a`) and (`test`.`t1`.`a` < 3))
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	8
@@ -220,11 +293,18 @@ id	select_type	table	type	possible_keys
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	Using where
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	3	Using join buffer (BNL, incremental buffers)
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	3	Using where; FirstMatch(t2); Using join buffer (BNL, incremental buffers)
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE        t1, t2 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t2.b < 3);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	Using join buffer (BNL, incremental buffers)
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where; FirstMatch(t2); Using join buffer (BNL, incremental buffers)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1, t2            WHERE a IN (SELECT b FROM t2 WHERE t2.b < 3);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
@@ -232,6 +312,9 @@ id	select_type	table	type	possible_keys
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where; FirstMatch(t2); Using join buffer (BNL, incremental buffers)
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` semi join (`test`.`t2`) join `test`.`t2` where ((`test`.`t2`.`b` = `test`.`t1`.`a`) and (`test`.`t1`.`a` < 3))
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	12
@@ -254,11 +337,19 @@ id	select_type	table	type	possible_keys
 1	PRIMARY	t11	ALL	NULL	NULL	NULL	NULL	3	
 1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	3	Using join buffer (BNL, incremental buffers)
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	3	
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE        t1 t11, (SELECT * FROM t2) t12 SET t11.a = t11.a + 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t11	ALL	NULL	NULL	NULL	NULL	3	100.00	
 1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	3	100.00	Using join buffer (BNL, incremental buffers)
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_rnd_next	4
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 t11, (SELECT * FROM t2) t12;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t11	ALL	NULL	NULL	NULL	NULL	3	100.00	
@@ -266,6 +357,10 @@ id	select_type	table	type	possible_keys
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	
 Warnings:
 Note	1003	select `test`.`t11`.`a` AS `a`,`t12`.`b` AS `b` from `test`.`t1` `t11` join (select `test`.`t2`.`b` AS `b` from `test`.`t2`) `t12`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_rnd_next	4
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	12
@@ -290,11 +385,20 @@ id	select_type	table	type	possible_keys
 1	PRIMARY	<derived2>	system	NULL	NULL	NULL	NULL	1	
 1	PRIMARY	t11	ALL	NULL	NULL	NULL	NULL	3	
 2	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE        t1 t11, (SELECT 1 FROM DUAL) t12 SET t11.a = t11.a + 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	<derived2>	system	NULL	NULL	NULL	NULL	1	100.00	
 1	PRIMARY	t11	ALL	NULL	NULL	NULL	NULL	3	100.00	
 2	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_first	1
+Handler_read_rnd_next	1
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 t11, (SELECT 1 FROM DUAL) t12;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	<derived2>	system	NULL	NULL	NULL	NULL	1	100.00	
@@ -302,6 +406,11 @@ id	select_type	table	type	possible_keys
 2	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 Warnings:
 Note	1003	select `test`.`t11`.`a` AS `a`,'1' AS `1` from `test`.`t1` `t11`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_first	1
+Handler_read_rnd_next	1
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_first	1
@@ -328,11 +437,19 @@ id	select_type	table	type	possible_keys
 1	PRIMARY	t11	ALL	NULL	NULL	NULL	NULL	3	Using where
 1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	3	Using join buffer (BNL, incremental buffers)
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	3	
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE        t1 t11, (SELECT * FROM t2) t12 SET t11.a = 10 WHERE t11.a > 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t11	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
 1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	3	100.00	Using join buffer (BNL, incremental buffers)
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_rnd_next	4
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 t11, (SELECT * FROM t2) t12                WHERE t11.a > 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t11	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
@@ -340,6 +457,10 @@ id	select_type	table	type	possible_keys
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	
 Warnings:
 Note	1003	select `test`.`t11`.`a` AS `a`,`t12`.`b` AS `b` from `test`.`t1` `t11` join (select `test`.`t2`.`b` AS `b` from `test`.`t2`) `t12` where (`test`.`t11`.`a` > 1)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_rnd_next	4
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	12
@@ -359,14 +480,24 @@ INSERT INTO t1 VALUES (1), (2), (3);
 EXPLAIN DELETE   FROM t1 WHERE a > 1 LIMIT 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 WHERE a > 1 LIMIT 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a > 1 LIMIT 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > 1) limit 1
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	2
@@ -385,14 +516,24 @@ INSERT INTO t1 VALUES (1), (2), (3);
 EXPLAIN DELETE   FROM t1 WHERE 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 WHERE 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 WHERE 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 # Status of testing query execution:
@@ -408,14 +549,24 @@ INSERT INTO t1 VALUES (1), (2), (3);
 EXPLAIN DELETE   FROM t1 USING t1 WHERE 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 USING t1 WHERE 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1          WHERE 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 # Status of testing query execution:
@@ -431,14 +582,25 @@ INSERT INTO t1 VALUES (3, 3), (7, 7);
 EXPLAIN DELETE   FROM t1 WHERE a = 3;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	range	a,b	a	5	NULL	1	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 WHERE a = 3;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	range	a,b	a	5	NULL	1	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a = 3;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	const	a	a	5	const	1	100.00	
 Warnings:
 Note	1003	select '3' AS `a`,'3' AS `b` from `test`.`t1` where 1
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_key	1
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_key	1
@@ -457,14 +619,24 @@ INSERT INTO t1 VALUES (3, 3), (7, 7);
 EXPLAIN DELETE   FROM t1 WHERE a < 3;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	range	a,b	a	5	NULL	1	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 WHERE a < 3;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	range	a,b	a	5	NULL	1	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a < 3;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	range	a	a	5	NULL	1	100.00	Using index condition
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (`test`.`t1`.`a` < 3)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_key	1
@@ -481,14 +653,26 @@ CREATE TABLE t1 ( a int PRIMARY KEY );
 EXPLAIN DELETE   FROM t1 WHERE t1.a > 0 ORDER BY t1.a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 WHERE t1.a > 0 ORDER BY t1.a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a > 0 ORDER BY t1.a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
 Warnings:
 Note	1003	select NULL AS `a` from `test`.`t1` where 0 order by NULL
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_first	1
+Handler_read_rnd_next	1
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_first	1
@@ -505,14 +689,24 @@ INSERT INTO t1 VALUES (1), (2), (3);
 EXPLAIN DELETE   FROM t1 WHERE t1.a > 0 ORDER BY t1.a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	3	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 WHERE t1.a > 0 ORDER BY t1.a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	3	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a > 0 ORDER BY t1.a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	index	PRIMARY	PRIMARY	4	NULL	3	100.00	Using where; Using index
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > 0) order by `test`.`t1`.`a`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_first	1
@@ -533,14 +727,24 @@ INSERT INTO t1 VALUES (4),(3),(1),(2);
 EXPLAIN DELETE   FROM t1 WHERE (@a:= a) ORDER BY a LIMIT 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ALL	PRIMARY	PRIMARY	4	NULL	4	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 WHERE (@a:= a) ORDER BY a LIMIT 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	PRIMARY	PRIMARY	4	NULL	4	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 WHERE (@a:= a) ORDER BY a LIMIT 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	index	NULL	PRIMARY	4	NULL	1	400.00	Using where; Using index
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (@a:=`test`.`t1`.`a`) order by `test`.`t1`.`a` limit 1
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_first	1
@@ -560,14 +764,24 @@ UPDATE t1 SET a = c, b = c;
 EXPLAIN DELETE   FROM t1 ORDER BY a ASC, b ASC LIMIT 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ALL	c,b,a	NULL	NULL	NULL	10	Using filesort
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 ORDER BY a ASC, b ASC LIMIT 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	c,b,a	NULL	NULL	NULL	10	100.00	Using filesort
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 ORDER BY a ASC, b ASC LIMIT 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	10	100.00	Using filesort
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` order by `test`.`t1`.`a`,`test`.`t1`.`b` limit 1
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	11
@@ -597,11 +811,18 @@ id	select_type	table	type	possible_keys
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	
 1	SIMPLE	t2	ref	PRIMARY	PRIMARY	4	test.t1.a1	1	
 1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t2.b2,test.t1.b1	1	
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE t1,t2,t3 FROM t1,t2,t3 WHERE a1=a2 AND b2=a3 AND b1=b3;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	
 1	SIMPLE	t2	ref	PRIMARY	PRIMARY	4	test.t1.a1	1	100.00	
 1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t2.b2,test.t1.b1	1	100.00	
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT *        FROM t1,t2,t3 WHERE a1=a2 AND b2=a3 AND b1=b3;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	
@@ -609,6 +830,9 @@ id	select_type	table	type	possible_keys
 1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t2.b2,test.t1.b1	1	100.00	Using index
 Warnings:
 Note	1003	select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b2` AS `b2`,`test`.`t3`.`a3` AS `a3`,`test`.`t3`.`b3` AS `b3` from `test`.`t1` join `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`b3` = `test`.`t1`.`b1`) and (`test`.`t3`.`a3` = `test`.`t2`.`b2`) and (`test`.`t2`.`a2` = `test`.`t1`.`a1`))
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_key	6
@@ -635,16 +859,26 @@ EXPLAIN UPDATE t1 SET a = 10 WHERE a IN
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	Using where
 2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	3	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
 2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1     WHERE a IN (SELECT a FROM t2);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where; FirstMatch(t1); Using join buffer (BNL, incremental buffers)
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where (`test`.`t2`.`a` = `test`.`t1`.`a`)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	8
@@ -668,16 +902,26 @@ EXPLAIN DELETE   FROM t1 WHERE a1 IN (SE
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	5	Using where
 2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	5	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	5	100.00	Using where
 2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	5	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	5	100.00	Using where
 2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	5	100.00	Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a1` AS `a1` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a1`,<exists>(select 1 from `test`.`t2` where ((`test`.`t2`.`a2` > 2) and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`a2`))))
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	30
@@ -697,16 +941,26 @@ EXPLAIN DELETE   FROM t1 WHERE a1 IN (SE
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	5	Using where
 2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	5	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	5	100.00	Using where
 2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	5	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	5	100.00	
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	5	100.00	Using where; FirstMatch(t1); Using join buffer (BNL, incremental buffers)
 Warnings:
 Note	1003	select `test`.`t1`.`a1` AS `a1` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`a2` > 2) and (`test`.`t1`.`a1` = `test`.`t2`.`a2`))
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	12
@@ -725,14 +979,24 @@ INSERT INTO t1 VALUES (1, 1), (2, 2), (3
 EXPLAIN UPDATE t1 SET i = 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	5	
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t1 SET i = 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	5	100.00	
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	5	100.00	
 Warnings:
 Note	1003	select `test`.`t1`.`i` AS `i`,`test`.`t1`.`j` AS `j` from `test`.`t1`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	6
@@ -742,7 +1006,7 @@ Handler_read_rnd_next	6
 Handler_update	5
 
 DROP TABLE t1;
-CREATE TABLE t1 (i INT, j INT);
+CREATE TABLE t1 (i INT, j INT) ENGINE=MyISAM;
 INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);
 #
 # query:  DELETE FROM t1
@@ -750,15 +1014,25 @@ INSERT INTO t1 VALUES (1, 1), (2, 2), (3
 #
 EXPLAIN DELETE FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	5	Using delete_all_rows
+1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	5	Deleting all rows
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
-1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	5	NULL	Using delete_all_rows
+1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	5	NULL	Deleting all rows
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	5	100.00	
 Warnings:
 Note	1003	select `test`.`t1`.`i` AS `i`,`test`.`t1`.`j` AS `j` from `test`.`t1`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	6
@@ -766,6 +1040,46 @@ Handler_read_rnd_next	6
 Variable_name	Value
 
 DROP TABLE t1;
+CREATE TABLE t1 (i INT, j INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);
+#
+# query:  DELETE FROM t1
+# select: SELECT * FROM t1
+#
+EXPLAIN DELETE FROM t1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	5	Deleting all rows
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED DELETE FROM t1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	5	NULL	Deleting all rows
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED SELECT * FROM t1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	5	100.00	
+Warnings:
+Note	1003	select `test`.`t1`.`i` AS `i`,`test`.`t1`.`j` AS `j` from `test`.`t1`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+# Status of "equivalent" SELECT query execution:
+Variable_name	Value
+Handler_read_first	1
+Handler_read_key	2
+Handler_read_rnd_next	6
+# Status of testing query execution:
+Variable_name	Value
+Handler_delete	5
+Handler_read_first	1
+Handler_read_key	2
+Handler_read_rnd_next	6
+
+DROP TABLE t1;
 CREATE TABLE t1 (i INT);
 INSERT INTO t1 VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19),
 (20),(21),(22),(23),(24),(25),(26),(27),(28),(29),
@@ -780,14 +1094,24 @@ INSERT INTO t2 (a, b, c) SELECT t1.i, t1
 EXPLAIN DELETE   FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	a	a	15	NULL	17602	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	a	a	15	NULL	17602	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	index	NULL	a	15	NULL	5	352040.00	Using where
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where (`test`.`t2`.`b` = 10) order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_first	1
@@ -809,14 +1133,24 @@ CREATE TABLE t2 (i INT);
 EXPLAIN INSERT INTO t2 SELECT * FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED INSERT INTO t2 SELECT * FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	
 Warnings:
 Note	1003	select `test`.`t1`.`i` AS `i` from `test`.`t1`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	4
@@ -836,14 +1170,24 @@ CREATE TABLE t2 (i INT);
 EXPLAIN REPLACE INTO t2 SELECT * FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED REPLACE INTO t2 SELECT * FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	
 Warnings:
 Note	1003	select `test`.`t1`.`i` AS `i` from `test`.`t1`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	4
@@ -861,9 +1205,14 @@ CREATE TABLE t1 (i INT);
 EXPLAIN INSERT INTO t1 SET i = 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED INSERT INTO t1 SET i = 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of testing query execution:
 Variable_name	Value
 Handler_write	1
@@ -877,9 +1226,14 @@ CREATE TABLE t1 (i INT);
 EXPLAIN REPLACE INTO t1 SET i = 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED REPLACE INTO t1 SET i = 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of testing query execution:
 Variable_name	Value
 Handler_write	1
@@ -896,14 +1250,24 @@ INSERT INTO t1 (i) VALUES (10),(11),(12)
 EXPLAIN DELETE   FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	8	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	8	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	8	100.00	Using index condition
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`i` AS `i` from `test`.`t1` where ((`test`.`t1`.`i` > 10) and (`test`.`t1`.`i` <= 18)) order by `test`.`t1`.`i` limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_key	1
@@ -926,12 +1290,19 @@ INSERT INTO t1 (i) VALUES (10),(11),(12)
 EXPLAIN DELETE   FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ALL	i	NULL	NULL	NULL	26	Using where; Using filesort
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	i	NULL	NULL	NULL	26	100.00	Using where; Using filesort
 Warnings:
 Warning	1713	Cannot use range access on index 'i' due to type or collation conversion on field 'i'
 Warning	1713	Cannot use range access on index 'i' due to type or collation conversion on field 'i'
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	i	NULL	NULL	NULL	26	100.00	Using where; Using filesort
@@ -941,6 +1312,9 @@ Warning	1713	Cannot use range access on
 Warning	1713	Cannot use range access on index 'i' due to type or collation conversion on field 'i'
 Warning	1713	Cannot use range access on index 'i' due to type or collation conversion on field 'i'
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`i` AS `i` from `test`.`t1` where ((`test`.`t1`.`i` > 10) and (`test`.`t1`.`i` <= 18)) order by `test`.`t1`.`i` limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	27
@@ -968,14 +1342,24 @@ INSERT INTO t2 (a, b, c) SELECT i, i, i
 EXPLAIN DELETE   FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	Using where; Using filesort
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	100.00	Using where; Using filesort
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	26	100.00	Using where; Using filesort
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where (`test`.`t2`.`b` = 10) order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	27
@@ -1004,14 +1388,24 @@ INSERT INTO t2 (a, b, c) SELECT t1.i, t1
 EXPLAIN DELETE   FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	a	a	15	NULL	17602	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	a	a	15	NULL	17602	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	index	NULL	a	15	NULL	5	352040.00	Using where
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where (`test`.`t2`.`b` = 10) order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_first	1
@@ -1036,16 +1430,26 @@ INSERT INTO t2 SELECT i, i, i, i FROM t1
 EXPLAIN DELETE   FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	Using where; Using filesort
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	100.00	Using where; Using filesort
 Warnings:
 Warning	1713	Cannot use range access on index 'a' due to type or collation conversion on field 'b'
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	26	100.00	Using where; Using filesort
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where (`test`.`t2`.`b` = 10) order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	27
@@ -1074,16 +1478,26 @@ INSERT INTO t2 SELECT i, i, i, i FROM t1
 EXPLAIN DELETE   FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	Using where; Using filesort
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	100.00	Using where; Using filesort
 Warnings:
 Warning	1713	Cannot use range access on index 'a' due to type or collation conversion on field 'b'
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	26	100.00	Using where; Using filesort
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where (`test`.`t2`.`b` = 10) order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd	1
@@ -1113,14 +1527,24 @@ INSERT INTO t2 (key1, key2) SELECT i, i
 EXPLAIN DELETE   FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	index_merge	key1,key2	key1,key2	5,5	NULL	7	Using sort_union(key1,key2); Using where; Using filesort
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	index_merge	key1,key2	key1,key2	5,5	NULL	7	100.00	Using sort_union(key1,key2); Using where; Using filesort
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	index_merge	key1,key2	key1,key2	5,5	NULL	7	100.00	Using sort_union(key1,key2); Using where; Using filesort
 Warnings:
 Note	1003	select `test`.`t2`.`i` AS `i`,`test`.`t2`.`key1` AS `key1`,`test`.`t2`.`key2` AS `key2` from `test`.`t2` where ((`test`.`t2`.`key1` < 13) or (`test`.`t2`.`key2` < 14)) order by `test`.`t2`.`key1`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_key	2
@@ -1151,14 +1575,24 @@ INSERT INTO t2 (i) SELECT i FROM t1;
 EXPLAIN DELETE   FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	range	PRIMARY	PRIMARY	4	NULL	8	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	range	PRIMARY	PRIMARY	4	NULL	8	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	range	PRIMARY	PRIMARY	4	NULL	8	100.00	Using index condition
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where ((`test`.`t2`.`i` > 10) and (`test`.`t2`.`i` <= 18)) order by `test`.`t2`.`i` desc limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_key	1
@@ -1183,14 +1617,24 @@ INSERT INTO t2 SELECT i, i, i FROM t1;
 EXPLAIN DELETE   FROM t2 ORDER BY a, b DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	Using filesort
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t2 ORDER BY a, b DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	100.00	Using filesort
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2 ORDER BY a, b DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	26	100.00	Using filesort
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` order by `test`.`t2`.`a`,`test`.`t2`.`b` desc limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	27
@@ -1219,14 +1663,24 @@ INSERT INTO t2 (a, b) SELECT t1.i, t1.i
 EXPLAIN DELETE   FROM t2 ORDER BY a DESC, b DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	a	a	6	NULL	5	
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t2 ORDER BY a DESC, b DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	a	a	6	NULL	5	100.00	
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2 ORDER BY a DESC, b DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	index	NULL	a	6	NULL	5	352040.00	
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` order by `test`.`t2`.`a` desc,`test`.`t2`.`b` desc limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_last	1
@@ -1251,14 +1705,24 @@ INSERT INTO t2 (i) SELECT i FROM t1;
 EXPLAIN UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	range	PRIMARY	PRIMARY	4	NULL	8	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	range	PRIMARY	PRIMARY	4	NULL	8	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM  t2    WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	range	PRIMARY	PRIMARY	4	NULL	8	100.00	Using index condition
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where ((`test`.`t2`.`i` > 10) and (`test`.`t2`.`i` <= 18)) order by `test`.`t2`.`i` limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_key	1
@@ -1284,12 +1748,19 @@ INSERT INTO t2 (i) SELECT i FROM t1;
 EXPLAIN UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	i	NULL	NULL	NULL	26	Using where; Using filesort
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	i	NULL	NULL	NULL	26	100.00	Using where; Using filesort
 Warnings:
 Warning	1713	Cannot use range access on index 'i' due to type or collation conversion on field 'i'
 Warning	1713	Cannot use range access on index 'i' due to type or collation conversion on field 'i'
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2     WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	i	NULL	NULL	NULL	26	100.00	Using where; Using filesort
@@ -1299,6 +1770,9 @@ Warning	1713	Cannot use range access on
 Warning	1713	Cannot use range access on index 'i' due to type or collation conversion on field 'i'
 Warning	1713	Cannot use range access on index 'i' due to type or collation conversion on field 'i'
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where ((`test`.`t2`.`i` > 10) and (`test`.`t2`.`i` <= 18)) order by `test`.`t2`.`i` limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	27
@@ -1326,14 +1800,24 @@ INSERT INTO t2 (a, b, c) SELECT i, i, i
 EXPLAIN UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	Using where; Using filesort
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	100.00	Using where; Using filesort
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2     WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	26	100.00	Using where; Using filesort
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where (`test`.`t2`.`b` = 10) order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	27
@@ -1362,14 +1846,24 @@ INSERT INTO t2 (a, b, c) SELECT t1.i, t1
 EXPLAIN UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	a	a	15	NULL	17602	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	a	a	15	NULL	17602	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2     WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	index	NULL	a	15	NULL	5	352040.00	Using where
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where (`test`.`t2`.`b` = 10) order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_first	1
@@ -1395,16 +1889,26 @@ INSERT INTO t2 SELECT i, i, i, i FROM t1
 EXPLAIN UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	Using where; Using filesort
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	100.00	Using where; Using filesort
 Warnings:
 Warning	1713	Cannot use range access on index 'a' due to type or collation conversion on field 'b'
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2     WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	26	100.00	Using where; Using filesort
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where (`test`.`t2`.`b` = 10) order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	27
@@ -1432,16 +1936,26 @@ INSERT INTO t2 SELECT i, i, i, i FROM t1
 EXPLAIN UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	Using where; Using filesort
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	100.00	Using where; Using filesort
 Warnings:
 Warning	1713	Cannot use range access on index 'a' due to type or collation conversion on field 'b'
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2     WHERE b = 10 ORDER BY a, c LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	26	100.00	Using where; Using filesort
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where (`test`.`t2`.`b` = 10) order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd	1
@@ -1470,14 +1984,24 @@ INSERT INTO t2 (key1, key2) SELECT i, i
 EXPLAIN UPDATE t2 SET i = 123 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	index_merge	key1,key2	key1,key2	5,5	NULL	7	Using sort_union(key1,key2); Using where; Using filesort
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t2 SET i = 123 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	index_merge	key1,key2	key1,key2	5,5	NULL	7	100.00	Using sort_union(key1,key2); Using where; Using filesort
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2      WHERE key1 < 13 or key2 < 14 ORDER BY key1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	index_merge	key1,key2	key1,key2	5,5	NULL	7	100.00	Using sort_union(key1,key2); Using where; Using filesort
 Warnings:
 Note	1003	select `test`.`t2`.`i` AS `i`,`test`.`t2`.`key1` AS `key1`,`test`.`t2`.`key2` AS `key2` from `test`.`t2` where ((`test`.`t2`.`key1` < 13) or (`test`.`t2`.`key2` < 14)) order by `test`.`t2`.`key1`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_key	2
@@ -1508,14 +2032,24 @@ INSERT INTO t2 (i) SELECT i FROM t1;
 EXPLAIN UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	range	PRIMARY	PRIMARY	4	NULL	8	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	range	PRIMARY	PRIMARY	4	NULL	8	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2     WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	range	PRIMARY	PRIMARY	4	NULL	8	100.00	Using index condition
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where ((`test`.`t2`.`i` > 10) and (`test`.`t2`.`i` <= 18)) order by `test`.`t2`.`i` desc limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_key	1
@@ -1541,14 +2075,24 @@ INSERT INTO t2 SELECT i, i, i FROM t1;
 EXPLAIN UPDATE t2 SET c = 10 ORDER BY a, b DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	Using filesort
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t2 SET c = 10 ORDER BY a, b DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	a	NULL	NULL	NULL	26	100.00	Using filesort
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2     ORDER BY a, b DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	26	100.00	Using filesort
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` order by `test`.`t2`.`a`,`test`.`t2`.`b` desc limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_rnd_next	27
@@ -1577,14 +2121,24 @@ INSERT INTO t2 (a, b) SELECT t1.i, t1.i
 EXPLAIN UPDATE t2 SET c = 10 ORDER BY a DESC, b DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ALL	a	a	6	NULL	5	
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t2 SET c = 10 ORDER BY a DESC, b DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	ALL	a	a	6	NULL	5	100.00	
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t2     ORDER BY a DESC, b DESC LIMIT 5;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	index	NULL	a	6	NULL	5	352040.00	
 Warnings:
 Note	1003	select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` order by `test`.`t2`.`a` desc,`test`.`t2`.`b` desc limit 5
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_last	1
@@ -1612,14 +2166,26 @@ INSERT INTO t1 VALUES (1,'y',1), (2,'n',
 EXPLAIN UPDATE t1 SET c2 = 0 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	range	PRIMARY,c1_idx	c1_idx	2	NULL	2	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t1 SET c2 = 0 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	range	PRIMARY,c1_idx	c1_idx	2	NULL	2	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_key	3
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1     WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ref	c1_idx	c1_idx	2	const	2	100.00	Using index condition; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1_idx` AS `c1_idx`,`test`.`t1`.`c2` AS `c2` from `test`.`t1` where (`test`.`t1`.`c1_idx` = 'y') order by `test`.`t1`.`pk` desc limit 2
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_key	3
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_key	5
@@ -1638,14 +2204,26 @@ Handler_update	2
 EXPLAIN DELETE   FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	range	PRIMARY,c1_idx	c1_idx	2	NULL	2	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED DELETE   FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	range	PRIMARY,c1_idx	c1_idx	2	NULL	2	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_key	3
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ref	c1_idx	c1_idx	2	const	2	100.00	Using index condition; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1_idx` AS `c1_idx`,`test`.`t1`.`c2` AS `c2` from `test`.`t1` where (`test`.`t1`.`c1_idx` = 'y') order by `test`.`t1`.`pk` desc limit 2
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_key	3
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_key	5
@@ -1666,14 +2244,24 @@ INSERT INTO t1 VALUES (),(),(),(),(),(),
 EXPLAIN UPDATE t1 SET a=a+10 WHERE a > 34;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	3	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t1 SET a=a+10 WHERE a > 34;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	3	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1     WHERE a > 34;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	3	100.00	Using where; Using index
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > 34)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_key	1
@@ -1697,16 +2285,30 @@ EXPLAIN UPDATE        t1 LEFT JOIN t2 ON
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	system	NULL	NULL	NULL	NULL	0	const row not found
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE        t1 LEFT JOIN t2 ON t1.c1 = t2.c1 SET t2.c2 = 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	system	NULL	NULL	NULL	NULL	0	0.00	const row not found
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_first	1
+Handler_read_rnd_next	1
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	system	NULL	NULL	NULL	NULL	0	0.00	const row not found
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	
 Warnings:
 Note	1003	select `test`.`t1`.`c1` AS `c1`,`test`.`t1`.`c2` AS `c2`,`test`.`t1`.`c3` AS `c3`,NULL AS `c1`,NULL AS `c2` from `test`.`t1`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_first	1
+Handler_read_rnd_next	1
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_first	1
@@ -1724,16 +2326,30 @@ EXPLAIN UPDATE        t1 LEFT JOIN t2 ON
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	system	NULL	NULL	NULL	NULL	0	const row not found
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	Using where
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE        t1 LEFT JOIN t2 ON t1.c1 = t2.c1 SET t2.c2 = 10 WHERE t1.c3 = 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	system	NULL	NULL	NULL	NULL	0	0.00	const row not found
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_first	1
+Handler_read_rnd_next	1
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT * FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1                WHERE t1.c3 = 10;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t2	system	NULL	NULL	NULL	NULL	0	0.00	const row not found
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
 Note	1003	select `test`.`t1`.`c1` AS `c1`,`test`.`t1`.`c2` AS `c2`,`test`.`t1`.`c3` AS `c3`,NULL AS `c1`,NULL AS `c2` from `test`.`t1` where (`test`.`t1`.`c3` = 10)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_first	1
+Handler_read_rnd_next	1
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_first	1
@@ -1757,12 +2373,19 @@ EXPLAIN UPDATE t1 SET t1.f2=(SELECT MAX(
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	
 2	DEPENDENT SUBQUERY	t2	ref	IDX	IDX	5	test.t1.f1	2	
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED UPDATE t1 SET t1.f2=(SELECT MAX(t2.f4) FROM t2 WHERE t2.f3=t1.f1);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	
 2	DEPENDENT SUBQUERY	t2	ref	IDX	IDX	5	test.t1.f1	2	100.00	
 Warnings:
 Note	1276	Field or reference 'test.t1.f1' of SELECT #2 was resolved in SELECT #1
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
 EXPLAIN EXTENDED SELECT              (SELECT MAX(t2.f4) FROM t2 WHERE t2.f3=t1.f1) FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	
@@ -1770,6 +2393,9 @@ id	select_type	table	type	possible_keys
 Warnings:
 Note	1276	Field or reference 'test.t1.f1' of SELECT #2 was resolved in SELECT #1
 Note	1003	select (select max(`test`.`t2`.`f4`) from `test`.`t2` where (`test`.`t2`.`f3` = `test`.`t1`.`f1`)) AS `(SELECT MAX(t2.f4) FROM t2 WHERE t2.f3=t1.f1)` from `test`.`t1`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
 # Status of "equivalent" SELECT query execution:
 Variable_name	Value
 Handler_read_key	2
@@ -1814,3 +2440,318 @@ ERROR HY000: You are using safe update m
 SET SESSION sql_safe_updates = DEFAULT;
 DROP TABLE t1;
 DROP VIEW v1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (0), (1);
+CREATE VIEW v1 AS SELECT t11.a, t12.a AS b FROM t1 t11, t1 t12;
+#
+# query:  UPDATE        v1 SET a = 1 WHERE a > 0
+# select: SELECT * FROM v1           WHERE a > 0
+#
+EXPLAIN UPDATE        v1 SET a = 1 WHERE a > 0;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t11	ALL	NULL	NULL	NULL	NULL	2	Using where
+1	SIMPLE	t12	ALL	NULL	NULL	NULL	NULL	2	Using join buffer (BNL, incremental buffers)
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED UPDATE        v1 SET a = 1 WHERE a > 0;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t11	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
+1	SIMPLE	t12	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer (BNL, incremental buffers)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED SELECT * FROM v1           WHERE a > 0;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t11	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
+1	SIMPLE	t12	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer (BNL, incremental buffers)
+Warnings:
+Note	1003	select `test`.`t11`.`a` AS `a`,`test`.`t12`.`a` AS `b` from `test`.`t1` `t11` join `test`.`t1` `t12` where (`test`.`t11`.`a` > 0)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+# Status of "equivalent" SELECT query execution:
+Variable_name	Value
+Handler_read_rnd_next	6
+# Status of testing query execution:
+Variable_name	Value
+Handler_read_rnd	1
+Handler_read_rnd_next	9
+Handler_write	2
+
+#
+# query:  UPDATE        t1, v1 SET v1.a = 1 WHERE t1.a = v1.a
+# select: SELECT * FROM t1, v1              WHERE t1.a = v1.a
+#
+EXPLAIN UPDATE        t1, v1 SET v1.a = 1 WHERE t1.a = v1.a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t11	ALL	NULL	NULL	NULL	NULL	2	Using where; Using join buffer (BNL, incremental buffers)
+1	SIMPLE	t12	ALL	NULL	NULL	NULL	NULL	2	Using join buffer (BNL, incremental buffers)
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED UPDATE        t1, v1 SET v1.a = 1 WHERE t1.a = v1.a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	
+1	SIMPLE	t11	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where; Using join buffer (BNL, incremental buffers)
+1	SIMPLE	t12	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer (BNL, incremental buffers)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED SELECT * FROM t1, v1              WHERE t1.a = v1.a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	
+1	SIMPLE	t11	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where; Using join buffer (BNL, incremental buffers)
+1	SIMPLE	t12	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer (BNL, incremental buffers)
+Warnings:
+Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t11`.`a` AS `a`,`test`.`t12`.`a` AS `b` from `test`.`t1` join `test`.`t1` `t11` join `test`.`t1` `t12` where (`test`.`t11`.`a` = `test`.`t1`.`a`)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+# Status of "equivalent" SELECT query execution:
+Variable_name	Value
+Handler_read_rnd_next	9
+# Status of testing query execution:
+Variable_name	Value
+Handler_read_rnd	2
+Handler_read_rnd_next	19
+Handler_update	1
+Handler_write	4
+
+DROP TABLE t1;
+DROP VIEW v1;
+CREATE TABLE t1 (a INT, PRIMARY KEY(a));
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+CREATE VIEW v1 (a) AS SELECT a FROM t1;
+#
+# query:  DELETE   FROM v1 WHERE a < 4
+# select: SELECT * FROM v1 WHERE a < 4
+#
+EXPLAIN DELETE   FROM v1 WHERE a < 4;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	3	Using where
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED DELETE   FROM v1 WHERE a < 4;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	3	100.00	Using where
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED SELECT * FROM v1 WHERE a < 4;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	3	100.00	Using where; Using index
+Warnings:
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` < 4)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+# Status of "equivalent" SELECT query execution:
+Variable_name	Value
+Handler_read_first	1
+Handler_read_next	3
+# Status of testing query execution:
+Variable_name	Value
+Handler_delete	3
+Handler_read_first	1
+Handler_read_next	3
+
+DROP TABLE t1;
+DROP VIEW v1;
+CREATE TABLE t1 (a INT, b INT, PRIMARY KEY(a));
+INSERT INTO t1 VALUES (1,2), (2,3), (3,4), (4,5), (5,10);
+CREATE TABLE t2 (x INT);
+INSERT INTO t2 VALUES (1), (2), (3), (4);
+CREATE VIEW v1 (a,c) AS SELECT a, b+1 FROM t1;
+#
+# query:  DELETE v1 FROM t2, v1 WHERE t2.x = v1.a
+# select: SELECT *  FROM t2, v1 WHERE t2.x = v1.a
+#
+EXPLAIN DELETE v1 FROM t2, v1 WHERE t2.x = v1.a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	4	Using where
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t2.x	1	
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED DELETE v1 FROM t2, v1 WHERE t2.x = v1.a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	4	100.00	Using where
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t2.x	1	100.00	
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED SELECT *  FROM t2, v1 WHERE t2.x = v1.a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	4	100.00	Using where
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t2.x	1	100.00	
+Warnings:
+Note	1003	select `test`.`t2`.`x` AS `x`,`test`.`t1`.`a` AS `a`,(`test`.`t1`.`b` + 1) AS `c` from `test`.`t2` join `test`.`t1` where (`test`.`t1`.`a` = `test`.`t2`.`x`)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+# Status of "equivalent" SELECT query execution:
+Variable_name	Value
+Handler_read_key	4
+Handler_read_rnd_next	5
+# Status of testing query execution:
+Variable_name	Value
+Handler_delete	4
+Handler_read_key	4
+Handler_read_rnd	4
+Handler_read_rnd_next	5
+
+DROP TABLE t1,t2;
+DROP VIEW v1;
+CREATE TABLE t1 (a INT, b INT, PRIMARY KEY(a));
+INSERT INTO t1 VALUES (1,2), (2,3), (3,4), (4,5), (5,10);
+CREATE TABLE t2 (x INT);
+INSERT INTO t2 VALUES (1), (2), (3), (4);
+CREATE VIEW v1 (a,c) AS SELECT a, b+1 FROM t1;
+#
+# query:  DELETE v1 FROM t2, v1 WHERE t2.x = v1.a
+# select: SELECT *  FROM t2, v1 WHERE t2.x = v1.a
+#
+EXPLAIN DELETE v1 FROM t2, v1 WHERE t2.x = v1.a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	4	Using where
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t2.x	1	
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED DELETE v1 FROM t2, v1 WHERE t2.x = v1.a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	4	100.00	Using where
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t2.x	1	100.00	
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED SELECT *  FROM t2, v1 WHERE t2.x = v1.a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	4	100.00	Using where
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t2.x	1	100.00	
+Warnings:
+Note	1003	select `test`.`t2`.`x` AS `x`,`test`.`t1`.`a` AS `a`,(`test`.`t1`.`b` + 1) AS `c` from `test`.`t2` join `test`.`t1` where (`test`.`t1`.`a` = `test`.`t2`.`x`)
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+# Status of "equivalent" SELECT query execution:
+Variable_name	Value
+Handler_read_key	4
+Handler_read_rnd_next	5
+# Status of testing query execution:
+Variable_name	Value
+Handler_delete	4
+Handler_read_key	4
+Handler_read_rnd	4
+Handler_read_rnd_next	5
+
+DROP TABLE t1,t2;
+DROP VIEW v1;
+CREATE TABLE t1 (a INT);
+CREATE VIEW v1 (x) AS SELECT a FROM t1;
+#
+# query:  INSERT INTO v1 VALUES (10)
+# select: SELECT NULL
+#
+EXPLAIN INSERT INTO v1 VALUES (10);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED INSERT INTO v1 VALUES (10);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED SELECT NULL;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+Warnings:
+Note	1003	select NULL AS `NULL`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+# Status of "equivalent" SELECT query execution:
+Variable_name	Value
+# Status of testing query execution:
+Variable_name	Value
+Handler_write	1
+
+DROP TABLE t1;
+DROP VIEW v1;
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (b INT);
+INSERT INTO t2 VALUES (1), (2), (3);
+CREATE VIEW v1 (x) AS SELECT b FROM t2;
+#
+# query:  INSERT INTO v1 SELECT * FROM t1
+# select: SELECT * FROM t1
+#
+EXPLAIN INSERT INTO v1 SELECT * FROM t1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	system	NULL	NULL	NULL	NULL	0	const row not found
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED INSERT INTO v1 SELECT * FROM t1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	system	NULL	NULL	NULL	NULL	0	0.00	const row not found
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_first	1
+Handler_read_rnd_next	1
+FLUSH STATUS;
+FLUSH TABLES;
+EXPLAIN EXTENDED SELECT * FROM t1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	system	NULL	NULL	NULL	NULL	0	0.00	const row not found
+Warnings:
+Note	1003	select NULL AS `a` from `test`.`t1`
+SHOW STATUS WHERE (Variable_name LIKE 'Sort%' OR
+Variable_name LIKE 'Handler_read_%') AND Value <> 0;
+Variable_name	Value
+Handler_read_first	1
+Handler_read_rnd_next	1
+# Status of "equivalent" SELECT query execution:
+Variable_name	Value
+Handler_read_first	1
+Handler_read_rnd_next	1
+# Status of testing query execution:
+Variable_name	Value
+Handler_read_first	1
+Handler_read_rnd_next	1
+
+DROP TABLE t1, t2;
+DROP VIEW v1;
+CREATE DATABASE grant_db;
+CREATE TABLE grant_db.t1 (a INT);
+CREATE VIEW grant_db.v1 (x) AS SELECT a FROM grant_db.t1;
+GRANT  ALL    ON grant_db.* TO   'granttest'@localhost;
+REVOKE SELECT ON grant_db.* FROM 'granttest'@localhost;
+USE grant_db;
+EXPLAIN INSERT INTO v1 SELECT * FROM v1;
+ERROR 42000: SELECT command denied to user 'granttest'@'localhost' for table 'v1'
+EXPLAIN REPLACE INTO v1 SELECT * FROM v1;
+ERROR 42000: SELECT command denied to user 'granttest'@'localhost' for table 'v1'
+EXPLAIN UPDATE t1 SET t1.a = 10 WHERE t1.a IN (SELECT a FROM v1);
+ERROR 42000: SELECT command denied to user 'granttest'@'localhost' for table 'v1'
+EXPLAIN UPDATE t1 t11, (SELECT * FROM v1) t12 SET t11.a = 10 WHERE t11.a = 1;
+ERROR 42000: SELECT command denied to user 'granttest'@'localhost' for table 'v1'
+EXPLAIN DELETE FROM t1 WHERE t1.a IN (SELECT a FROM v1);
+ERROR 42000: SELECT command denied to user 'granttest'@'localhost' for table 'v1'
+EXPLAIN DELETE FROM t1 USING t1 WHERE t1.a IN (SELECT a FROM v1);
+ERROR 42000: SELECT command denied to user 'granttest'@'localhost' for table 't1'
+DROP USER 'granttest'@localhost;
+USE test;
+DROP DATABASE grant_db;

=== modified file 'mysql-test/r/func_gconcat.result'
--- a/mysql-test/r/func_gconcat.result	2011-03-08 19:14:42 +0000
+++ b/mysql-test/r/func_gconcat.result	2011-05-25 14:16:06 +0000
@@ -993,7 +993,7 @@ EXPLAIN EXTENDED SELECT 1 FROM
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	<derived2>	system	NULL	NULL	NULL	NULL	1	100.00	
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	
-2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort; Distinct
+2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using filesort; Using temporary; Distinct
 2	DERIVED	td	ALL	NULL	NULL	NULL	NULL	2	100.00	Distinct; Using join buffer (BNL, incremental buffers)
 Warnings:
 Note	1003	select 1 AS `1` from `test`.`t1`
@@ -1014,7 +1014,7 @@ EXPLAIN EXTENDED SELECT 1 FROM
 t1 t2, t1 GROUP BY t1.a) AS d;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	<derived2>	system	NULL	NULL	NULL	NULL	1	100.00	
-2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
+2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using filesort; Using temporary
 2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer (BNL, incremental buffers)
 Warnings:
 Note	1003	select 1 AS `1` from dual

=== modified file 'mysql-test/r/key.result'
--- a/mysql-test/r/key.result	2010-08-30 06:38:09 +0000
+++ b/mysql-test/r/key.result	2011-05-25 14:16:06 +0000
@@ -607,13 +607,13 @@ CREATE TABLE t1( a INT, b INT, KEY( a )
 INSERT INTO t1 values (1, 2), (1, 3), (2, 3), (2, 4), (3, 4), (3, 5);
 EXPLAIN SELECT a, SUM( b ) FROM t1 GROUP BY a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	6	Using temporary; Using filesort
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	6	Using filesort; Using temporary
 SHOW STATUS LIKE 'Last_query_cost';
 Variable_name	Value
 Last_query_cost	9.212184
 EXPLAIN SELECT a, SUM( b ) FROM t1 USE INDEX( a ) GROUP BY a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	6	Using temporary; Using filesort
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	6	Using filesort; Using temporary
 SHOW STATUS LIKE 'Last_query_cost';
 Variable_name	Value
 Last_query_cost	9.212184

=== modified file 'mysql-test/r/optimizer_switch.result'
--- a/mysql-test/r/optimizer_switch.result	2011-01-24 14:17:03 +0000
+++ b/mysql-test/r/optimizer_switch.result	2011-05-25 14:16:06 +0000
@@ -281,7 +281,7 @@ HAVING ta.a=tc.f));
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	ta	ALL	NULL	NULL	NULL	NULL	7	Using where
 2	DEPENDENT SUBQUERY	tb	ALL	NULL	NULL	NULL	NULL	6	Using where
-3	DEPENDENT SUBQUERY	tc	ALL	NULL	NULL	NULL	NULL	6	Using temporary; Using filesort
+3	DEPENDENT SUBQUERY	tc	ALL	NULL	NULL	NULL	NULL	6	Using filesort; Using temporary
 SELECT * FROM t1 AS ta
 WHERE ta.a IN (SELECT c FROM t2 AS tb
 WHERE tb.d >= SOME(SELECT SUM(g) FROM t4 as tc
@@ -301,7 +301,7 @@ HAVING ta.a=tc.f));
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	tb	ALL	NULL	NULL	NULL	NULL	6	Start temporary
 1	PRIMARY	ta	ALL	NULL	NULL	NULL	NULL	7	Using where; End temporary; Using join buffer (BNL, incremental buffers)
-3	DEPENDENT SUBQUERY	tc	ALL	NULL	NULL	NULL	NULL	6	Using temporary; Using filesort
+3	DEPENDENT SUBQUERY	tc	ALL	NULL	NULL	NULL	NULL	6	Using filesort; Using temporary
 SELECT * FROM t1 AS ta
 WHERE ta.a IN (SELECT c FROM t2 AS tb
 WHERE tb.d >= SOME(SELECT SUM(g) FROM t4 as tc

=== modified file 'mysql-test/r/udf.result'
--- a/mysql-test/r/udf.result	2011-02-09 10:19:05 +0000
+++ b/mysql-test/r/udf.result	2011-05-25 14:16:06 +0000
@@ -101,7 +101,7 @@ create table t1(f1 int);
 insert into t1 values(1),(2);
 explain select myfunc_int(f1) from t1 order by 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	Using temporary; Using filesort
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	Using filesort; Using temporary
 drop table t1;
 CREATE TABLE t1(a INT, b INT);
 INSERT INTO t1 values (1,1),(2,2);
@@ -145,22 +145,22 @@ c
 2
 EXPLAIN EXTENDED SELECT myfunc_int(MIN(b) xx) as c FROM t1 GROUP BY a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
-1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using filesort; Using temporary
 Warnings:
 Note	1003	select myfunc_int(min(`test`.`t1`.`b`) AS `xx`) AS `c` from `test`.`t1` group by `test`.`t1`.`a`
 EXPLAIN EXTENDED SELECT test.fn(MIN(b)) as c FROM t1 GROUP BY a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
-1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using filesort; Using temporary
 Warnings:
 Note	1003	select `test`.`fn`(min(`test`.`t1`.`b`)) AS `c` from `test`.`t1` group by `test`.`t1`.`a`
 EXPLAIN EXTENDED SELECT myfunc_int(fn(MIN(b))) as c FROM t1 GROUP BY a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
-1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using filesort; Using temporary
 Warnings:
 Note	1003	select myfunc_int(`fn`(min(`test`.`t1`.`b`)) AS `fn(MIN(b))`) AS `c` from `test`.`t1` group by `test`.`t1`.`a`
 EXPLAIN EXTENDED SELECT myfunc_int(test.fn(MIN(b))) as c FROM t1 GROUP BY a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
-1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using filesort; Using temporary
 Warnings:
 Note	1003	select myfunc_int(`test`.`fn`(min(`test`.`t1`.`b`)) AS `test.fn(MIN(b))`) AS `c` from `test`.`t1` group by `test`.`t1`.`a`
 SELECT myfunc_int(MIN(b) xx) as c FROM t1 GROUP BY a;

=== modified file 'mysql-test/t/explain_non_select.test'
--- a/mysql-test/t/explain_non_select.test	2011-03-30 16:48:25 +0000
+++ b/mysql-test/t/explain_non_select.test	2011-05-25 14:16:06 +0000
@@ -1,3 +1,13 @@
+-- source include/have_innodb.inc
+
+# Grant tests not performed with embedded server
+-- source include/not_embedded.inc
+
+# Save the initial number of concurrent sessions
+--source include/count_sessions.inc
+
+SET SESSION DEFAULT_STORAGE_ENGINE = MyISAM;
+
 CREATE TABLE t1 (a INT);
 INSERT INTO t1 VALUES (1), (2), (3);
 --let $query =  UPDATE t1 SET a = 10 WHERE a < 10
@@ -196,7 +206,14 @@ INSERT INTO t1 VALUES (1, 1), (2, 2), (3
 --source include/explain_non_select.inc
 DROP TABLE t1;
 
-CREATE TABLE t1 (i INT, j INT);
+CREATE TABLE t1 (i INT, j INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);
+--let $query =  DELETE FROM t1
+--let $select = SELECT * FROM t1
+--source include/explain_non_select.inc
+DROP TABLE t1;
+
+CREATE TABLE t1 (i INT, j INT) ENGINE=InnoDB;
 INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);
 --let $query =  DELETE FROM t1
 --let $select = SELECT * FROM t1
@@ -536,6 +553,8 @@ EXPLAIN EXTENDED UPDATE t1 SET f2=1 ORDE
 UPDATE t1 SET f2=1 ORDER BY f2;
 DROP TABLE t1;
 
+# views
+
 CREATE TABLE t1 ( a INT, KEY( a ) );
 INSERT INTO t1 VALUES (0), (1);
 CREATE VIEW v1 AS SELECT t11.a, t12.a AS b FROM t1 t11, t1 t12;
@@ -548,3 +567,102 @@ SET SESSION sql_safe_updates = DEFAULT;
 DROP TABLE t1;
 DROP VIEW v1;
 
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (0), (1);
+CREATE VIEW v1 AS SELECT t11.a, t12.a AS b FROM t1 t11, t1 t12;
+--let $query =  UPDATE        v1 SET a = 1 WHERE a > 0
+--let $select = SELECT * FROM v1           WHERE a > 0
+--source include/explain_non_select.inc
+--let $query =  UPDATE        t1, v1 SET v1.a = 1 WHERE t1.a = v1.a
+--let $select = SELECT * FROM t1, v1              WHERE t1.a = v1.a
+--source include/explain_non_select.inc
+DROP TABLE t1;
+DROP VIEW v1;
+
+CREATE TABLE t1 (a INT, PRIMARY KEY(a));
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+CREATE VIEW v1 (a) AS SELECT a FROM t1;
+--let $query =  DELETE   FROM v1 WHERE a < 4
+--let $select = SELECT * FROM v1 WHERE a < 4
+--source include/explain_non_select.inc
+DROP TABLE t1;
+DROP VIEW v1;
+
+CREATE TABLE t1 (a INT, b INT, PRIMARY KEY(a));
+INSERT INTO t1 VALUES (1,2), (2,3), (3,4), (4,5), (5,10);
+CREATE TABLE t2 (x INT);
+INSERT INTO t2 VALUES (1), (2), (3), (4);
+CREATE VIEW v1 (a,c) AS SELECT a, b+1 FROM t1;
+--let $query =  DELETE v1 FROM t2, v1 WHERE t2.x = v1.a
+--let $select = SELECT *  FROM t2, v1 WHERE t2.x = v1.a
+--source include/explain_non_select.inc
+DROP TABLE t1,t2;
+DROP VIEW v1;
+
+CREATE TABLE t1 (a INT, b INT, PRIMARY KEY(a));
+INSERT INTO t1 VALUES (1,2), (2,3), (3,4), (4,5), (5,10);
+CREATE TABLE t2 (x INT);
+INSERT INTO t2 VALUES (1), (2), (3), (4);
+CREATE VIEW v1 (a,c) AS SELECT a, b+1 FROM t1;
+--let $query =  DELETE v1 FROM t2, v1 WHERE t2.x = v1.a
+--let $select = SELECT *  FROM t2, v1 WHERE t2.x = v1.a
+--source include/explain_non_select.inc
+DROP TABLE t1,t2;
+DROP VIEW v1;
+
+CREATE TABLE t1 (a INT);
+CREATE VIEW v1 (x) AS SELECT a FROM t1;
+--let $query =  INSERT INTO v1 VALUES (10)
+--let $select = SELECT NULL
+--source include/explain_non_select.inc
+DROP TABLE t1;
+DROP VIEW v1;
+
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (b INT);
+INSERT INTO t2 VALUES (1), (2), (3);
+CREATE VIEW v1 (x) AS SELECT b FROM t2;
+--let $query =  INSERT INTO v1 SELECT * FROM t1
+--let $select =                SELECT * FROM t1
+--source include/explain_non_select.inc
+DROP TABLE t1, t2;
+DROP VIEW v1;
+
+#
+# Grants
+#
+
+CREATE DATABASE grant_db;
+
+CREATE TABLE grant_db.t1 (a INT);
+CREATE VIEW grant_db.v1 (x) AS SELECT a FROM grant_db.t1;
+
+GRANT  ALL    ON grant_db.* TO   'granttest'@localhost;
+REVOKE SELECT ON grant_db.* FROM 'granttest'@localhost;
+
+connect(con1,localhost,granttest,,);
+connection con1;
+
+USE grant_db;
+
+--error ER_TABLEACCESS_DENIED_ERROR
+EXPLAIN INSERT INTO v1 SELECT * FROM v1;
+--error ER_TABLEACCESS_DENIED_ERROR
+EXPLAIN REPLACE INTO v1 SELECT * FROM v1;
+--error ER_TABLEACCESS_DENIED_ERROR
+EXPLAIN UPDATE t1 SET t1.a = 10 WHERE t1.a IN (SELECT a FROM v1);
+--error ER_TABLEACCESS_DENIED_ERROR
+EXPLAIN UPDATE t1 t11, (SELECT * FROM v1) t12 SET t11.a = 10 WHERE t11.a = 1;
+--error ER_TABLEACCESS_DENIED_ERROR
+EXPLAIN DELETE FROM t1 WHERE t1.a IN (SELECT a FROM v1);
+--error ER_TABLEACCESS_DENIED_ERROR
+EXPLAIN DELETE FROM t1 USING t1 WHERE t1.a IN (SELECT a FROM v1);
+
+connection default;
+disconnect con1;
+
+DROP USER 'granttest'@localhost;
+USE test;
+DROP DATABASE grant_db;
+

=== modified file 'sql/opt_explain.cc'
--- a/sql/opt_explain.cc	2011-03-30 16:48:25 +0000
+++ b/sql/opt_explain.cc	2011-05-25 14:16:06 +0000
@@ -14,15 +14,16 @@
    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
 
 #include "opt_explain.h"
+#include "sql_select.h"
 #include "sql_partition.h" // for make_used_partitions_str()
 
+#define EMPTY_NAME ""
+
 
 /**
   A base for all Explain_* classes
 
-  This class hierarchy is a successor of the old select_describe() function
-  implementation. It extends old select_describe() functionality to deal with
-  single-table data-modifying commands (UPDATE and DELETE).
+  Explain_* classes collect and output EXPLAIN data.
 */
 
 class Explain
@@ -32,25 +33,64 @@ private:
   Item_null *nil; ///< pre-allocated NULL item to fill empty columns in EXPLAIN
 
 protected:
+  /**
+    Helper class to keep string data in memroot before passing to Item_string
+  */
+  struct memroot_str
+  {
+    const char *str;
+    size_t length;
+    
+    memroot_str() { cleanup(); }
+    void cleanup()
+    {
+      str= NULL;
+      length= 0;
+    }
+    bool nil() const { return str == NULL; }
+
+    bool set(THD *thd, const char *str_arg)
+    {
+      return set(thd, str_arg, strlen(str_arg));
+    }
+    bool set(THD *thd, const String &s)
+    {
+      return set(thd, s.ptr(), s.length());
+    }
+    bool set(THD *thd, const char *str_arg, size_t length_arg)
+    {
+      if (!(str= static_cast<char *>(alloc_root(thd->mem_root, length_arg))))
+        return true;
+      memcpy(const_cast<char *>(str), str_arg, length_arg);
+      length= length_arg;
+      return false;
+    }
+    void set_const(const char *str_arg)
+    {
+      str= str_arg;
+      length= strlen(str_arg);
+    }
+  };
+
   /*
     Next "col_*" fields are intended for the filling by "explain_*()" methods.
     Then the make_list() method links these Items into "items" list.
 
-    NOTE: NULL value means that Item_null object will be pushed into "items"
-          list instead.
+    NOTE: NULL value or memroot_str.nil()==true means that Item_null object
+          will be pushed into "items" list instead.
   */
   Item_uint   *col_id; ///< "id" column: seq. number of SELECT withing the query
-  Item_string *col_select_type; ///< "select_type" column
-  Item_string *col_table_name; ///< "table" to which the row of output refers
-  Item_string *col_partitions; ///< "partitions" column
-  Item_string *col_join_type; ///< "type" column, see join_type_str array
-  Item_string *col_possible_keys; ///< "possible_keys": comma-separated list
-  Item_string *col_key; ///< "key" column: index that is actually decided to use
-  Item_string *col_key_len; ///< "key_length" column: length of the "key" above
-  Item_string *col_ref; ///< "ref":columns/constants which are compared to "key"
+  memroot_str col_select_type; ///< "select_type" column
+  memroot_str col_table_name; ///< "table" to which the row of output refers
+  memroot_str col_partitions; ///< "partitions" column
+  memroot_str col_join_type; ///< "type" column, see join_type_str array
+  memroot_str col_possible_keys; ///< "possible_keys": comma-separated list
+  memroot_str col_key; ///< "key" column: index that is actually decided to use
+  memroot_str col_key_len; ///< "key_length" column: length of the "key" above
+  memroot_str col_ref; ///< "ref":columns/constants which are compared to "key"
   Item_int    *col_rows; ///< "rows": estimated number of examined table rows
   Item_float  *col_filtered; ///< "filtered": % of rows filtered by condition
-  Item_string *col_extra; ///< "extra" column: additional information
+  memroot_str col_extra; ///< "extra" column: additional information
 
   THD *thd; ///< cached THD pointer
   const CHARSET_INFO *cs; ///< cached pointer to system_charset_info
@@ -59,10 +99,9 @@ protected:
 
   select_result *external_result; ///< result stream (if any) provided by caller
 
-public:
-  explicit Explain(JOIN *join_arg= NULL)
+  explicit Explain(THD *thd_arg, JOIN *join_arg= NULL)
   : nil(NULL),
-    thd(current_thd),
+    thd(thd_arg),
     cs(system_charset_info),
     join(join_arg),
     select_lex(join ? join->select_lex : &thd->lex->select_lex),
@@ -72,12 +111,20 @@ public:
   }
   virtual ~Explain() {}
 
+public:
   bool send();
 
 private:
   void init_columns();
   bool make_list();
   bool push(Item *item) { return items.push_back(item ? item : nil); }
+  bool push(const memroot_str &s)
+  {
+    if (s.nil())
+      return items.push_back(nil);
+    Item_string *item= new Item_string(s.str, s.length, cs);
+    return item == NULL || items.push_back(item);
+  }
 
 protected:
   bool describe(uint8 mask) { return thd->lex->describe & mask; }
@@ -89,8 +136,8 @@ protected:
     select_send object. Then that JOIN object prepares the select_send
     object calling result->prepare() in JOIN::prepare(),
     result->initalize_tables() in JOIN::optimize() and result->prepare2()
-    in JOIN::exe().
-    However witout the presence of the top-level JOIN we have to
+    in JOIN::exec().
+    However without the presence of the top-level JOIN we have to
     prepare/initialize select_send object manually.
   */
   bool prepare(select_result *result)
@@ -104,22 +151,22 @@ protected:
   virtual bool send_to(select_result *to);
 
   /*
-    Rest of the methods are overloadable functions those calculate and fill
+    Rest of the methods are overloadable functions, those calculate and fill
     "col_*" fields with Items for further sending as EXPLAIN columns.
 
-    "explain_*" methods return FALSE on success and TRUE on error (usually OOM).
+    "explain_*" methods return false on success and true on error (usually OOM).
   */
   virtual bool explain_id();
   virtual bool explain_select_type();
-  virtual bool explain_table_name() { return FALSE; }
-  virtual bool explain_partitions() { return FALSE; }
-  virtual bool explain_join_type() { return FALSE; }
-  virtual bool explain_possible_keys() { return FALSE; }
-  /* fill col_key and and col_key_len fields together */
-  virtual bool explain_key_and_len() { return FALSE; }
-  virtual bool explain_ref() { return FALSE; }
-  /* fill col_rows and col_filtered fields together */
-  virtual bool explain_rows_and_filtered() { return FALSE; }
+  virtual bool explain_table_name() { return false; }
+  virtual bool explain_partitions() { return false; }
+  virtual bool explain_join_type() { return false; }
+  virtual bool explain_possible_keys() { return false; }
+  /** fill col_key and and col_key_len fields together */
+  virtual bool explain_key_and_len() { return false; }
+  virtual bool explain_ref() { return false; }
+  /** fill col_rows and col_filtered fields together */
+  virtual bool explain_rows_and_filtered() { return false; }
   virtual bool explain_extra();
 };
 
@@ -127,7 +174,6 @@ protected:
 /**
   Explain_msg class outputs a trivial EXPLAIN row with "extra" column
 
-  Fromer part of the old select_describe() function.
   This class is intended for simple cases to produce EXPLAIN output
   with "No tables used", "No matching records" etc.
   Optionally it can output number of estimated rows in the "row"
@@ -143,12 +189,12 @@ private:
   const ha_rows rows; ///< HA_POS_ERROR or cached "rows" argument
 
 public:
-  Explain_msg(JOIN *join_arg, const char *message_arg)
-  : Explain(join_arg), message(message_arg), rows(HA_POS_ERROR)
+  Explain_msg(THD *thd_arg, JOIN *join_arg, const char *message_arg)
+  : Explain(thd_arg, join_arg), message(message_arg), rows(HA_POS_ERROR)
   {}
-  
-  explicit Explain_msg(const char *message_arg, ha_rows rows_arg= HA_POS_ERROR)
-  : message(message_arg), rows(rows_arg)
+
+  explicit Explain_msg(THD *thd_arg, const char *message_arg, ha_rows rows_arg= HA_POS_ERROR)
+  : Explain(thd_arg), message(message_arg), rows(rows_arg)
   {}
 
 protected:
@@ -159,8 +205,6 @@ protected:
 
 /**
   Explain_union class outputs EXPLAIN row for UNION
-
-  Former part of the old select_describe() function.
 */
 
 class Explain_union : public Explain
@@ -169,7 +213,7 @@ private:
   char table_name_buffer[NAME_CHAR_LEN];
 
 public:
-  Explain_union(JOIN *join_arg) : Explain(join_arg)
+  Explain_union(THD *thd_arg, JOIN *join_arg) : Explain(thd_arg, join_arg)
   {
     /* it's a UNION: */
     DBUG_ASSERT(join_arg->select_lex == join_arg->unit->fake_select_lex);
@@ -186,8 +230,6 @@ protected:
 
 /**
   Common base class for Explain_join and Explain_table
-
-  Former part of the old select_describe() function.
 */
 
 class Explain_table_base : public Explain {
@@ -195,70 +237,147 @@ protected:
   TABLE *table;
   key_map usable_keys;
 
-  char buff_possible_keys[512];
-  String str_possible_keys;
-
-public:
-  explicit Explain_table_base(JOIN *join_arg)
-  : Explain(join_arg), table(NULL),
-    str_possible_keys(buff_possible_keys, sizeof(buff_possible_keys), cs)
+  Explain_table_base(THD *thd_arg, JOIN *join_arg)
+  : Explain(thd_arg, join_arg), table(NULL)
   {}
 
-  explicit Explain_table_base(TABLE *table_arg)
-  : table(table_arg),
-    str_possible_keys(buff_possible_keys, sizeof(buff_possible_keys), cs)
+  Explain_table_base(THD *thd_arg, TABLE *table_arg)
+  : Explain(thd_arg), table(table_arg)
   {}
 
-protected:
   virtual bool explain_partitions();
   virtual bool explain_possible_keys();
+
+  bool explain_key_and_len_quick(const SQL_SELECT *select)
+  {
+    DBUG_ASSERT(select && select->quick);
+
+    char buff_key[512];
+    String str_key(buff_key, sizeof(buff_key), cs);
+    str_key.length(0);
+
+    char buff_key_len[512];
+    String str_key_len(buff_key_len, sizeof(buff_key_len), cs);
+    str_key_len.length(0);
+
+    select->quick->add_keys_and_lengths(&str_key, &str_key_len);
+    return col_key.set(thd, str_key) || col_key_len.set(thd, str_key_len);
+  }
+  bool explain_key_and_len_index(int key)
+  {
+    DBUG_ASSERT(key != MAX_KEY);
+
+    KEY *key_info= table->key_info + key;
+    char buff_key_len[512];
+    int length= longlong2str(key_info->key_length, buff_key_len, 10) -
+                             buff_key_len;
+    return col_key.set(thd, key_info->name) ||
+           col_key_len.set(thd, buff_key_len, length);
+  }
+  void explain_extra_common(const SQL_SELECT *select, const JOIN_TAB *tab, int quick_type, uint keyno, bool need_sort, String *str_extra)
+  {
+    if ((keyno != MAX_KEY && keyno == table->file->pushed_idx_cond_keyno &&
+         table->file->pushed_idx_cond) || (tab && tab->cache_idx_cond))
+      str_extra->append(STRING_WITH_LEN("; Using index condition"));
+
+    switch (quick_type) {
+    case QUICK_SELECT_I::QS_TYPE_ROR_UNION:
+    case QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT:
+    case QUICK_SELECT_I::QS_TYPE_INDEX_MERGE:
+      str_extra->append(STRING_WITH_LEN("; Using "));
+      select->quick->add_info_string(str_extra);
+      break;
+    default: ;
+    }
+
+    if (select)
+    {
+      if (tab && tab->use_quick == QS_DYNAMIC_RANGE)
+      {
+        /* 4 bits per 1 hex digit + terminating '\0' */
+        char buf[MAX_KEY / 4 + 1];
+        str_extra->append(STRING_WITH_LEN("; Range checked for each "
+                                          "record (index map: 0x"));
+        str_extra->append(tab->keys.print(buf));
+        str_extra->append(')');
+      }
+      else if (select->cond)
+      {
+        const Item *pushed_cond= table->file->pushed_cond;
+
+        if (thd->optimizer_switch_flag(OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN) &&
+            pushed_cond)
+        {
+          str_extra->append(STRING_WITH_LEN("; Using where with pushed condition"));
+          if (describe(DESCRIBE_EXTENDED))
+          {
+            str_extra->append(STRING_WITH_LEN(": "));
+            ((Item *)pushed_cond)->print(str_extra, QT_ORDINARY);
+          }
+        }
+        else
+          str_extra->append(STRING_WITH_LEN("; Using where"));
+      }
+    }
+    if (table->reginfo.not_exists_optimize)
+      str_extra->append(STRING_WITH_LEN("; Not exists"));
+
+    if (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE &&
+        !(((QUICK_RANGE_SELECT*)(select->quick))->mrr_flags &
+         (HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED)))
+    {
+      /*
+        During normal execution of a query, multi_range_read_init() is
+        called to initialize MRR. If HA_MRR_SORTED is set at this point,
+        multi_range_read_init() for any native MRR implementation will
+        revert to default MRR because they cannot produce sorted output
+        currently.
+        Calling multi_range_read_init() can potentially be costly, so it
+        is not done when executing an EXPLAIN. We therefore make the
+        assumption that HA_MRR_SORTED means no MRR. If some MRR native
+        implementation will support sorted output in the future, a
+        function "bool mrr_supports_sorted()" should be added in the
+        handler.
+      */
+      str_extra->append(STRING_WITH_LEN("; Using MRR"));
+    }
+    if (need_sort)
+      str_extra->append(STRING_WITH_LEN("; Using filesort"));
+  }
 };
 
 
 /**
   Explain_join class produces EXPLAIN output for JOINs
-
-  Former part of the old select_describe() function.
 */
 
 class Explain_join : public Explain_table_base
 {
 private:
-  const bool need_tmp_table;
-  const bool need_order;
-  const bool distinct;
-
-  uint tabnum;
-  JOIN_TAB *tab;
-  int quick_type;
-  table_map used_tables;
-  uint last_sjm_table;
+  const bool need_tmp_table; ///< add "Using temporary" to "extra" if true
+  const bool need_order; ///< add "Using filesort"" to "extra" if true
+  const bool distinct; ///< add "Distinct" string to "extra" column if true
+
+  uint tabnum; ///< current tab number in join->join_tab[]
+  JOIN_TAB *tab; ///< current JOIN_TAB
+  int quick_type; ///< current quick type, see anon. enum at QUICK_SELECT_I
+  table_map used_tables; ///< accumulate used tables bitmap
+  uint last_sjm_table; ///< last materialized semi-joined table
 
+  /*
+    Next few private fields are intermediate buffers.
+    We need them here since String objects don't care about pre-allocated
+    data lifetime.
+  */
   char table_name_buffer[NAME_LEN];
 
-  char buff_key[512];
-  String str_key;
-
-  char buff_key_len[512];
-  String str_key_len;
-
-  char buff_ref[512];
-  String str_ref;
-
-  char buff_extra[512];
-  String str_extra;
-
 public:
-  Explain_join(JOIN *join_arg,
+  Explain_join(THD *thd_arg, JOIN *join_arg,
                bool need_tmp_table_arg, bool need_order_arg,
-               bool distinct_arg) 
-  : Explain_table_base(join_arg), need_tmp_table(need_tmp_table_arg),
+               bool distinct_arg)
+  : Explain_table_base(thd_arg, join_arg), need_tmp_table(need_tmp_table_arg),
     need_order(need_order_arg), distinct(distinct_arg),
-    tabnum(0), used_tables(0), last_sjm_table(MAX_TABLES),
-    str_key(buff_key, sizeof(buff_key), cs),
-    str_key_len(buff_key_len, sizeof(buff_key_len), cs),
-    str_ref(buff_ref, sizeof(buff_ref), cs),
-    str_extra(buff_extra, sizeof(buff_extra), cs)
+    tabnum(0), used_tables(0), last_sjm_table(MAX_TABLES)
   {
     /* it is not UNION: */
     DBUG_ASSERT(join_arg->select_lex != join_arg->unit->fake_select_lex);
@@ -291,28 +410,15 @@ private:
   const ha_rows    limit;      ///< HA_POS_ERROR or cached "limit" argument
   const bool       need_sort;  ///< cached need_sort argument
 
-  /*
-    Pre-allocated buffers and String wrapper objects for them
-  */
-  char buff_key[512];
-  String str_key;
-  char buff_key_len[512];
-  String str_key_len;
-  char buff_extra[512];
-  String str_extra;
-
 public:
-  Explain_table(TABLE *table_arg, SQL_SELECT *select_arg,
+  Explain_table(THD *thd_arg, TABLE *table_arg, SQL_SELECT *select_arg,
                 uint key_arg, ha_rows limit_arg, bool need_sort_arg)
-  : Explain_table_base(table_arg), select(select_arg), key(key_arg),
-    limit(limit_arg), need_sort(need_sort_arg),
-    str_key(buff_key, sizeof(buff_key), cs),
-    str_key_len(buff_key_len, sizeof(buff_key_len), cs),
-    str_extra(buff_extra, sizeof(buff_extra), cs)
+  : Explain_table_base(thd_arg, table_arg), select(select_arg), key(key_arg),
+    limit(limit_arg), need_sort(need_sort_arg)
   {
     usable_keys= table->keys_in_use_for_query;
   }
-  
+
 private:
   virtual bool explain_table_name();
   virtual bool explain_join_type();
@@ -338,18 +444,19 @@ static join_type calc_join_type(int quic
 
 /**
   Explain class main function
-  
+
   This method:
     a) allocates a select_send object (if no one pre-allocated available),
     b) calculates and sends whole EXPLAIN data.
 
   @returns
-    @retval FALSE  Ok
-    @retval TRUE   Error
+    @retval false  Ok
+    @retval true   Error
 */
 
 bool Explain::send()
 {
+  DBUG_ENTER("Explain::send");
   /* Don't log this into the slow query log */
   thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
                          SERVER_QUERY_NO_GOOD_INDEX_USED);
@@ -358,13 +465,12 @@ bool Explain::send()
   if (external_result == NULL)
   {
     /* Create select_result object if the called doesn't provide one: */
-    result= new select_send;
     if (!(result= new select_send))
-      return TRUE;
+      DBUG_RETURN(true);
     if (thd->send_explain_fields(result) || prepare(result))
     {
       delete result;
-      return TRUE;
+      DBUG_RETURN(true);;
     }
   }
   else
@@ -373,8 +479,8 @@ bool Explain::send()
     external_result->reset_offset_limit_cnt();
   }
 
-  if (!(nil= new Item_null))
-    return TRUE;
+  if (nil == NULL && !(nil= new Item_null))
+    DBUG_RETURN(true);
   bool ret= send_to(result);
 
   if (ret && join)
@@ -393,7 +499,7 @@ bool Explain::send()
       result->send_eof();
     delete result;
   }
-  return ret;
+  DBUG_RETURN(ret);
 }
 
 
@@ -404,17 +510,17 @@ bool Explain::send()
 void Explain::init_columns()
 {
   col_id= NULL;
-  col_select_type= NULL;
-  col_table_name= NULL;
-  col_partitions= NULL;
-  col_join_type= NULL;
-  col_possible_keys= NULL;
-  col_key= NULL;
-  col_key_len= NULL;
-  col_ref= NULL;
+  col_select_type.cleanup();
+  col_table_name.cleanup();
+  col_partitions.cleanup();
+  col_join_type.cleanup();
+  col_possible_keys.cleanup();
+  col_key.cleanup();
+  col_key_len.cleanup();
+  col_ref.cleanup();
   col_rows= NULL;
   col_filtered= NULL;
-  col_extra= NULL;
+  col_extra.cleanup();
 }
 
 
@@ -422,8 +528,8 @@ void Explain::init_columns()
   Calculate EXPLAIN column values and link them into "items" list
 
   @returns
-    @retval FALSE  Ok
-    @retval TRUE   Error
+    @retval false  Ok
+    @retval true   Error
 */
 
 bool Explain::make_list()
@@ -438,9 +544,9 @@ bool Explain::make_list()
       explain_ref() ||
       explain_rows_and_filtered() ||
       explain_extra())
-    return TRUE;
-    
-  /* 
+    return true;
+
+  /*
     NOTE: the number/types of items pushed into item_list must be in sync with
     EXPLAIN column types as they're "defined" in THD::send_explain_fields()
   */
@@ -467,13 +573,13 @@ bool Explain::make_list()
   it many times (once for each JOIN::join_tab[] element).
 
   @returns
-    @retval FALSE  Ok
-    @retval TRUE   Error
+    @retval false  Ok
+    @retval true   Error
 */
 
 bool Explain::send_to(select_result *to)
 {
-  bool ret= make_list() || to->send_data(items);
+  const bool ret= make_list() || to->send_data(items);
   items.empty();
   init_columns();
   return ret;
@@ -490,20 +596,19 @@ bool Explain::explain_id()
 bool Explain::explain_select_type()
 {
   if (select_lex->type)
-    col_select_type= new Item_string(select_lex->type,
-                                     strlen(select_lex->type), cs);
+    col_select_type.set(thd, select_lex->type);
   else if (select_lex->first_inner_unit() || select_lex->next_select())
-    col_select_type= new Item_string(STRING_WITH_LEN("PRIMARY"), cs);
+    col_select_type.set_const("PRIMARY");
   else
-    col_select_type= new Item_string(STRING_WITH_LEN("SIMPLE"), cs);
-  return col_select_type == NULL;                                       
+    col_select_type.set_const("SIMPLE");
+  return col_select_type.nil();
 }
 
 
 bool Explain::explain_extra()
 {
-  col_extra= new Item_string("", 0, cs);
-  return col_extra == NULL;
+  col_extra.set_const("");
+  return false;
 }
 
 
@@ -513,7 +618,7 @@ bool Explain::explain_extra()
 bool Explain_msg::explain_rows_and_filtered()
 {
   if (rows == HA_POS_ERROR)
-    return FALSE;
+    return false;
   col_rows= new Item_int(rows, MY_INT64_NUM_DECIMAL_DIGITS);
   return col_rows == NULL;
 }
@@ -521,8 +626,7 @@ bool Explain_msg::explain_rows_and_filte
 
 bool Explain_msg::explain_extra()
 {
-  col_extra= new Item_string(message, strlen(message), cs);
-  return col_extra == NULL;
+  return col_extra.set(thd, message);
 }
 
 
@@ -531,8 +635,7 @@ bool Explain_msg::explain_extra()
 
 bool Explain_union::explain_id()
 {
-  col_id= NULL;
-  return FALSE;
+  return false;
 }
 
 
@@ -550,8 +653,8 @@ bool Explain_union::explain_table_name()
     - 6 + last_length: the number of characters needed to print
       '...,'<last_select->select_number>'>\0'
   */
-  for (; 
-       sl && len + lastop + 6 + last_length < NAME_CHAR_LEN; 
+  for (;
+       sl && len + lastop + 6 + last_length < NAME_CHAR_LEN;
        sl= sl->next_select())
   {
     len+= lastop;
@@ -568,25 +671,19 @@ bool Explain_union::explain_table_name()
   len+= lastop;
   table_name_buffer[len - 1]= '>';  // change ',' to '>'
 
-  col_table_name= new Item_string(table_name_buffer, len, cs);
-
-  return col_table_name == NULL;
+  return col_table_name.set(thd, table_name_buffer, len);
 }
 
 
 bool Explain_union::explain_join_type()
 {
-  col_join_type= new Item_string(join_type_str[JT_ALL],
-                                 strlen(join_type_str[JT_ALL]), cs);
-  return col_join_type == NULL;
+  return col_join_type.set(thd, join_type_str[JT_ALL]);
 }
 
 
 bool Explain_union::explain_extra()
 {
-  /* 
-    Moved from select_describe():
-
+  /*
     here we assume that the query will return at least two rows, so we
     show "filesort" in EXPLAIN. Of course, sometimes we'll be wrong
     and no filesort will be actually done, but executing all selects in
@@ -595,8 +692,8 @@ bool Explain_union::explain_extra()
   */
   if (join->unit->global_parameters->order_list.first)
   {
-    col_extra= new Item_string(STRING_WITH_LEN("Using filesort"), cs);
-    return col_extra == NULL;
+    col_extra.set_const("Using filesort");
+    return false;
   }
   return Explain::explain_extra();
 }
@@ -609,41 +706,38 @@ bool Explain_table_base::explain_partiti
 {
 #ifdef WITH_PARTITION_STORAGE_ENGINE
   if (!table->derived_select_number && table->part_info)
-  {          
-    col_partitions= new Item_string(cs);
-    if (col_partitions == NULL)
-      return TRUE;
-    make_used_partitions_str(table->part_info, &col_partitions->str_value);
+  {
+    String s;
+    make_used_partitions_str(table->part_info, &s);
+    return col_partitions.set(thd, s);
   }
 #endif
-  return FALSE;
+  return false;
 }
 
 
 bool Explain_table_base::explain_possible_keys()
 {
   if (usable_keys.is_clear_all())
-    return FALSE;
+    return false;
 
+  char buff_possible_keys[512];
+  String str_possible_keys(buff_possible_keys, sizeof(buff_possible_keys), cs);
   str_possible_keys.length(0);
 
-  for (uint j=0 ; j < table->s->keys ; j++)
+  for (uint j= 0 ; j < table->s->keys ; j++)
   {
     if (usable_keys.is_set(j))
     {
       if (str_possible_keys.length())
         str_possible_keys.append(',');
-      str_possible_keys.append(table->key_info[j].name, 
+      str_possible_keys.append(table->key_info[j].name,
                                strlen(table->key_info[j].name), cs);
     }
   }
   if (str_possible_keys.length())
-  {
-    col_possible_keys= new Item_string(str_possible_keys.ptr(),
-                                       str_possible_keys.length(), cs);
-    return col_possible_keys == NULL;
-  }
-  return FALSE;
+    return col_possible_keys.set(thd, str_possible_keys);
+  return false;
 }
 
 
@@ -658,7 +752,7 @@ bool Explain_join::send_to(select_result
     table= tab->table;
     usable_keys= tab->keys;
     quick_type= -1;
-    
+
     if (tab->type == JT_ALL && tab->select && tab->select->quick)
     {
       quick_type= tab->select->quick->get_type();
@@ -666,11 +760,11 @@ bool Explain_join::send_to(select_result
     }
 
     if (Explain_table_base::send_to(external_result))
-      return TRUE;
-      
+      return true;
+
     used_tables|= table->map;
   }
-  return FALSE;
+  return false;
 }
 
 
@@ -681,63 +775,51 @@ bool Explain_join::explain_table_name()
     /* Derived table name generation */
     int len= my_snprintf(table_name_buffer, sizeof(table_name_buffer) - 1,
                          "<derived%u>", table->derived_select_number);
-    col_table_name= new Item_string(table_name_buffer, len, cs);
+    return col_table_name.set(thd, table_name_buffer, len);
   }
   else
   {
-    TABLE_LIST *real_table= table->pos_in_table_list; 
-    col_table_name= new Item_string(real_table->alias,
-                                    strlen(real_table->alias), cs);
+    TABLE_LIST *real_table= table->pos_in_table_list;
+    return col_table_name.set(thd, real_table->alias);
   }
-  return col_table_name == NULL;
 }
 
 
 bool Explain_join::explain_join_type()
 {
-  col_join_type= new Item_string(join_type_str[tab->type],
-                                 strlen(join_type_str[tab->type]), cs);
-  return col_join_type == NULL;
+  return col_join_type.set(thd, join_type_str[tab->type]);
 }
 
 
 bool Explain_join::explain_key_and_len()
 {
-  str_key.length(0);
-  str_key_len.length(0);
-  
+  char buff_key_len[512];
   if (tab->ref.key_parts)
   {
     KEY *key_info= table->key_info + tab->ref.key;
     uint length;
-    col_key= new Item_string(key_info->name, strlen(key_info->name), cs);
+    col_key.set(thd, key_info->name);
     length= longlong2str(tab->ref.key_length, buff_key_len, 10) - buff_key_len;
-    col_key_len= new Item_string(buff_key_len, length, cs);
-    return col_key == NULL || col_key_len == NULL;
+    col_key_len.set(thd, buff_key_len, length);
+    return col_key.nil() || col_key_len.nil();
   }
   else if (tab->type == JT_NEXT)
-  {
-    KEY *key_info= table->key_info + tab->index;
-    uint length;
-    col_key= new Item_string(key_info->name, strlen(key_info->name), cs);
-    length= longlong2str(key_info->key_length, buff_key_len, 10) - 
-            buff_key_len;
-    col_key_len= new Item_string(buff_key_len, length, cs);
-    return col_key == NULL || col_key_len == NULL;
-  }
+    return explain_key_and_len_index(tab->index);
   else if (tab->select && tab->select->quick)
-  {
-    tab->select->quick->add_keys_and_lengths(&str_key, &str_key_len);
-    col_key= new Item_string(str_key.ptr(), str_key.length(), cs);
-    col_key_len= new Item_string(str_key_len.ptr(), str_key_len.length(), cs);
-    return col_key == NULL || col_key_len == NULL;
-  }
+    return explain_key_and_len_quick(tab->select);
   else
   {
-    TABLE_LIST *table_list= tab->table->pos_in_table_list;
+    TABLE_LIST *table_list= table->pos_in_table_list;
     if (table_list->schema_table &&
         table_list->schema_table->i_s_requested_object & OPTIMIZE_I_S_TABLE)
     {
+      char buff_key[512];
+      String str_key(buff_key, sizeof(buff_key), cs);
+      str_key.length(0);
+
+      String str_key_len(buff_key_len, sizeof(buff_key_len), cs);
+      str_key_len.length(0);
+
       const char *f_name;
       int f_idx;
       if (table_list->has_db_lookup_value)
@@ -745,7 +827,7 @@ bool Explain_join::explain_key_and_len()
         f_idx= table_list->schema_table->idx_field1;
         f_name= table_list->schema_table->fields_info[f_idx].field_name;
         str_key.append(f_name, strlen(f_name), cs);
-      }          
+      }
       if (table_list->has_table_lookup_value)
       {
         if (table_list->has_db_lookup_value)
@@ -755,39 +837,36 @@ bool Explain_join::explain_key_and_len()
         str_key.append(f_name, strlen(f_name), cs);
       }
       if (str_key.length())
-      {
-        col_key= new Item_string(str_key.ptr(), str_key.length(), cs);
-        return col_key == NULL;
-      }
+        return col_key.set(thd, str_key);
     }
   }
-  return FALSE;
+  return false;
 }
 
 
 bool Explain_join::explain_ref()
 {
-  str_ref.length(0);
-
   if (tab->ref.key_parts)
   {
+    char buff_ref[512];
+    String str_ref(buff_ref, sizeof(buff_ref), cs);
+    str_ref.length(0);
     for (store_key **ref= tab->ref.key_copy; *ref; ref++)
     {
       if (str_ref.length())
         str_ref.append(',');
       str_ref.append((*ref)->name(), strlen((*ref)->name()), cs);
     }
-    col_ref= new Item_string(str_ref.ptr(), str_ref.length(), cs);
-    return col_ref == NULL;
+    return col_ref.set(thd, str_ref);
   }
-  return FALSE;
+  return false;
 }
 
 
 bool Explain_join::explain_rows_and_filtered()
 {
-  if (tab->table->pos_in_table_list->schema_table)
-    return FALSE;
+  if (table->pos_in_table_list->schema_table)
+    return false;
 
   double examined_rows;
   if (tab->select && tab->select->quick)
@@ -798,47 +877,47 @@ bool Explain_join::explain_rows_and_filt
       examined_rows= rows2double(tab->limit);
     else
     {
-      tab->table->file->info(HA_STATUS_VARIABLE);
-      examined_rows= rows2double(tab->table->file->stats.records);
+      table->file->info(HA_STATUS_VARIABLE);
+      examined_rows= rows2double(table->file->stats.records);
     }
   }
   else
-    examined_rows= join->best_positions[tabnum].records_read; 
+    examined_rows= join->best_positions[tabnum].records_read;
 
-  col_rows= new Item_int((longlong) (ulonglong) examined_rows, 
+  col_rows= new Item_int((longlong) (ulonglong) examined_rows,
                          MY_INT64_NUM_DECIMAL_DIGITS);
   if (col_rows == NULL)
-    return TRUE;
+    return true;
 
   /* Add "filtered" field */
   if (describe(DESCRIBE_EXTENDED))
   {
-    float f= 0.0; 
+    float f= 0.0;
     if (examined_rows)
-      f= (float) (100.0 * join->best_positions[tabnum].records_read /
-                  examined_rows);
+      f= 100.0 * join->best_positions[tabnum].records_read / examined_rows;
     col_filtered= new Item_float(f, 2);
-    if (col_filtered == NULL)
-      return TRUE;
+    return col_filtered == NULL;
   }
-  return FALSE;
+  return false;
 }
 
 
 bool Explain_join::explain_extra()
 {
+  char buff_extra[512];
+  String str_extra(buff_extra, sizeof(buff_extra), cs);
   str_extra.length(0);
 
-  my_bool key_read=table->key_read;
+  bool key_read= table->key_read;
   if ((tab->type == JT_NEXT || tab->type == JT_CONST) &&
       table->covering_keys.is_set(tab->index))
-    key_read=1;
+    key_read= true;
   if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT &&
       !((QUICK_ROR_INTERSECT_SELECT*)tab->select->quick)->need_to_fetch_row)
-    key_read=1;
-    
+    key_read= true;
+
   if (tab->info)
-    col_extra= new Item_string(tab->info,strlen(tab->info), cs);
+    col_extra.set(thd, tab->info);
   else if (tab->packed_info & TAB_INFO_HAVE_VALUE)
   {
     if (tab->packed_info & TAB_INFO_USING_INDEX)
@@ -855,7 +934,7 @@ bool Explain_join::explain_extra()
       str += 2;
       len -= 2;
     }
-    col_extra= new Item_string(str, len, cs);
+    col_extra.set(thd, str, len);
   }
   else
   {
@@ -865,48 +944,10 @@ bool Explain_join::explain_extra()
     else if (tab->select && tab->select->quick)
       keyno = tab->select->quick->index;
 
-    if ((keyno != MAX_KEY && keyno == table->file->pushed_idx_cond_keyno &&
-         table->file->pushed_idx_cond) || tab->cache_idx_cond)
-      str_extra.append(STRING_WITH_LEN("; Using index condition"));
+    explain_extra_common(tab->select, tab, quick_type, keyno,
+                         (tabnum == 0 && need_order), &str_extra);
 
-    if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION || 
-        quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
-        quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
-    {
-      str_extra.append(STRING_WITH_LEN("; Using "));
-      tab->select->quick->add_info_string(&str_extra);
-    }
-    if (tab->select)
-    {
-      if (tab->use_quick == QS_DYNAMIC_RANGE)
-      {
-        /* 4 bits per 1 hex digit + terminating '\0' */
-        char buf[MAX_KEY / 4 + 1];
-        str_extra.append(STRING_WITH_LEN("; Range checked for each "
-                                     "record (index map: 0x"));
-        str_extra.append(tab->keys.print(buf));
-        str_extra.append(')');
-      }
-      else if (tab->select->cond)
-      {
-        const Item *pushed_cond= tab->table->file->pushed_cond;
-
-        if (thd->optimizer_switch_flag(OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN) &&
-            pushed_cond)
-        {
-          str_extra.append(STRING_WITH_LEN("; Using where with pushed "
-                                       "condition"));
-          if (describe(DESCRIBE_EXTENDED))
-          {
-            str_extra.append(STRING_WITH_LEN(": "));
-            ((Item *)pushed_cond)->print(&str_extra, QT_ORDINARY);
-          }
-        }
-        else
-          str_extra.append(STRING_WITH_LEN("; Using where"));
-      }
-    }
-    TABLE_LIST *table_list= tab->table->pos_in_table_list;
+    TABLE_LIST *table_list= table->pos_in_table_list;
     if (table_list->schema_table &&
         table_list->schema_table->i_s_requested_object & OPTIMIZE_I_S_TABLE)
     {
@@ -929,7 +970,7 @@ bool Explain_join::explain_extra()
     {
       if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
       {
-        QUICK_GROUP_MIN_MAX_SELECT *qgs= 
+        QUICK_GROUP_MIN_MAX_SELECT *qgs=
           (QUICK_GROUP_MIN_MAX_SELECT *) tab->select->quick;
         str_extra.append(STRING_WITH_LEN("; Using index for group-by"));
         qgs->append_loose_scan_type(&str_extra);
@@ -937,41 +978,15 @@ bool Explain_join::explain_extra()
       else
         str_extra.append(STRING_WITH_LEN("; Using index"));
     }
-    if (table->reginfo.not_exists_optimize)
-      str_extra.append(STRING_WITH_LEN("; Not exists"));
 
-    if (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE &&
-        !(((QUICK_RANGE_SELECT*)(tab->select->quick))->mrr_flags &
-         (HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED))) 
-    {
-      /*
-        During normal execution of a query, multi_range_read_init() is
-        called to initialize MRR. If HA_MRR_SORTED is set at this point,
-        multi_range_read_init() for any native MRR implementation will
-        revert to default MRR because they cannot produce sorted output
-        currently.
-        Calling multi_range_read_init() can potentially be costly, so it
-        is not done when executing an EXPLAIN. We therefore make the
-        assumption that HA_MRR_SORTED means no MRR. If some MRR native
-        implementation will support sorted output in the future, a
-        function "bool mrr_supports_sorted()" should be added in the
-        handler.
-      */
-      str_extra.append(STRING_WITH_LEN("; Using MRR"));
-    }
     if (tabnum == 0 && need_tmp_table)
       str_extra.append(STRING_WITH_LEN("; Using temporary"));
 
-    if (tabnum == 0 && need_order)
-      str_extra.append(STRING_WITH_LEN("; Using filesort"));
-    
     if (distinct && test_all_bits(used_tables,thd->used_tables))
       str_extra.append(STRING_WITH_LEN("; Distinct"));
 
     if (tab->loosescan_match_tab)
-    {
       str_extra.append(STRING_WITH_LEN("; LooseScan"));
-    }
 
     if (tab->flush_weedout_table)
       str_extra.append(STRING_WITH_LEN("; Start temporary"));
@@ -984,7 +999,7 @@ bool Explain_join::explain_extra()
       else
       {
         str_extra.append(STRING_WITH_LEN("; FirstMatch("));
-        TABLE *prev_table=tab->do_firstmatch->table;
+        TABLE *prev_table= tab->do_firstmatch->table;
         if (prev_table->derived_select_number)
         {
           char namebuf[NAME_LEN];
@@ -1051,9 +1066,9 @@ bool Explain_join::explain_extra()
       str += 2;
       len -= 2;
     }
-    col_extra= new Item_string(str, len, cs);
+    col_extra.set(thd, str, len);
   }
-  return col_extra == NULL;
+  return col_extra.nil();
 }
 
 
@@ -1062,8 +1077,7 @@ bool Explain_join::explain_extra()
 
 bool Explain_table::explain_table_name()
 {
-  col_table_name= new Item_string(table->alias, strlen(table->alias), cs);
-  return col_table_name == NULL;                                    
+  return col_table_name.set(thd, table->alias);
 }
 
 
@@ -1075,34 +1089,17 @@ bool Explain_table::explain_join_type()
   else
     jt= JT_ALL;
 
-  col_join_type= new Item_string(join_type_str[jt],
-                                 strlen(join_type_str[jt]), cs);
-  return col_join_type == NULL;                                   
+  return col_join_type.set(thd, join_type_str[jt]);
 }
 
 
 bool Explain_table::explain_key_and_len()
 {
-  str_key.length(0);
-  str_key_len.length(0);
-
   if (key != MAX_KEY)
-  {
-    KEY *key_info= table->key_info + key;
-    col_key= new Item_string(key_info->name, strlen(key_info->name), cs);
-    int length= longlong2str(key_info->key_length, buff_key_len, 10) - 
-                             buff_key_len;
-    col_key_len= new Item_string(buff_key_len, length, cs);
-    return col_key == NULL || col_key_len == NULL;
-  }
-  else if (select && select->quick)
-  {
-    select->quick->add_keys_and_lengths(&str_key, &str_key_len);
-    col_key= new Item_string(str_key.ptr(), str_key.length(), cs);
-    col_key_len= new Item_string(str_key_len.ptr(), str_key_len.length(), cs);
-    return col_key == NULL || col_key_len == NULL;
-  }
-  return FALSE;
+    return explain_key_and_len_index(key);
+  if (select && select->quick)
+    return explain_key_and_len_quick(select);
+  return false;
 }
 
 
@@ -1121,83 +1118,28 @@ bool Explain_table::explain_rows_and_fil
   col_rows= new Item_int((longlong) (ulonglong) examined_rows,
                          MY_INT64_NUM_DECIMAL_DIGITS);
   if (col_rows == NULL)
-    return TRUE;
+    return true;
 
   if (describe(DESCRIBE_EXTENDED))
   {
     col_filtered= new Item_float(100.0, 2);
     if (col_filtered == NULL)
-      return TRUE;
+      return true;
   }
-  return FALSE;
+  return false;
 }
 
 
 bool Explain_table::explain_extra()
 {
+  char buff_extra[512];
+  String str_extra(buff_extra, sizeof(buff_extra), cs);
   str_extra.length(0);
 
   uint keyno= (select && select->quick) ? select->quick->index : key;
-
-  if (keyno != MAX_KEY && keyno == table->file->pushed_idx_cond_keyno &&
-      table->file->pushed_idx_cond)
-    str_extra.append(STRING_WITH_LEN("; Using index condition"));
-
   int quick_type= (select && select->quick) ? select->quick->get_type() : -1;
 
-  switch (quick_type) {
-  case QUICK_SELECT_I::QS_TYPE_ROR_UNION:
-  case QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT:
-  case QUICK_SELECT_I::QS_TYPE_INDEX_MERGE:
-    str_extra.append(STRING_WITH_LEN("; Using "));
-    select->quick->add_info_string(&str_extra);
-    break;
-  default: ;
-  }
-
-  if (select && select->cond)
-  {
-    const Item *pushed_cond= table->file->pushed_cond;
-
-    if (thd->optimizer_switch_flag(OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN) &&
-        pushed_cond)
-    {
-      str_extra.append(STRING_WITH_LEN("; Using where with pushed "
-                                       "condition"));
-      if (describe(DESCRIBE_EXTENDED))
-      {
-        str_extra.append(STRING_WITH_LEN(": "));
-        ((Item *)pushed_cond)->print(&str_extra, QT_ORDINARY);
-      }
-    }
-    else
-      str_extra.append(STRING_WITH_LEN("; Using where"));
-  }
-
-  if (table->reginfo.not_exists_optimize)
-    str_extra.append(STRING_WITH_LEN("; Not exists"));
-
-  if (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE &&
-      !(((QUICK_RANGE_SELECT*)(select->quick))->mrr_flags &
-       (HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED))) 
-  {
-    /*
-      During normal execution of a query, multi_range_read_init() is
-      called to initialize MRR. If HA_MRR_SORTED is set at this point,
-      multi_range_read_init() for any native MRR implementation will
-      revert to default MRR because they cannot produce sorted output
-      currently.
-      Calling multi_range_read_init() can potentially be costly, so it
-      is not done when executing an EXPLAIN. We therefore make the
-      assumption that HA_MRR_SORTED means no MRR. If some MRR native
-      implementation will support sorted output in the future, a
-      function "bool mrr_supports_sorted()" should be added in the
-      handler.
-    */
-    str_extra.append(STRING_WITH_LEN("; Using MRR"));
-  }
-  if (need_sort)
-    str_extra.append(STRING_WITH_LEN("; Using filesort"));
+  explain_extra_common(select, NULL, quick_type, keyno, need_sort, &str_extra);
 
   /* Skip initial "; "*/
   const char *str= str_extra.ptr();
@@ -1207,8 +1149,7 @@ bool Explain_table::explain_extra()
     str += 2;
     len -= 2;
   }
-  col_extra= new Item_string(str, len, cs);
-  return col_extra == NULL;
+  return col_extra.set(thd, str, len);
 }
 
 
@@ -1244,12 +1185,25 @@ protected:
     for multiple invocations, so result_state bitmap guards data interceptor
     object from method re-invocation.
   */
-  enum result_state_enum { 
-    SELECT_RESULT_PREPARED    = 0x01, // 1st bit set: prepare() is complete
-    SELECT_RESULT_PREPARED2   = 0x02, // 2nd bit set: prepare2() is complete
-    SELECT_RESULT_INITIALIZED = 0x04  // 3rd bit set: initialize_tables() done
-  };
-  int result_state; ///< bitmap of result_state_enum bits
+  enum result_state_enum {
+    SELECT_RESULT_NONE        = 0x00, ///< initial value
+    SELECT_RESULT_PREPARED    = 0x01, ///< 1st bit set: prepare() is done 
+    SELECT_RESULT_PREPARED2   = 0x02, ///< 2nd bit set: prepare2() is done
+    SELECT_RESULT_INITIALIZED = 0x04  ///< 3rd bit set: initialize_tables() done
+  } result_state; ///< bitmap of result_state_enum bits
+  
+  /**
+    Binary OR operator for result_state_enum to return result_state_enum
+    without casts
+
+    The "friend" modifier is to declare a "static" operator since "static" is
+    prohibited there.
+  */
+  friend result_state_enum operator|(result_state_enum x, result_state_enum y)
+  {
+    return static_cast<result_state_enum>(static_cast<int>(x) |
+                                          static_cast<int>(y));
+  }
 
   /**
     Pointer to underlying insert_select, multi_update or multi_delete object
@@ -1257,35 +1211,32 @@ protected:
   select_result_interceptor *interceptor;
 
 public:
-  explain_send(select_result_interceptor *interceptor_arg) 
-  : result_state(0), interceptor(interceptor_arg)
+  explain_send(select_result_interceptor *interceptor_arg)
+  : result_state(SELECT_RESULT_NONE), interceptor(interceptor_arg)
   {}
 
 protected:
   virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
   {
     if (result_state & SELECT_RESULT_PREPARED)
-      return FALSE;
-    else
-      result_state|= SELECT_RESULT_PREPARED;
+      return false;
+    result_state= result_state|SELECT_RESULT_PREPARED;
     return select_send::prepare(list, u) || interceptor->prepare(list, u);
   }
 
   virtual int prepare2(void)
   {
     if (result_state & SELECT_RESULT_PREPARED2)
-      return FALSE;
-    else
-      result_state|= SELECT_RESULT_PREPARED2;
+      return false;
+    result_state= result_state|SELECT_RESULT_PREPARED2;
     return select_send::prepare2() || interceptor->prepare2();
   }
 
   virtual bool initialize_tables(JOIN *join)
   {
     if (result_state & SELECT_RESULT_INITIALIZED)
-      return FALSE;
-    else
-      result_state|= SELECT_RESULT_INITIALIZED;
+      return false;
+    result_state= result_state|SELECT_RESULT_INITIALIZED;
     return select_send::initialize_tables(join) ||
            interceptor->initialize_tables(join);
   }
@@ -1304,47 +1255,54 @@ protected:
 
 
 /**
-  Send a messages as an "extra" column value
+  Send a message as an "extra" column value
 
   This function forms the 1st row of the QEP output with a simple text message.
   This is useful to explain such trivial cases as "No tables used" etc.
-  
-  NOTE: Also this function explains the rest of QEP (subqueries or joined
+
+  @note Also this function explains the rest of QEP (subqueries or joined
         tables if any).
 
+  @param thd      current THD
+  @param join     JOIN
   @param message  text message for the "extra" column.
-  @param rows     HA_POS_ERROR or a value for the "rows" column.
 
   @returns
-    @retval FALSE  OK
-    @retval TRUE   Error
+    @retval false  OK
+    @retval true   Error
 */
 
-bool msg_describe(JOIN *join, const char *message)
+bool explain_msg(THD *thd, JOIN *join, const char *message)
 {
-  return Explain_msg(join, message).send();
+  DBUG_ENTER("explain_msg");
+  const bool ret= Explain_msg(thd, join, message).send();
+  DBUG_RETURN(ret);
 }
 
 
 /**
-  Send a messages as an "extra" column value
+  Send a message as an "extra" column value
 
   This function forms the 1st row of the QEP output with a simple text message.
   This is useful to explain such trivial cases as "No tables used" etc.
-  
-  NOTE: Also this function explains the rest of QEP (subqueries if any).
 
+  @note Also this function explains the rest of QEP (subqueries if any).
+
+  @param thd      current THD
   @param message  text message for the "extra" column.
   @param rows     HA_POS_ERROR or a value for the "rows" column.
 
   @returns
-    @retval FALSE  OK
-    @retval TRUE   Error
+    @retval false  OK
+    @retval true   Error
 */
 
-bool msg_describe(const char *message, ha_rows rows)
+bool explain_msg(THD *thd, const char *message, ha_rows rows)
 {
-  return Explain_msg(message, rows).send();
+  DBUG_ENTER("explain_msg");
+  const bool ret= Explain_msg(thd, message, rows).send();
+  DBUG_RETURN(ret);
+
 }
 
 
@@ -1357,6 +1315,7 @@ bool msg_describe(const char *message, h
   thus we deal with this single table in a special way and then call
   mysql_explain_union() for subqueries (if any).
 
+  @param thd        current THD
   @param table      TABLE object to update/delete rows in the UPDATE/DELETE
                     query.
   @param select     SQL_SELECT object that represents quick access methods/
@@ -1364,49 +1323,55 @@ bool msg_describe(const char *message, h
   @param key        MAX_KEY or and index number of the key that was chosen to
                     access table data.
   @param limit      HA_POS_ERROR or LIMIT value.
-  @param need_sort  TRUE if it requires filesort() -- "Using filesort"
+  @param need_sort  true if it requires filesort() -- "Using filesort"
                     string in the "extra" column.
 
   @returns
-    @retval FALSE  OK
-    @retval TRUE   Error
+    @retval false  OK
+    @retval true   Error
 */
 
-bool table_describe(TABLE *table, SQL_SELECT *select, uint key, ha_rows limit,
-                    bool need_sort)
+bool explain_table_no_JOIN(THD *thd, TABLE *table, SQL_SELECT *select, uint key,
+                           ha_rows limit, bool need_sort)
 {
-  return Explain_table(table, select, key, limit, need_sort).send();
+  DBUG_ENTER("explain_table_no_JOIN");
+  const bool ret= Explain_table(thd, table, select, key, limit,
+                                need_sort).send();
+  DBUG_RETURN(ret);
 }
 
 
 /**
   EXPLAIN handling for EXPLAIN SELECT queries
 
-  Send a description about what how the select will be done to the client
+  Send QEP to the client.
 
+  @param thd             current THD
   @param join            JOIN
-  @param need_tmp_table  TRUE if it requires a temporary table --
+  @param need_tmp_table  true if it requires a temporary table --
                          "Using temporary" string in the "extra" column.
-  @param need_order      TRUE if it requires filesort() -- "Using filesort"
+  @param need_order      true if it requires filesort() -- "Using filesort"
                          string in the "extra" column.
-  @param distinct        TRUE if there is the DISTINCT clause (not optimized
+  @param distinct        true if there is the DISTINCT clause (not optimized
                          out) -- "Distinct" string in the "extra" column.
 
   @returns
-    @retval FALSE  OK
-    @retval TRUE   Error
+    @retval false  OK
+    @retval true   Error
 */
 
-bool select_describe(JOIN *join, bool need_tmp_table, bool need_order,
+bool select_describe(THD *thd, JOIN *join, bool need_tmp_table, bool need_order,
                      bool distinct)
 {
   DBUG_ENTER("select_describe");
-  DBUG_PRINT("info", ("Select 0x%lx, type %s",
-		      (ulong)join->select_lex, join->select_lex->type));
+  DBUG_PRINT("info", ("Select %p, type %s",
+		      join->select_lex, join->select_lex->type));
+  bool ret;
   if (join->select_lex == join->unit->fake_select_lex)
-    DBUG_RETURN(Explain_union(join).send());
+    ret= Explain_union(thd, join).send();
   else
-    DBUG_RETURN(Explain_join(join, need_tmp_table, need_order, distinct).send());
+    ret= Explain_join(thd, join, need_tmp_table, need_order, distinct).send();
+  DBUG_RETURN(ret);
 }
 
 
@@ -1418,25 +1383,28 @@ bool select_describe(JOIN *join, bool ne
   UPDATE and DELETE queries) like mysql_select() does for SELECT queries in
   the "describe" mode.
 
-  NOTE: See table_describe() for single-table UPDATE/DELETE EXPLAIN handling.
+  @note See explain_table_no_JOIN() for single-table UPDATE/DELETE EXPLAIN
+        handling.
 
-  NOTE: Unlike the mysql_select() function, explain_data_modification()
+  @note Unlike the mysql_select function, explain_data_modification_having_JOIN
         calls abort_result_set() itself in the case of failure (OOM etc.)
-        since explain_data_modification() uses internally created select_result
-        stream.
+        since explain_data_modification_having_JOIN() uses internally created
+        select_result stream.
 
+  @param thd     current THD
   @param result  pointer to select_insert, multi_delete or multi_update object:
                  the function uses it to call result->prepare(),
                  result->prepare2() and result->initialize_tables() only but
                  not to modify table data or to send a result to client.
   @returns
-    @retval FALSE  OK
-    @retval TRUE   Error
+    @retval false  OK
+    @retval true   Error
 */
 
-bool explain_data_modification(select_result_interceptor *result)
+bool explain_data_modification_having_JOIN(THD *thd,
+                                           select_result_interceptor *result)
 {
-  THD *thd= current_thd;
+  DBUG_ENTER("explain_data_modification_having_JOIN");
   explain_send explain(result);
   bool res= thd->send_explain_fields(&explain) ||
             mysql_explain_union(thd, &thd->lex->unit, &explain) ||
@@ -1445,6 +1413,6 @@ bool explain_data_modification(select_re
     explain.abort_result_set();
   else
     explain.send_eof();
-  return res;
+  DBUG_RETURN(res);
 }
 

=== modified file 'sql/opt_explain.h'
--- a/sql/opt_explain.h	2011-03-30 16:48:25 +0000
+++ b/sql/opt_explain.h	2011-05-25 14:16:06 +0000
@@ -14,17 +14,24 @@
    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
 
 
-#ifndef SQL_EXPLAIN_INCLUDED
-#define SQL_EXPLAIN_INCLUDED
+#ifndef OPT_EXPLAIN_INCLUDED
+#define OPT_EXPLAIN_INCLUDED
 
-#include "sql_select.h"
+class JOIN;
+class select_result_interceptor;
+class SQL_SELECT;
+class TABLE;
+class THD;
 
-bool msg_describe(JOIN *join, const char *message);
-bool msg_describe(const char *message, ha_rows rows= HA_POS_ERROR);
-bool table_describe(TABLE *table, SQL_SELECT *select, uint key, ha_rows limit,
-                    bool need_sort);
-bool select_describe(JOIN *join, bool need_tmp_table, bool need_order,
+#include "my_base.h"
+
+bool explain_msg(THD *thd, JOIN *join, const char *message);
+bool explain_msg(THD *thd, const char *message, ha_rows rows= HA_POS_ERROR);
+bool explain_table_no_JOIN(THD *thd, TABLE *table, SQL_SELECT *select, uint key,
+                    ha_rows limit, bool need_sort);
+bool select_describe(THD *thd, JOIN *join, bool need_tmp_table, bool need_order,
                      bool distinct);
-bool explain_data_modification(select_result_interceptor *result);
+bool explain_data_modification_having_JOIN(THD *thd,
+                                           select_result_interceptor *result);
 
-#endif /* SQL_EXPLAIN_INCLUDED */
+#endif /* OPT_EXPLAIN_INCLUDED */

=== modified file 'sql/opt_range.h'
--- a/sql/opt_range.h	2011-03-30 16:48:25 +0000
+++ b/sql/opt_range.h	2011-05-25 14:16:06 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2011-03-30 16:48:25 +0000
+++ b/sql/sql_class.h	2011-05-25 14:16:06 +0000
@@ -3112,7 +3112,7 @@ public:
   virtual void cleanup();
   void set_thd(THD *thd_arg) { thd= thd_arg; }
 
-  /*
+  /**
     If we execute EXPLAIN SELECT ... LIMIT (or any other EXPLAIN query)
     we have to ignore LIMIT value sending EXPLAIN output rows since
     LIMIT value belongs to the underlying query, not to the whole EXPLAIN.

=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc	2011-03-30 16:48:25 +0000
+++ b/sql/sql_delete.cc	2011-05-25 14:16:06 +0000
@@ -62,6 +62,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
   bool          reverse= FALSE;
   bool          skip_record;
   bool          need_sort= FALSE;
+  bool          err= true;
   ORDER *order= (ORDER *) ((order_list && order_list->elements) ?
                            order_list->first : NULL);
   uint usable_index= MAX_KEY;
@@ -149,10 +150,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *
 
     if (thd->lex->describe)
     {
-      bool err= msg_describe("Using delete_all_rows", maybe_deleted);
-      delete select;
-      free_underlaid_joins(thd, select_lex);
-      DBUG_RETURN(err);
+      err= explain_msg(thd, "Deleting all rows", maybe_deleted);
+      goto exit_without_my_ok;
     }
 
     DBUG_PRINT("debug", ("Trying to use delete_all_rows()"));
@@ -185,10 +184,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *
 
       if (thd->lex->describe)
       {
-        bool err= msg_describe("Impossible WHERE");
-        delete select;
-        free_underlaid_joins(thd, select_lex);
-        DBUG_RETURN(err);
+        err= explain_msg(thd, "Impossible WHERE");
+        goto exit_without_my_ok;
       }
     }
   }
@@ -198,10 +195,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *
   { // No matching records
     if (thd->lex->describe)
     {
-      bool err= msg_describe("No matching records");
-      delete select;
-      free_underlaid_joins(thd, select_lex);
-      DBUG_RETURN(err);
+      err= explain_msg(thd, "No matching records");
+      goto exit_without_my_ok;
     }
 
     free_underlaid_joins(thd, select_lex);
@@ -259,10 +254,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *
 
   if (thd->lex->describe)
   {
-    bool err= table_describe(table, select, usable_index, limit, need_sort);
-    delete select;
-    free_underlaid_joins(thd, select_lex);
-    DBUG_RETURN(err);
+    err= explain_table_no_JOIN(thd, table, select, usable_index,
+                               limit, need_sort);
+    goto exit_without_my_ok;
   }
 
   if (options & OPTION_QUICK)
@@ -454,6 +448,11 @@ cleanup:
     DBUG_PRINT("info",("%ld records deleted",(long) deleted));
   }
   DBUG_RETURN(thd->is_error() || thd->killed);
+
+exit_without_my_ok:
+  delete select;
+  free_underlaid_joins(thd, select_lex);
+  DBUG_RETURN((err || thd->is_error() || thd->killed) ? 1 : 0);
 }
 
 

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2011-03-30 16:48:25 +0000
+++ b/sql/sql_insert.cc	2011-05-25 14:16:06 +0000
@@ -658,6 +658,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
 		  bool ignore)
 {
   int error, res;
+  int err= true;
   bool transactional_table, joins_freed= FALSE;
   bool changed;
   bool was_insert_delayed= (table_list->lock_type ==  TL_WRITE_DELAYED);
@@ -730,7 +731,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
                            !ignore && (thd->variables.sql_mode &
                                        (MODE_STRICT_TRANS_TABLES |
                                         MODE_STRICT_ALL_TABLES))))
-    goto abort;
+    goto exit_without_my_ok;
 
   /* mysql_prepare_insert set table_list->table if it was not set */
   table= table_list->table;
@@ -761,10 +762,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
     if (values->elements != value_count)
     {
       my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
-      goto abort;
+      goto exit_without_my_ok;
     }
     if (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0))
-      goto abort;
+      goto exit_without_my_ok;
   }
   its.rewind ();
  
@@ -774,14 +775,12 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
   if (thd->lex->describe)
   {
     /*
-      Obviously INSERT without the SELECT is not suitable for EXPLAIN, since we
-      don't plan how read tables.
-      So we simply send "No tables used" and stop execution here.
+      Send "No tables used" and stop execution here since
+      there is no SELECT to explain.
     */
 
-    bool err= msg_describe("No tables used");
-    free_underlaid_joins(thd, &thd->lex->select_lex);
-    DBUG_RETURN(err);
+    err= explain_msg(thd, "No tables used");
+    goto exit_without_my_ok;
   }
 
   /*
@@ -811,7 +810,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
       (info.handle_duplicates == DUP_UPDATE) &&
       (table->next_number_field != NULL) &&
       rpl_master_has_bug(active_mi->rli, 24432, TRUE, NULL, NULL))
-    goto abort;
+    goto exit_without_my_ok;
 #endif
 
   error=0;
@@ -1085,7 +1084,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
     table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
   if (error)
-    goto abort;
+    goto exit_without_my_ok;
   if (values_list.elements == 1 && (!(thd->variables.option_bits & OPTION_WARNINGS) ||
 				    !thd->cuted_fields))
   {
@@ -1113,7 +1112,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
   thd->abort_on_warning= 0;
   DBUG_RETURN(FALSE);
 
-abort:
+exit_without_my_ok:
 #ifndef EMBEDDED_LIBRARY
   if (lock_type == TL_WRITE_DELAYED)
     end_delayed_insert(thd);
@@ -1123,7 +1122,7 @@ abort:
   if (!joins_freed)
     free_underlaid_joins(thd, &thd->lex->select_lex);
   thd->abort_on_warning= 0;
-  DBUG_RETURN(TRUE);
+  DBUG_RETURN(err || thd->is_error() || thd->killed);
 }
 
 

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2011-03-30 16:48:25 +0000
+++ b/sql/sql_parse.cc	2011-05-25 14:16:06 +0000
@@ -2943,7 +2943,7 @@ end_with_restore_list:
                                                  lex->ignore)))
       {
         if (lex->describe)
-          res= explain_data_modification(sel_result);
+          res= explain_data_modification_having_JOIN(thd, sel_result);
         else
         {
           res= handle_select(thd, lex, sel_result, OPTION_SETUP_TABLES_DONE);
@@ -3026,7 +3026,7 @@ end_with_restore_list:
         (del_result= new multi_delete(aux_tables, lex->table_count)))
     {
       if (lex->describe)
-        res= explain_data_modification(del_result);
+        res= explain_data_modification_having_JOIN(thd, del_result);
       else
       {
         res= mysql_select(thd, &select_lex->ref_pointer_array,

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-03-30 16:48:25 +0000
+++ b/sql/sql_select.cc	2011-05-25 14:16:06 +0000
@@ -2793,8 +2793,8 @@ JOIN::exec()
   if (!tables_list && (tables || !select_lex->with_sum_func))
   {                                           // Only test of functions
     if (select_options & SELECT_DESCRIBE)
-      msg_describe(this, zero_result_cause ? zero_result_cause 
-                                           : "No tables used");
+      explain_msg(thd, this, zero_result_cause ? zero_result_cause 
+                                               : "No tables used");
     else
     {
       if (result->send_result_set_metadata(*columns_list,
@@ -2889,11 +2889,11 @@ JOIN::exec()
       order=0;
     having= tmp_having;
     if (tables)
-      select_describe(this, need_tmp,
+      select_describe(thd, this, need_tmp,
                       order != 0 && !skip_sort_order,
                       select_distinct);
     else
-      msg_describe(this, "No tables used");
+      explain_msg(thd, this, "No tables used");
     DBUG_VOID_RETURN;
   }
 
@@ -11939,7 +11939,7 @@ return_zero_rows(JOIN *join, select_resu
 
   if (select_options & SELECT_DESCRIBE)
   {
-    msg_describe(join, info);
+    explain_msg(join->thd, join, info);
     DBUG_RETURN(0);
   }
 

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2011-03-30 16:48:25 +0000
+++ b/sql/sql_update.cc	2011-05-25 14:16:06 +0000
@@ -267,6 +267,8 @@ int mysql_update(THD *thd,
   uint          used_index, dup_key_found;
   bool          need_sort= TRUE;
   bool          reverse= FALSE;
+  bool          using_filesort;
+  bool          err= true;
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
   uint		want_privilege;
 #endif
@@ -396,9 +398,8 @@ int mysql_update(THD *thd,
   { // No matching records
     if (thd->lex->describe)
     {
-      bool err= msg_describe("No matching records");
-      free_underlaid_joins(thd, select_lex);
-      DBUG_RETURN(err);
+      err= explain_msg(thd, "Impossible WHERE");
+      goto exit_without_my_ok;
     }
 
     free_underlaid_joins(thd, select_lex);
@@ -414,6 +415,12 @@ int mysql_update(THD *thd,
   if (error || !limit ||
       (select && select->check_quick(thd, safe_update, limit)))
   {
+    if (thd->lex->describe && !error && !thd->is_error())
+    {
+      err= explain_msg(thd, "Impossible WHERE");
+      goto exit_without_my_ok;
+    }
+    
     delete select;
     free_underlaid_joins(thd, select_lex);
     /*
@@ -427,13 +434,6 @@ int mysql_update(THD *thd,
     {
       DBUG_RETURN(1);				// Error in where
     }
-    if (thd->lex->describe)
-    {
-      bool err= msg_describe("Impossible WHERE");
-      delete select;
-      free_underlaid_joins(thd, select_lex);
-      DBUG_RETURN(err);
-    }
     my_ok(thd);				// No matching records
     DBUG_RETURN(0);
   }
@@ -446,7 +446,7 @@ int mysql_update(THD *thd,
     {
       my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
 		 ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
-      goto err;
+      goto exit_without_my_ok;
     }
   }
   init_ftfuncs(thd, select_lex, 1);
@@ -465,13 +465,12 @@ int mysql_update(THD *thd,
     used_key_is_modified= is_key_used(table, used_index, table->write_set);
   }
 
+  using_filesort= order && (need_sort||used_key_is_modified);
   if (thd->lex->describe)
   {
-    bool err= table_describe(table, select, used_index, limit, 
-                             order && (need_sort||used_key_is_modified));
-    delete select;
-    free_underlaid_joins(thd, select_lex);
-    DBUG_RETURN(err);
+    err= explain_table_no_JOIN(thd, table, select, used_index,
+                               limit, using_filesort);
+    goto exit_without_my_ok;
   }
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
@@ -493,7 +492,7 @@ int mysql_update(THD *thd,
     }
 
     /* note: We avoid sorting if we sort on the used index */
-    if (order && (need_sort || used_key_is_modified))
+    if (using_filesort)
     {
       /*
 	Doing an ORDER BY;  Let filesort find and sort the rows we are going
@@ -514,7 +513,7 @@ int mysql_update(THD *thd,
                                                &examined_rows, &found_rows))
           == HA_POS_ERROR)
       {
-	goto err;
+	goto exit_without_my_ok;
       }
       thd->inc_examined_row_count(examined_rows);
       /*
@@ -535,11 +534,11 @@ int mysql_update(THD *thd,
       IO_CACHE tempfile;
       if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX,
 			   DISK_BUFFER_SIZE, MYF(MY_WME)))
-	goto err;
+	goto exit_without_my_ok;
 
       /* If quick select is used, initialize it before retrieving rows. */
       if (select && select->quick && select->quick->reset())
-        goto err;
+        goto exit_without_my_ok;
       table->file->try_semi_consistent_read(1);
 
       /*
@@ -616,7 +615,7 @@ int mysql_update(THD *thd,
 	error=1; /* purecov: inspected */
       select->file=tempfile;			// Read row ptrs from this file
       if (error >= 0)
-	goto err;
+	goto exit_without_my_ok;
     }
     if (table->key_read)
       table->restore_column_maps_after_mark_index();
@@ -626,7 +625,7 @@ int mysql_update(THD *thd,
     table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
   
   if (select && select->quick && select->quick->reset())
-    goto err;
+    goto exit_without_my_ok;
   table->file->try_semi_consistent_read(1);
   init_read_record(&info, thd, table, select, 0, 1, FALSE);
 
@@ -935,12 +934,12 @@ int mysql_update(THD *thd,
   *updated_return= updated;
   DBUG_RETURN((error >= 0 || thd->is_error()) ? 1 : 0);
 
-err:
+exit_without_my_ok:
   delete select;
   free_underlaid_joins(thd, select_lex);
   table->set_keyread(FALSE);
   thd->abort_on_warning= 0;
-  DBUG_RETURN(1);
+  DBUG_RETURN((err || thd->is_error() || thd->killed) ? 1 : 0);
 }
 
 /*
@@ -1363,7 +1362,7 @@ bool mysql_multi_update(THD *thd,
                                MODE_STRICT_ALL_TABLES));
 
   if (thd->lex->describe)
-    res= explain_data_modification(*result);
+    res= explain_data_modification_having_JOIN(thd, *result);
   else
   {
     List<Item> total_list;

=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc	2011-03-17 17:39:31 +0000
+++ b/sql/sql_view.cc	2011-05-25 14:16:06 +0000
@@ -1277,8 +1277,14 @@ bool mysql_make_view(THD *thd, File_pars
       underlying tables.
       Skip this step if we are opening view for prelocking only.
     */
-    if (!table->prelocking_placeholder &&
-        (old_lex->sql_command == SQLCOM_SELECT && old_lex->describe))
+    if (!table->prelocking_placeholder && old_lex->describe &&
+        (old_lex->sql_command == SQLCOM_SELECT ||
+         old_lex->sql_command == SQLCOM_INSERT ||
+         old_lex->sql_command == SQLCOM_INSERT_SELECT ||
+         old_lex->sql_command == SQLCOM_UPDATE ||
+         old_lex->sql_command == SQLCOM_UPDATE_MULTI ||
+         old_lex->sql_command == SQLCOM_DELETE ||
+         old_lex->sql_command == SQLCOM_DELETE_MULTI))
     {
       if (check_table_access(thd, SELECT_ACL, view_tables, FALSE,
                              UINT_MAX, TRUE) &&

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2011-03-30 16:48:25 +0000
+++ b/sql/sql_yacc.yy	2011-05-25 14:16:06 +0000
@@ -11371,39 +11371,16 @@ describe:
           opt_describe_column {}
         | describe_command opt_extended_describe
           { Lex->describe|= DESCRIBE_NORMAL; }
+          explanable_command
+          { Lex->select_lex.options|= SELECT_DESCRIBE; }
+        ;
+
+explanable_command:
           select
-          {
-            LEX *lex=Lex;
-            lex->select_lex.options|= SELECT_DESCRIBE;
-          }
-        | describe_command opt_extended_describe
-          { Lex->describe|= DESCRIBE_NORMAL; }
-          insert 
-          {
-            LEX *lex=Lex;
-            lex->select_lex.options|= SELECT_DESCRIBE;
-          }
-        | describe_command opt_extended_describe
-          { Lex->describe|= DESCRIBE_NORMAL; }
-          replace 
-          {
-            LEX *lex=Lex;
-            lex->select_lex.options|= SELECT_DESCRIBE;
-          }
-        | describe_command opt_extended_describe
-          { Lex->describe|= DESCRIBE_NORMAL; }
-          update 
-          {
-            LEX *lex=Lex;
-            lex->select_lex.options|= SELECT_DESCRIBE;
-          }
-        | describe_command opt_extended_describe
-          { Lex->describe|= DESCRIBE_NORMAL; }
-          delete 
-          {
-            LEX *lex=Lex;
-            lex->select_lex.options|= SELECT_DESCRIBE;
-          }
+        | insert
+        | replace
+        | update
+        | delete
         ;
 
 describe_command:

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (gleb.shchepa:3357 to 3358) Gleb Shchepa25 May