diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index 97a9e0b7f16..ee7951548de 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -1133,3 +1133,55 @@ SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM f1 f2 set @@optimizer_switch=@save_optimizer_switch; drop table t1,t2; +# +# LP BUG#613029 Wrong result with materialization and semijoin, and +# valgrind warnings in Protocol::net_store_data with materialization +# for implicit grouping +# +CREATE TABLE t1 ( +pk int(11) NOT NULL AUTO_INCREMENT, +f2 int(11) NOT NULL, +f3 varchar(1) NOT NULL, +PRIMARY KEY (pk), +KEY f2 (f2)); +INSERT INTO t1 VALUES (1,9,'x'); +INSERT INTO t1 VALUES (2,5,'g'); +CREATE TABLE t2 ( +pk int(11) NOT NULL AUTO_INCREMENT, +f2 int(11) NOT NULL, +f3 varchar(1) NOT NULL, +PRIMARY KEY (pk), +KEY f2 (f2)); +INSERT INTO t2 VALUES (1,7,'p'); +set @save_optimizer_switch=@@optimizer_switch; +set @@optimizer_switch='materialization=off,semijoin=off'; +EXPLAIN +SELECT t1.f3, MAX(t1.f2) +FROM t1, t2 +WHERE (t2.pk = t1.pk) AND t2.pk IN (SELECT f2 FROM t1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 index_subquery f2 f2 4 func 2 Using index +SELECT t1.f3, MAX(t1.f2) +FROM t1, t2 +WHERE (t2.pk = t1.pk) AND t2.pk IN (SELECT f2 FROM t1); +f3 MAX(t1.f2) +NULL NULL +set @@optimizer_switch='materialization=on,semijoin=off'; +EXPLAIN +SELECT t1.f3, MAX(t1.f2) +FROM t1, t2 +WHERE (t2.pk = t1.pk) AND t2.pk IN (SELECT f2 FROM t1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 system PRIMARY NULL NULL NULL 1 +1 PRIMARY t1 const PRIMARY PRIMARY 4 const 1 +2 SUBQUERY t1 index NULL f2 4 NULL 2 Using index +SELECT t1.f3, MAX(t1.f2) +FROM t1, t2 +WHERE (t2.pk = t1.pk) AND t2.pk IN (SELECT f2 FROM t1); +f3 MAX(t1.f2) +NULL NULL +TODO: add a test case for semijoin when the wrong result is fixed +set @@optimizer_switch='materialization=off,semijoin=on'; +set @@optimizer_switch=@save_optimizer_switch; +drop table t1, t2; diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index ee2d48a8324..5cc44ca5557 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -906,3 +906,60 @@ SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM set @@optimizer_switch=@save_optimizer_switch; drop table t1,t2; + +--echo # +--echo # LP BUG#613029 Wrong result with materialization and semijoin, and +--echo # valgrind warnings in Protocol::net_store_data with materialization +--echo # for implicit grouping +--echo # + +CREATE TABLE t1 ( + pk int(11) NOT NULL AUTO_INCREMENT, + f2 int(11) NOT NULL, + f3 varchar(1) NOT NULL, + PRIMARY KEY (pk), + KEY f2 (f2)); + +INSERT INTO t1 VALUES (1,9,'x'); +INSERT INTO t1 VALUES (2,5,'g'); + +CREATE TABLE t2 ( + pk int(11) NOT NULL AUTO_INCREMENT, + f2 int(11) NOT NULL, + f3 varchar(1) NOT NULL, + PRIMARY KEY (pk), + KEY f2 (f2)); + +INSERT INTO t2 VALUES (1,7,'p'); + +set @save_optimizer_switch=@@optimizer_switch; + +set @@optimizer_switch='materialization=off,semijoin=off'; + +EXPLAIN +SELECT t1.f3, MAX(t1.f2) +FROM t1, t2 +WHERE (t2.pk = t1.pk) AND t2.pk IN (SELECT f2 FROM t1); + +SELECT t1.f3, MAX(t1.f2) +FROM t1, t2 +WHERE (t2.pk = t1.pk) AND t2.pk IN (SELECT f2 FROM t1); + +set @@optimizer_switch='materialization=on,semijoin=off'; + +EXPLAIN +SELECT t1.f3, MAX(t1.f2) +FROM t1, t2 +WHERE (t2.pk = t1.pk) AND t2.pk IN (SELECT f2 FROM t1); + +SELECT t1.f3, MAX(t1.f2) +FROM t1, t2 +WHERE (t2.pk = t1.pk) AND t2.pk IN (SELECT f2 FROM t1); + +-- echo TODO: add a test case for semijoin when the wrong result is fixed +-- echo set @@optimizer_switch='materialization=off,semijoin=on'; + + +set @@optimizer_switch=@save_optimizer_switch; + +drop table t1, t2; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2ade04e8592..f7e4c1be706 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13452,6 +13452,13 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) { List *columns_list= (procedure ? &join->procedure_fields_list : fields); + /* + With implicit grouping all fields of special row produced for an + empty result are NULL. See return_zero_rows() for the same behavior. + */ + for (TABLE_LIST *table= join->select_lex->leaf_tables; + table; table= table->next_leaf) + mark_as_null_row(table->table); rc= join->result->send_data(*columns_list); } } diff --git a/sql/sql_select.h b/sql/sql_select.h index 33a278002a1..f625ef0ee9d 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -954,8 +954,8 @@ public: bool init_save_join_tab(); bool send_row_on_empty_set() { - return (do_send_rows && tmp_table_param.sum_func_count != 0 && - !group_list && having_value != Item::COND_FALSE); + return (do_send_rows && implicit_grouping && + having_value != Item::COND_FALSE); } bool change_result(select_result *result); bool is_top_level_join() const