List:Commits« Previous MessageNext Message »
From:Gleb Shchepa Date:May 11 2012 7:40pm
Subject:bzr push into mysql-trunk branch (gleb.shchepa:3823 to 3824) Bug#13906945
View as plain text  
 3824 Gleb Shchepa	2012-05-11
      Bug #13906945: EXPLAIN JSON DISPLAYS ATTACHED CONDITION WRONGLY                                      
                     IF INDEX_SUBQUERY                                                                     
                                                                                                           
      The value of the "attached_condition" string in JSON EXPLAIN                                         
      may display an outdated (unoptimized) expression text.                                               
                                                                                                           
                                                                                                           
      For top query, shallow_explain() writes attached_condition,                                          
      then explain_subqueries() runs JOIN::optimize() on subquery                                          
      which *transforms* subquery, so the subquery text printed                                            
      in top query's attached_condition becomes out-of-date.                                               
                                                                                                           
      The abstract "Lazy" class has been introduced to emulate                                             
      a lazy computation to evaluate expressions on demand.                                                 
                                                                                                           
      The Lazy_condition successor for this class has been                                                 
      introduced to defer Item tree pretty-printer call.     
     @ mysql-test/r/explain_json_all.result
        New test.                                                                                            
        Updates for old tests.
     @ mysql-test/r/explain_json_none.result
        New test.                                                                                            
        Updates for old tests.
     @ mysql-test/r/innodb_explain_json_non_select_all.result
        Updates for old tests.
     @ mysql-test/r/innodb_explain_json_non_select_none.result
        Updates for old tests.
     @ mysql-test/r/myisam_explain_json_non_select_all.result
        Updates for old tests.
     @ mysql-test/r/myisam_explain_json_non_select_none.result
        Updates for old tests.
     @ mysql-test/r/subquery_sj_mat_nosj.result
        Updates for old tests.
     @ mysql-test/r/subquery_sj_none.result
        Updates for old tests.
     @ mysql-test/r/subquery_sj_none_bka.result
        Updates for old tests.
     @ mysql-test/r/subquery_sj_none_bka_nixbnl.result
        Updates for old tests.
     @ mysql-test/r/subquery_sj_none_bkaunique.result
        Updates for old tests.
     @ sql/opt_explain.cc
        * The Lazy_condition successor for the Lazy class has been                                               
          introduced to defer Item tree pretty-printer call.
        * col_attached_condition string value has been replaced
          with a deferred calculation object to compute it later.
     @ sql/opt_explain_format.h
        * The abstract "Lazy" class has been introduced to emulate                                           
          a lazy computation to evaluate procedures on demand.                                               
        * The mem_root_str class has been modified to accept                                                 
          Lazy class object for further evaluation.
     @ sql/opt_explain_traditional.cc
        Minor update.

    modified:
      mysql-test/r/explain_json_all.result
      mysql-test/r/explain_json_none.result
      mysql-test/r/innodb_explain_json_non_select_all.result
      mysql-test/r/innodb_explain_json_non_select_none.result
      mysql-test/r/myisam_explain_json_non_select_all.result
      mysql-test/r/myisam_explain_json_non_select_none.result
      mysql-test/r/subquery_sj_mat_nosj.result
      mysql-test/r/subquery_sj_none.result
      mysql-test/r/subquery_sj_none_bka.result
      mysql-test/r/subquery_sj_none_bka_nixbnl.result
      mysql-test/r/subquery_sj_none_bkaunique.result
      sql/opt_explain.cc
      sql/opt_explain_format.h
      sql/opt_explain_traditional.cc
 3823 Vasil Dimov	2012-05-11
      Non-functional change, rename:
      
      dict_stats_delete_index_stats() -> dict_stats_drop_index()
      dict_stats_delete_table_stats() -> dict_stats_drop_table()

    modified:
      storage/innobase/dict/dict0stats.cc
      storage/innobase/handler/ha_innodb.cc
      storage/innobase/handler/handler0alter.cc
      storage/innobase/include/dict0stats.h
=== modified file 'mysql-test/r/explain_json_all.result'
--- a/mysql-test/r/explain_json_all.result	2012-05-02 07:44:09 +0000
+++ b/mysql-test/r/explain_json_all.result	2012-05-11 19:37:22 +0000
@@ -266,7 +266,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 7,
       "filtered": 100,
-      "attached_condition": "(<in_optimizer>(`test`.`t1`.`i`,<exists>(select 1 from `test`.`t2` where ((`test`.`t1`.`i` = 10) and (<cache>(`test`.`t1`.`i`) = `test`.`t2`.`i`)))) or <in_optimizer>(`test`.`t1`.`i`,`test`.`t1`.`i` in ( <materialize> (select `test`.`t4`.`i` from `test`.`t4` ), <primary_index_lookup>(`test`.`t1`.`i` in <temporary table> on distinct_key where ((`test`.`t1`.`i` = `materialized subselect`.`i`))))))",
+      "attached_condition": "(<in_optimizer>(`test`.`t1`.`i`,<exists>(select 1 from `test`.`t2` where ((`test`.`t1`.`i` = 10) and (<cache>(`test`.`t1`.`i`) = `test`.`t2`.`i`)))) or <in_optimizer>(`test`.`t1`.`i`,`test`.`t1`.`i` in ( <materialize> (select NULL from `test`.`t4` ), <primary_index_lookup>(`test`.`t1`.`i` in <temporary table> on distinct_key where ((`test`.`t1`.`i` = `materialized subselect`.`i`))))))",
       "attached_subqueries": [
         {
           "using_temporary_table": true,
@@ -899,7 +899,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 1,
       "filtered": 100,
-      "attached_condition": "exists(select `test`.`t2`.`c1` from (`test`.`t2` join `test`.`t3` on((`test`.`t3`.`c1` = `test`.`t2`.`c1`))) where ((`test`.`t2`.`c2` <> `test`.`t1`.`c1`) and (`test`.`t2`.`c2` = (select min(`test`.`t3`.`c1`) from `test`.`t3`))))",
+      "attached_condition": "exists(select `test`.`t2`.`c1` from `test`.`t2` join `test`.`t3` where ((`test`.`t2`.`c1` = `test`.`t3`.`c1`) and (`test`.`t2`.`c2` = (select min(`test`.`t3`.`c1`) from `test`.`t3`)) and ((select min(`test`.`t3`.`c1`) from `test`.`t3`) <> `test`.`t1`.`c1`)))",
       "attached_subqueries": [
         {
           "dependent": true,

=== modified file 'mysql-test/r/explain_json_none.result'
--- a/mysql-test/r/explain_json_none.result	2012-05-02 07:44:09 +0000
+++ b/mysql-test/r/explain_json_none.result	2012-05-11 19:37:22 +0000
@@ -267,7 +267,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 7,
       "filtered": 100,
-      "attached_condition": "(<in_optimizer>(`test`.`t1`.`i`,<exists>(select 1 from `test`.`t2` where ((`test`.`t1`.`i` = 10) and (<cache>(`test`.`t1`.`i`) = `test`.`t2`.`i`)))) or <in_optimizer>(`test`.`t1`.`i`,<exists>(select 1 from `test`.`t4` where (<cache>(`test`.`t1`.`i`) = `test`.`t4`.`i`))))",
+      "attached_condition": "(<in_optimizer>(`test`.`t1`.`i`,<exists>(select 1 from `test`.`t2` where ((`test`.`t1`.`i` = 10) and (<cache>(`test`.`t1`.`i`) = `test`.`t2`.`i`)))) or <in_optimizer>(`test`.`t1`.`i`,<exists>(select 1 from `test`.`t4` where 0)))",
       "attached_subqueries": [
         {
           "dependent": true,
@@ -899,7 +899,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 1,
       "filtered": 100,
-      "attached_condition": "exists(select `test`.`t2`.`c1` from (`test`.`t2` join `test`.`t3` on((`test`.`t3`.`c1` = `test`.`t2`.`c1`))) where ((`test`.`t2`.`c2` <> `test`.`t1`.`c1`) and (`test`.`t2`.`c2` = (select min(`test`.`t3`.`c1`) from `test`.`t3`))))",
+      "attached_condition": "exists(select `test`.`t2`.`c1` from `test`.`t2` join `test`.`t3` where ((`test`.`t2`.`c1` = `test`.`t3`.`c1`) and (`test`.`t2`.`c2` = (select min(`test`.`t3`.`c1`) from `test`.`t3`)) and ((select min(`test`.`t3`.`c1`) from `test`.`t3`) <> `test`.`t1`.`c1`)))",
       "attached_subqueries": [
         {
           "dependent": true,
@@ -1007,7 +1007,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 3,
       "filtered": 100,
-      "attached_condition": "(<in_optimizer>(`test`.`t5`.`c`,<exists>(select 1 from (`test`.`t1` join `test`.`t2` on((`test`.`t2`.`c_key` = `test`.`t1`.`c_key`))) where (<cache>(`test`.`t5`.`c`) = `test`.`t2`.`c`))) and <in_optimizer>(`test`.`t5`.`c`,<exists>(select 1 from (`test`.`t3` join `test`.`t4` on((`test`.`t4`.`c_key` = `test`.`t3`.`c_key`))) where (<cache>(`test`.`t5`.`c`) = `test`.`t4`.`c`))))",
+      "attached_condition": "(<in_optimizer>(`test`.`t5`.`c`,<exists>(select 1 from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`c_key` = `test`.`t2`.`c_key`) and (<cache>(`test`.`t5`.`c`) = `test`.`t2`.`c`)))) and <in_optimizer>(`test`.`t5`.`c`,<exists>(select 1 from `test`.`t3` join `test`.`t4` where ((`test`.`t3`.`c_key` = `test`.`t4`.`c_key`) and (<cache>(`test`.`t5`.`c`) = `test`.`t4`.`c`)))))",
       "attached_subqueries": [
         {
           "dependent": true,
@@ -1773,7 +1773,7 @@ EXPLAIN
       "rows": 4,
       "filtered": 100,
       "using_index": true,
-      "attached_condition": "<in_optimizer>(`test`.`t2`.`a`,<exists>(select 1 from `test`.`t1` where ((`test`.`t1`.`b` <> 30) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))))",
+      "attached_condition": "<in_optimizer>(`test`.`t2`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on PRIMARY where ((`test`.`t1`.`b` <> 30) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))))",
       "attached_subqueries": [
         {
           "dependent": true,

=== modified file 'mysql-test/r/innodb_explain_json_non_select_all.result'
--- a/mysql-test/r/innodb_explain_json_non_select_all.result	2012-04-23 08:14:28 +0000
+++ b/mysql-test/r/innodb_explain_json_non_select_all.result	2012-05-11 19:37:22 +0000
@@ -479,7 +479,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 3,
       "filtered": 100,
-      "attached_condition": "<in_optimizer>(1,<exists>(select 1 from `test`.`t2` where ((`test`.`t2`.`b` < 3) and (<cache>(1) = 1))))",
+      "attached_condition": "<in_optimizer>(1,<exists>(select 1 from `test`.`t2` where (`test`.`t2`.`b` < 3)))",
       "attached_subqueries": [
         {
           "dependent": true,

=== modified file 'mysql-test/r/innodb_explain_json_non_select_none.result'
--- a/mysql-test/r/innodb_explain_json_non_select_none.result	2012-04-23 08:14:28 +0000
+++ b/mysql-test/r/innodb_explain_json_non_select_none.result	2012-05-11 19:37:22 +0000
@@ -478,7 +478,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 3,
       "filtered": 100,
-      "attached_condition": "<in_optimizer>(1,<exists>(select 1 from `test`.`t2` where ((`test`.`t2`.`b` < 3) and (<cache>(1) = 1))))",
+      "attached_condition": "<in_optimizer>(1,<exists>(select 1 from `test`.`t2` where (`test`.`t2`.`b` < 3)))",
       "attached_subqueries": [
         {
           "dependent": true,
@@ -5949,7 +5949,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 3,
       "filtered": 100,
-      "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from (select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` where (<cache>(`test`.`t1`.`a`) = `x`.`b`)))",
+      "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in x on auto_key0)))",
       "attached_subqueries": [
         {
           "dependent": true,
@@ -6047,7 +6047,7 @@ EXPLAIN
           "access_type": "ALL",
           "rows": 3,
           "filtered": 100,
-          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from (select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` where (<cache>(`test`.`t1`.`a`) = `x`.`b`)))",
+          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in x on auto_key0)))",
           "attached_subqueries": [
             {
               "dependent": true,
@@ -6127,7 +6127,7 @@ EXPLAIN
           "access_type": "ALL",
           "rows": 3,
           "filtered": 100,
-          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from (select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` where (<cache>(`test`.`t1`.`a`) = `x`.`b`)))",
+          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in x on auto_key0)))",
           "attached_subqueries": [
             {
               "dependent": true,
@@ -6237,7 +6237,7 @@ EXPLAIN
           "access_type": "ALL",
           "rows": 3,
           "filtered": 100,
-          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from (select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` where (<cache>(`test`.`t1`.`a`) = `x`.`b`)))",
+          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in x on auto_key0)))",
           "attached_subqueries": [
             {
               "dependent": true,
@@ -6332,7 +6332,7 @@ EXPLAIN
           "access_type": "ALL",
           "rows": 3,
           "filtered": 100,
-          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from (select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` where (<cache>(`test`.`t1`.`a`) = `x`.`b`)))",
+          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in x on auto_key0)))",
           "attached_subqueries": [
             {
               "dependent": true,

=== modified file 'mysql-test/r/myisam_explain_json_non_select_all.result'
--- a/mysql-test/r/myisam_explain_json_non_select_all.result	2012-04-23 08:14:28 +0000
+++ b/mysql-test/r/myisam_explain_json_non_select_all.result	2012-05-11 19:37:22 +0000
@@ -459,7 +459,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 3,
       "filtered": 100,
-      "attached_condition": "<in_optimizer>(1,<exists>(select 1 from `test`.`t2` where ((`test`.`t2`.`b` < 3) and (<cache>(1) = 1))))",
+      "attached_condition": "<in_optimizer>(1,<exists>(select 1 from `test`.`t2` where (`test`.`t2`.`b` < 3)))",
       "attached_subqueries": [
         {
           "dependent": true,

=== modified file 'mysql-test/r/myisam_explain_json_non_select_none.result'
--- a/mysql-test/r/myisam_explain_json_non_select_none.result	2012-04-23 08:14:28 +0000
+++ b/mysql-test/r/myisam_explain_json_non_select_none.result	2012-05-11 19:37:22 +0000
@@ -458,7 +458,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 3,
       "filtered": 100,
-      "attached_condition": "<in_optimizer>(1,<exists>(select 1 from `test`.`t2` where ((`test`.`t2`.`b` < 3) and (<cache>(1) = 1))))",
+      "attached_condition": "<in_optimizer>(1,<exists>(select 1 from `test`.`t2` where (`test`.`t2`.`b` < 3)))",
       "attached_subqueries": [
         {
           "dependent": true,
@@ -5818,7 +5818,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 3,
       "filtered": 100,
-      "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from (select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` where (<cache>(`test`.`t1`.`a`) = `x`.`b`)))",
+      "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in x on auto_key0)))",
       "attached_subqueries": [
         {
           "dependent": true,
@@ -5913,7 +5913,7 @@ EXPLAIN
           "access_type": "ALL",
           "rows": 3,
           "filtered": 100,
-          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from (select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` where (<cache>(`test`.`t1`.`a`) = `x`.`b`)))",
+          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in x on auto_key0)))",
           "attached_subqueries": [
             {
               "dependent": true,
@@ -5993,7 +5993,7 @@ EXPLAIN
           "access_type": "ALL",
           "rows": 3,
           "filtered": 100,
-          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from (select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` where (<cache>(`test`.`t1`.`a`) = `x`.`b`)))",
+          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in x on auto_key0)))",
           "attached_subqueries": [
             {
               "dependent": true,
@@ -6101,7 +6101,7 @@ EXPLAIN
           "access_type": "ALL",
           "rows": 3,
           "filtered": 100,
-          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from (select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` where (<cache>(`test`.`t1`.`a`) = `x`.`b`)))",
+          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in x on auto_key0)))",
           "attached_subqueries": [
             {
               "dependent": true,
@@ -6196,7 +6196,7 @@ EXPLAIN
           "access_type": "ALL",
           "rows": 3,
           "filtered": 100,
-          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from (select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` where (<cache>(`test`.`t1`.`a`) = `x`.`b`)))",
+          "attached_condition": "<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in x on auto_key0)))",
           "attached_subqueries": [
             {
               "dependent": true,

=== modified file 'mysql-test/r/subquery_sj_mat_nosj.result'
--- a/mysql-test/r/subquery_sj_mat_nosj.result	2012-03-26 10:29:07 +0000
+++ b/mysql-test/r/subquery_sj_mat_nosj.result	2012-05-11 19:37:22 +0000
@@ -5566,7 +5566,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 16,
       "filtered": 100,
-      "attached_condition": "(<in_optimizer>(`test`.`t2`.`Code`,`test`.`t2`.`Code` in ( <materialize> (select `test`.`t1`.`Country` from `test`.`t1` where (`test`.`t1`.`Population` > 5000000) ), <primary_index_lookup>(`test`.`t2`.`Code` in <temporary table> on distinct_key where ((`test`.`t2`.`Code` = `materialized subselect`.`Country`))))) and <in_optimizer>(`test`.`t2`.`Code`,<exists>(select 1 from `test`.`t3` where ((`test`.`t3`.`Language` = 'English') and (`test`.`t3`.`Percentage` > 10) and (`test`.`t2`.`Population` > 100000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t3`.`Country`)))))",
+      "attached_condition": "(<in_optimizer>(`test`.`t2`.`Code`,`test`.`t2`.`Code` in ( <materialize> (select `test`.`t1`.`Country` from `test`.`t1` where (`test`.`t1`.`Population` > 5000000) ), <primary_index_lookup>(`test`.`t2`.`Code` in <temporary table> on distinct_key where ((`test`.`t2`.`Code` = `materialized subselect`.`Country`))))) and <in_optimizer>(`test`.`t2`.`Code`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`Code`) in t3 on PRIMARY where ((`test`.`t3`.`Language` = 'English') and (`test`.`t3`.`Percentage` > 10) and (`test`.`t2`.`Population` > 100000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t3`.`Country`))))))",
       "attached_subqueries": [
         {
           "dependent": true,
@@ -7346,7 +7346,7 @@ EXPLAIN
             ],
             "rows": 11,
             "filtered": 100,
-            "attached_condition": "(<in_optimizer>((`test`.`grandparent1`.`col_int_nokey`,`test`.`grandparent1`.`col_int_key`),(`test`.`grandparent1`.`col_int_nokey`,`test`.`grandparent1`.`col_int_key`) in ( <materialize> (select `test`.`parent1`.`col_int_key` AS `p1`,`test`.`parent1`.`col_int_key` AS `p2` from (`test`.`t1` `parent1` left join `test`.`t2` `parent2` on((`test`.`parent1`.`col_int_nokey` = `test`.`parent2`.`col_int_key`))) ), <primary_index_lookup>(`test`.`grandparent1`.`col_int_nokey` in <temporary table> on distinct_key where ((`test`.`grandparent1`.`col_int_nokey` = `materialized subselect`.`p1`) and (`test`.`grandparent1`.`col_int_key` = `materialized subselect`.`p2`))))) and (`test`.`grandparent1`.`col_int_key` <> 3))",
+            "attached_condition": "(<in_optimizer>((`test`.`grandparent1`.`col_int_nokey`,`test`.`grandparent1`.`col_int_key`),(`test`.`grandparent1`.`col_int_nokey`,`test`.`grandparent1`.`col_int_key`) in ( <materialize> (select `test`.`parent1`.`col_int_key` AS `p1`,`test`.`parent1`.`col_int_key` AS `p2` from `test`.`t1` `parent1` left join `test`.`t2` `parent2` on((`test`.`parent1`.`col_int_nokey` = `test`.`parent2`.`col_int_key`)) where 1 ), <primary_index_lookup>(`test`.`grandparent1`.`col_int_nokey` in <temporary table> on distinct_key where ((`test`.`grandparent1`.`col_int_nokey` = `materialized subselect`.`p1`) and (`test`.`grandparent1`.`col_int_key` = `materialized subselect`.`p2`))))) and (`test`.`grandparent1`.`col_int_key` <> 3))",
             "attached_subqueries": [
               {
                 "using_temporary_table": true,

=== modified file 'mysql-test/r/subquery_sj_none.result'
--- a/mysql-test/r/subquery_sj_none.result	2012-03-26 10:29:07 +0000
+++ b/mysql-test/r/subquery_sj_none.result	2012-05-11 19:37:22 +0000
@@ -5486,7 +5486,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 16,
       "filtered": 100,
-      "attached_condition": "(<in_optimizer>(`test`.`t2`.`Code`,<exists>(select 1 from `test`.`t1` where ((`test`.`t1`.`Population` > 5000000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t1`.`Country`)))) and <in_optimizer>(`test`.`t2`.`Code`,<exists>(select 1 from `test`.`t3` where ((`test`.`t3`.`Language` = 'English') and (`test`.`t3`.`Percentage` > 10) and (`test`.`t2`.`Population` > 100000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t3`.`Country`)))))",
+      "attached_condition": "(<in_optimizer>(`test`.`t2`.`Code`,<exists>(select 1 from `test`.`t1` where ((`test`.`t1`.`Population` > 5000000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t1`.`Country`)))) and <in_optimizer>(`test`.`t2`.`Code`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`Code`) in t3 on PRIMARY where ((`test`.`t3`.`Language` = 'English') and (`test`.`t3`.`Percentage` > 10) and (`test`.`t2`.`Population` > 100000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t3`.`Country`))))))",
       "attached_subqueries": [
         {
           "dependent": true,

=== modified file 'mysql-test/r/subquery_sj_none_bka.result'
--- a/mysql-test/r/subquery_sj_none_bka.result	2012-03-26 10:29:07 +0000
+++ b/mysql-test/r/subquery_sj_none_bka.result	2012-05-11 19:37:22 +0000
@@ -5487,7 +5487,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 16,
       "filtered": 100,
-      "attached_condition": "(<in_optimizer>(`test`.`t2`.`Code`,<exists>(select 1 from `test`.`t1` where ((`test`.`t1`.`Population` > 5000000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t1`.`Country`)))) and <in_optimizer>(`test`.`t2`.`Code`,<exists>(select 1 from `test`.`t3` where ((`test`.`t3`.`Language` = 'English') and (`test`.`t3`.`Percentage` > 10) and (`test`.`t2`.`Population` > 100000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t3`.`Country`)))))",
+      "attached_condition": "(<in_optimizer>(`test`.`t2`.`Code`,<exists>(select 1 from `test`.`t1` where ((`test`.`t1`.`Population` > 5000000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t1`.`Country`)))) and <in_optimizer>(`test`.`t2`.`Code`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`Code`) in t3 on PRIMARY where ((`test`.`t3`.`Language` = 'English') and (`test`.`t3`.`Percentage` > 10) and (`test`.`t2`.`Population` > 100000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t3`.`Country`))))))",
       "attached_subqueries": [
         {
           "dependent": true,

=== modified file 'mysql-test/r/subquery_sj_none_bka_nixbnl.result'
--- a/mysql-test/r/subquery_sj_none_bka_nixbnl.result	2012-03-26 10:29:07 +0000
+++ b/mysql-test/r/subquery_sj_none_bka_nixbnl.result	2012-05-11 19:37:22 +0000
@@ -5486,7 +5486,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 16,
       "filtered": 100,
-      "attached_condition": "(<in_optimizer>(`test`.`t2`.`Code`,<exists>(select 1 from `test`.`t1` where ((`test`.`t1`.`Population` > 5000000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t1`.`Country`)))) and <in_optimizer>(`test`.`t2`.`Code`,<exists>(select 1 from `test`.`t3` where ((`test`.`t3`.`Language` = 'English') and (`test`.`t3`.`Percentage` > 10) and (`test`.`t2`.`Population` > 100000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t3`.`Country`)))))",
+      "attached_condition": "(<in_optimizer>(`test`.`t2`.`Code`,<exists>(select 1 from `test`.`t1` where ((`test`.`t1`.`Population` > 5000000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t1`.`Country`)))) and <in_optimizer>(`test`.`t2`.`Code`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`Code`) in t3 on PRIMARY where ((`test`.`t3`.`Language` = 'English') and (`test`.`t3`.`Percentage` > 10) and (`test`.`t2`.`Population` > 100000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t3`.`Country`))))))",
       "attached_subqueries": [
         {
           "dependent": true,

=== modified file 'mysql-test/r/subquery_sj_none_bkaunique.result'
--- a/mysql-test/r/subquery_sj_none_bkaunique.result	2012-03-26 10:29:07 +0000
+++ b/mysql-test/r/subquery_sj_none_bkaunique.result	2012-05-11 19:37:22 +0000
@@ -5488,7 +5488,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 16,
       "filtered": 100,
-      "attached_condition": "(<in_optimizer>(`test`.`t2`.`Code`,<exists>(select 1 from `test`.`t1` where ((`test`.`t1`.`Population` > 5000000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t1`.`Country`)))) and <in_optimizer>(`test`.`t2`.`Code`,<exists>(select 1 from `test`.`t3` where ((`test`.`t3`.`Language` = 'English') and (`test`.`t3`.`Percentage` > 10) and (`test`.`t2`.`Population` > 100000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t3`.`Country`)))))",
+      "attached_condition": "(<in_optimizer>(`test`.`t2`.`Code`,<exists>(select 1 from `test`.`t1` where ((`test`.`t1`.`Population` > 5000000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t1`.`Country`)))) and <in_optimizer>(`test`.`t2`.`Code`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`Code`) in t3 on PRIMARY where ((`test`.`t3`.`Language` = 'English') and (`test`.`t3`.`Percentage` > 10) and (`test`.`t2`.`Population` > 100000) and (<cache>(`test`.`t2`.`Code`) = `test`.`t3`.`Country`))))))",
       "attached_subqueries": [
         {
           "dependent": true,

=== modified file 'sql/opt_explain.cc'
--- a/sql/opt_explain.cc	2012-03-21 21:19:11 +0000
+++ b/sql/opt_explain.cc	2012-05-11 19:37:22 +0000
@@ -59,6 +59,20 @@ protected:
   JOIN::ORDER_with_src group_list; //< GROUP BY item tee list
 
 protected:
+  class Lazy_condition: public Lazy
+  {
+    Item *const condition;
+  public:
+    Lazy_condition(Item *condition_arg): condition(condition_arg) {}
+    virtual bool eval(String *ret)
+    {
+      ret->length(0);
+      if (condition)
+        condition->print(ret, QT_ORDINARY);
+      return false;
+    }
+  };
+
   explicit Explain(Explain_context_enum context_type_arg,
                    THD *thd_arg, JOIN *join_arg= NULL)
   : thd(thd_arg),
@@ -945,15 +959,11 @@ bool Explain_table_base::explain_extra_c
       {
         if (fmt->is_hierarchical())
         {
-          StringBuffer<160> buff(cs);
-          if (tab)
-          {
-            if (tab->condition())
-              tab->condition()->print(&buff, QT_ORDINARY);
-          }
-          else
-            select->cond->print(&buff, QT_ORDINARY);
-          fmt->entry()->col_attached_condition.set(buff);
+          Lazy_condition *c= new Lazy_condition(tab ? tab->condition()
+                                                    : select->cond);
+          if (c == NULL)
+            return true;
+          fmt->entry()->col_attached_condition.set(c);
         }
         else if (push_extra(ET_USING_WHERE))
           return true;
@@ -1304,10 +1314,10 @@ bool Explain_join::explain_extra()
     {
       if (fmt->is_hierarchical())
       {
-        StringBuffer<160> buff(cs);
-        if (tab &&  tab->condition())
-          tab->condition()->print(&buff, QT_ORDINARY);
-        fmt->entry()->col_attached_condition.set(buff);
+        Lazy_condition *c= new Lazy_condition(tab->condition());
+        if (c == NULL)
+          return true;
+        fmt->entry()->col_attached_condition.set(c);
       }
       else if (push_extra(ET_USING_WHERE))
         return true;

=== modified file 'sql/opt_explain_format.h'
--- a/sql/opt_explain_format.h	2012-02-29 11:17:52 +0000
+++ b/sql/opt_explain_format.h	2012-05-11 19:37:22 +0000
@@ -104,6 +104,25 @@ enum Extra_tag
 
 
 /**
+  Emulate lazy computation
+*/
+class Lazy: public Sql_alloc
+{
+public:
+  virtual ~Lazy() {}
+
+  /**
+    Deferred evaluation of encapsulated expression
+
+    @param [out] ret    Return string value
+
+    @retval false       Success
+    @retval true        Failure (OOM)
+  */
+  virtual bool eval(String *ret)= 0;
+};
+
+/**
   Base class for all EXPLAIN context descriptor classes
 
   In structured EXPLAIN implementation Explain_context is a base class for
@@ -173,20 +192,38 @@ public:
     in the most cases, those input strings must have the same lifetime as
     Item_string objects, i.e. lifetime of MEM_ROOT.
     This class allocates input parameters for Item_string objects in MEM_ROOT.
+
+    @note Call to is_empty() is necessary before the access to "str" and
+          "length" fields, since is_empty() may trigger an evaluation of
+          an associated expression that updates these fields.
   */
   struct mem_root_str
   {
     const char *str;
     size_t length;
+    Lazy *deferred; //< encapsulated expression to evaluate it later (on demand)
     
     mem_root_str() { cleanup(); }
     void cleanup()
     {
       str= NULL;
       length= 0;
+      deferred= NULL;
+    }
+    bool is_empty()
+    {
+      if (deferred)
+      {
+        StringBuffer<128> buff(system_charset_info);
+        if (deferred->eval(&buff) || set(buff))
+        {
+          DBUG_ASSERT(!"OOM!");
+          return true; // ignore OOM
+        }
+        deferred= NULL; // prevent double evaluation, if any
+      }
+      return str == NULL;
     }
-    bool is_empty() const { return str == NULL; }
-
     bool set(const char *str_arg)
     {
       return set(str_arg, strlen(str_arg));
@@ -205,12 +242,24 @@ public:
     */
     bool set(const char *str_arg, size_t length_arg)
     {
+      deferred= NULL;
       if (!(str= strndup_root(current_thd->mem_root, str_arg, length_arg)))
         return true; /* purecov: inspected */
       length= length_arg;
       return false;
     }
     /**
+      Save expression for further evaluation
+
+      @param x  Expression
+    */
+    void set(Lazy *x)
+    {
+      deferred= x;
+      str= NULL;
+      length= 0;
+    }
+    /**
       Make a copy of string constant
 
       Variant of set() usable when the str_arg argument lives longer
@@ -222,6 +271,7 @@ public:
     }
     void set_const(const char *str_arg, size_t length_arg)
     {
+      deferred= NULL;
       str= str_arg;
       length= length_arg;
     }

=== modified file 'sql/opt_explain_traditional.cc'
--- a/sql/opt_explain_traditional.cc	2012-02-29 11:17:52 +0000
+++ b/sql/opt_explain_traditional.cc	2012-05-11 19:37:22 +0000
@@ -63,7 +63,7 @@ bool Explain_format_traditional::send_he
           current_thd->send_explain_fields(output));
 }
 
-static bool push(List<Item> *items, const qep_row::mem_root_str &s,
+static bool push(List<Item> *items, qep_row::mem_root_str &s,
                  Item_null *nil)
 {
   if (s.is_empty())

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (gleb.shchepa:3823 to 3824) Bug#13906945Gleb Shchepa21 May