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#13906945 | Gleb Shchepa | 21 May |