Commit ddc5c653 authored by Varun Gupta's avatar Varun Gupta

MDEV-14779: using left join causes incorrect results with materialization and derived tables

Conversion of a subquery to a semi-join is blocked when we have an
IN subquery predicate in the on_expr of an outer join. Currently this
scenario is handled but the cases when an IN subquery predicate is wrapped
inside a Item_in_optimizer item then this blocking is not done.
parent f3994b74
...@@ -2346,11 +2346,27 @@ CREATE TABLE t1 (b1 BIT NOT NULL); ...@@ -2346,11 +2346,27 @@ CREATE TABLE t1 (b1 BIT NOT NULL);
INSERT INTO t1 VALUES (0),(1); INSERT INTO t1 VALUES (0),(1);
CREATE TABLE t2 (b2 BIT NOT NULL); CREATE TABLE t2 (b2 BIT NOT NULL);
INSERT INTO t2 VALUES (0),(1); INSERT INTO t2 VALUES (0),(1);
SET SESSION JOIN_CACHE_LEVEL = 3; set @save_join_cache_level= @@join_cache_level;
SET @@join_cache_level = 3;
SELECT t1.b1+'0' , t2.b2 + '0' FROM t1 LEFT JOIN t2 ON b1 = b2; SELECT t1.b1+'0' , t2.b2 + '0' FROM t1 LEFT JOIN t2 ON b1 = b2;
t1.b1+'0' t2.b2 + '0' t1.b1+'0' t2.b2 + '0'
0 0 0 0
1 1 1 1
DROP TABLE t1, t2; DROP TABLE t1, t2;
set @join_cache_level= @save_join_cache_level;
#
# MDEV-14779: using left join causes incorrect results with materialization and derived tables
#
create table t1(id int);
insert into t1 values (1),(2);
create table t2(sid int, id int);
insert into t2 values (1,1),(2,2);
select * from t1 t
left join (select * from t2 where sid in (select max(sid) from t2 where 0=1 group by id)) r
on t.id=r.id ;
id sid id
1 NULL NULL
2 NULL NULL
drop table t1, t2;
# end of 5.5 tests # end of 5.5 tests
SET optimizer_switch=@save_optimizer_switch; SET optimizer_switch=@save_optimizer_switch;
...@@ -2357,12 +2357,28 @@ CREATE TABLE t1 (b1 BIT NOT NULL); ...@@ -2357,12 +2357,28 @@ CREATE TABLE t1 (b1 BIT NOT NULL);
INSERT INTO t1 VALUES (0),(1); INSERT INTO t1 VALUES (0),(1);
CREATE TABLE t2 (b2 BIT NOT NULL); CREATE TABLE t2 (b2 BIT NOT NULL);
INSERT INTO t2 VALUES (0),(1); INSERT INTO t2 VALUES (0),(1);
SET SESSION JOIN_CACHE_LEVEL = 3; set @save_join_cache_level= @@join_cache_level;
SET @@join_cache_level = 3;
SELECT t1.b1+'0' , t2.b2 + '0' FROM t1 LEFT JOIN t2 ON b1 = b2; SELECT t1.b1+'0' , t2.b2 + '0' FROM t1 LEFT JOIN t2 ON b1 = b2;
t1.b1+'0' t2.b2 + '0' t1.b1+'0' t2.b2 + '0'
0 0 0 0
1 1 1 1
DROP TABLE t1, t2; DROP TABLE t1, t2;
set @join_cache_level= @save_join_cache_level;
#
# MDEV-14779: using left join causes incorrect results with materialization and derived tables
#
create table t1(id int);
insert into t1 values (1),(2);
create table t2(sid int, id int);
insert into t2 values (1,1),(2,2);
select * from t1 t
left join (select * from t2 where sid in (select max(sid) from t2 where 0=1 group by id)) r
on t.id=r.id ;
id sid id
1 NULL NULL
2 NULL NULL
drop table t1, t2;
# end of 5.5 tests # end of 5.5 tests
SET optimizer_switch=@save_optimizer_switch; SET optimizer_switch=@save_optimizer_switch;
set join_cache_level=default; set join_cache_level=default;
......
...@@ -1891,9 +1891,25 @@ INSERT INTO t1 VALUES (0),(1); ...@@ -1891,9 +1891,25 @@ INSERT INTO t1 VALUES (0),(1);
CREATE TABLE t2 (b2 BIT NOT NULL); CREATE TABLE t2 (b2 BIT NOT NULL);
INSERT INTO t2 VALUES (0),(1); INSERT INTO t2 VALUES (0),(1);
SET SESSION JOIN_CACHE_LEVEL = 3; set @save_join_cache_level= @@join_cache_level;
SET @@join_cache_level = 3;
SELECT t1.b1+'0' , t2.b2 + '0' FROM t1 LEFT JOIN t2 ON b1 = b2; SELECT t1.b1+'0' , t2.b2 + '0' FROM t1 LEFT JOIN t2 ON b1 = b2;
DROP TABLE t1, t2; DROP TABLE t1, t2;
set @join_cache_level= @save_join_cache_level;
--echo #
--echo # MDEV-14779: using left join causes incorrect results with materialization and derived tables
--echo #
create table t1(id int);
insert into t1 values (1),(2);
create table t2(sid int, id int);
insert into t2 values (1,1),(2,2);
select * from t1 t
left join (select * from t2 where sid in (select max(sid) from t2 where 0=1 group by id)) r
on t.id=r.id ;
drop table t1, t2;
--echo # end of 5.5 tests --echo # end of 5.5 tests
......
...@@ -255,6 +255,7 @@ class Item_in_optimizer: public Item_bool_func ...@@ -255,6 +255,7 @@ class Item_in_optimizer: public Item_bool_func
bool is_null(); bool is_null();
longlong val_int(); longlong val_int();
void cleanup(); void cleanup();
enum Functype functype() const { return IN_OPTIMIZER_FUNC; }
const char *func_name() const { return "<in_optimizer>"; } const char *func_name() const { return "<in_optimizer>"; }
Item_cache **get_cache() { return &cache; } Item_cache **get_cache() { return &cache; }
void keep_top_level_cache(); void keep_top_level_cache();
...@@ -270,6 +271,10 @@ class Item_in_optimizer: public Item_bool_func ...@@ -270,6 +271,10 @@ class Item_in_optimizer: public Item_bool_func
void fix_after_pullout(st_select_lex *new_parent, Item **ref); void fix_after_pullout(st_select_lex *new_parent, Item **ref);
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
void restore_first_argument(); void restore_first_argument();
Item* get_wrapped_in_subselect_item()
{
return args[1];
}
}; };
class Comp_creator class Comp_creator
......
...@@ -66,7 +66,7 @@ class Item_func :public Item_result_field ...@@ -66,7 +66,7 @@ class Item_func :public Item_result_field
NOW_FUNC, TRIG_COND_FUNC, NOW_FUNC, TRIG_COND_FUNC,
SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC, SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC,
EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC, EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC,
NEG_FUNC, GSYSVAR_FUNC }; NEG_FUNC, GSYSVAR_FUNC, IN_OPTIMIZER_FUNC };
enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL, enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL,
OPTIMIZE_EQUAL }; OPTIMIZE_EQUAL };
enum Type type() const { return FUNC_ITEM; } enum Type type() const { return FUNC_ITEM; }
......
...@@ -1006,6 +1006,10 @@ bool check_for_outer_joins(List<TABLE_LIST> *join_list) ...@@ -1006,6 +1006,10 @@ bool check_for_outer_joins(List<TABLE_LIST> *join_list)
void find_and_block_conversion_to_sj(Item *to_find, void find_and_block_conversion_to_sj(Item *to_find,
List_iterator_fast<Item_in_subselect> &li) List_iterator_fast<Item_in_subselect> &li)
{ {
if (to_find->type() == Item::FUNC_ITEM &&
((Item_func*)to_find)->functype() == Item_func::IN_OPTIMIZER_FUNC)
to_find= ((Item_in_optimizer*)to_find)->get_wrapped_in_subselect_item();
if (to_find->type() != Item::SUBSELECT_ITEM || if (to_find->type() != Item::SUBSELECT_ITEM ||
((Item_subselect *) to_find)->substype() != Item_subselect::IN_SUBS) ((Item_subselect *) to_find)->substype() != Item_subselect::IN_SUBS)
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment