From 5ead4083ec052f458f13dc0bfbc2184dac7ee133 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 8 Jul 2011 16:39:28 -0700 Subject: [PATCH] Fixed LP bug #806510. The bug was caused by an incorrect code of the function Item_direct_view_ref::replace_equal_field introduced in the patch for bugs 717577, 724942. The function erroneously returned the wrapped field instead of the Item_direct_view_ref object itself in the cases when no replacement happened. The bug masked two other minor bugs that could result in not quite correct output of the EXPLAIN command for some queries. They were fixed in the patch as well. --- mysql-test/r/derived_view.result | 52 ++++++++++++++++++++++++++++++++ mysql-test/r/join_cache.result | 2 +- mysql-test/t/derived_view.test | 43 ++++++++++++++++++++++++++ sql/item.cc | 2 +- sql/sql_select.cc | 5 +-- 5 files changed, 100 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index bc8fec82275..fed5b23dc7b 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -848,3 +848,55 @@ Warnings: Note 1003 select `test`.`t3`.`b` AS `b`,`test`.`t1`.`a` AS `a` from `test`.`t3` left join (`test`.`t2` join `test`.`t1`) on((`test`.`t3`.`a` <> 0)) where ((`test`.`t1`.`a` = `test`.`t1`.`a`) or (`test`.`t3`.`b` <> 0)) DROP VIEW v1; DROP TABLE t1,t2,t3; +# +# LP bug #806510: subquery with outer reference +# to a derived_table/view +# +CREATE TABLE t1 (a int) ; +INSERT INTO t1 VALUES (4), (NULL); +CREATE TABLE t2 (a int) ; +INSERT INTO t2 VALUES (8), (0); +CREATE TABLE t3 (a int, b int) ; +INSERT INTO t3 VALUES (7,8); +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT * FROM t1 t +WHERE EXISTS (SELECT t3.a FROM t3, t2 +WHERE t2.a = t3.b AND t.a != 0); +a +4 +EXPLAIN +SELECT * FROM t1 t +WHERE EXISTS (SELECT t3.a FROM t3, t2 +WHERE t2.a = t3.b AND t.a != 0); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t3 system NULL NULL NULL NULL 1 +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where +SELECT * FROM (SELECT * FROM t1) t +WHERE EXISTS (SELECT t3.a FROM t3, t2 +WHERE t2.a = t3.b AND t.a != 0); +a +4 +EXPLAIN +SELECT * FROM (SELECT * FROM t1) t +WHERE EXISTS (SELECT t3.a FROM t3, t2 +WHERE t2.a = t3.b AND t.a != 0); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +3 DEPENDENT SUBQUERY t3 system NULL NULL NULL NULL 1 +3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where +SELECT * FROM v1 t +WHERE EXISTS (SELECT t3.a FROM t3, t2 +WHERE t2.a = t3.b AND t.a != 0); +a +4 +EXPLAIN +SELECT * FROM v1 t +WHERE EXISTS (SELECT t3.a FROM t3, t2 +WHERE t2.a = t3.b AND t.a != 0); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t3 system NULL NULL NULL NULL 1 +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where +DROP VIEW v1; +DROP TABLE t1,t2,t3; diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result index 7b890e4d4aa..e352d0b5888 100644 --- a/mysql-test/r/join_cache.result +++ b/mysql-test/r/join_cache.result @@ -3033,7 +3033,7 @@ t6.formattypeid IN (2) AND (t3.formatid IN (31, 8, 76)) AND t1.metaid = t2.metaid AND t1.affiliateid = '2'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t6 system PRIMARY NULL NULL NULL 1 -1 SIMPLE t1 ref t1_affiliateid,t1_metaid t1_affiliateid 4 const 1 Using index condition +1 SIMPLE t1 ref t1_affiliateid,t1_metaid t1_affiliateid 4 const 1 1 SIMPLE t4 ref PRIMARY,t4_formatclassid,t4_formats_idx t4_formats_idx 1 const 1 Using index condition; Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan 1 SIMPLE t5 eq_ref PRIMARY,t5_formattypeid PRIMARY 4 test.t4.formatclassid 1 Using where; Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan 1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.metaid 1 Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test index e5c64840d39..26f428571ee 100644 --- a/mysql-test/t/derived_view.test +++ b/mysql-test/t/derived_view.test @@ -460,3 +460,46 @@ SELECT t3.b, v1.a DROP VIEW v1; DROP TABLE t1,t2,t3; + +--echo # +--echo # LP bug #806510: subquery with outer reference +--echo # to a derived_table/view +--echo # + +CREATE TABLE t1 (a int) ; +INSERT INTO t1 VALUES (4), (NULL); + +CREATE TABLE t2 (a int) ; +INSERT INTO t2 VALUES (8), (0); + +CREATE TABLE t3 (a int, b int) ; +INSERT INTO t3 VALUES (7,8); + +CREATE VIEW v1 AS SELECT * FROM t1; + +SELECT * FROM t1 t + WHERE EXISTS (SELECT t3.a FROM t3, t2 + WHERE t2.a = t3.b AND t.a != 0); +EXPLAIN +SELECT * FROM t1 t + WHERE EXISTS (SELECT t3.a FROM t3, t2 + WHERE t2.a = t3.b AND t.a != 0); + +SELECT * FROM (SELECT * FROM t1) t + WHERE EXISTS (SELECT t3.a FROM t3, t2 + WHERE t2.a = t3.b AND t.a != 0); +EXPLAIN +SELECT * FROM (SELECT * FROM t1) t + WHERE EXISTS (SELECT t3.a FROM t3, t2 + WHERE t2.a = t3.b AND t.a != 0); + +SELECT * FROM v1 t + WHERE EXISTS (SELECT t3.a FROM t3, t2 + WHERE t2.a = t3.b AND t.a != 0); +EXPLAIN +SELECT * FROM v1 t + WHERE EXISTS (SELECT t3.a FROM t3, t2 + WHERE t2.a = t3.b AND t.a != 0); + +DROP VIEW v1; +DROP TABLE t1,t2,t3; diff --git a/sql/item.cc b/sql/item.cc index 0f549b914eb..d3a43818d23 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7527,7 +7527,7 @@ Item *Item_direct_view_ref::replace_equal_field(uchar *arg) field_item->set_item_equal(item_equal); Item *item= field_item->replace_equal_field(arg); field_item->set_item_equal(0); - return item; + return item != field_item ? item : this; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 56aabb8589c..8bdddbdbc9b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7383,7 +7383,7 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables, maybe_null ? key_buff : 0, key_part->length, ((Item_field*) keyuse->val->real_item())->field, - keyuse->val->full_name()); + keyuse->val->real_item()->full_name()); return new store_key_item(thd, key_part->field, key_buff + maybe_null, @@ -16512,7 +16512,8 @@ bool test_if_ref(Item *root_cond, Item_field *left_item,Item *right_item) } Item *ref_item=part_of_refkey(field->table,field); - if (ref_item && ref_item->eq(right_item,1)) + if (ref_item && (ref_item->eq(right_item,1) || + ref_item->real_item()->eq(right_item,1))) { right_item= right_item->real_item(); if (right_item->type() == Item::FIELD_ITEM)