Commit ebbdb14a authored by Sergey Petrunya's avatar Sergey Petrunya

BUG#849776: Wrong result with semijoin + "Impossible where"

- Provide fix_after_pullout() function for Item_in_optimizer and other Item_XXX classes (basically, all of them
  that have eval_not_null_tables, which means they have special rules for calculating not_null_tables_cache value)
parent 42b928ca
...@@ -1903,4 +1903,21 @@ a a ...@@ -1903,4 +1903,21 @@ a a
EXECUTE st1; EXECUTE st1;
a a a a
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
#
# BUG#849776: Wrong result with semijoin + "Impossible where"
#
CREATE TABLE t1 ( b varchar(1), a integer) ;
INSERT INTO t1 VALUES ('z',8);
CREATE TABLE t2 ( a integer, b varchar(1)) ;
CREATE TABLE t4 ( a integer, b varchar(1)) ;
CREATE TABLE t5 ( a integer) ;
INSERT INTO t5 VALUES (8);
select * from t5 where (a) in (
SELECT t1.a
FROM t1 LEFT JOIN t2 ON t1.a = t2.a
WHERE t2.b NOT IN (SELECT t4.b FROM t4 WHERE t4.b < t1.b)
);
a
8
DROP TABLE t1, t2, t4, t5;
set optimizer_switch=@subselect_sj_tmp; set optimizer_switch=@subselect_sj_tmp;
...@@ -1914,6 +1914,23 @@ a a ...@@ -1914,6 +1914,23 @@ a a
EXECUTE st1; EXECUTE st1;
a a a a
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
#
# BUG#849776: Wrong result with semijoin + "Impossible where"
#
CREATE TABLE t1 ( b varchar(1), a integer) ;
INSERT INTO t1 VALUES ('z',8);
CREATE TABLE t2 ( a integer, b varchar(1)) ;
CREATE TABLE t4 ( a integer, b varchar(1)) ;
CREATE TABLE t5 ( a integer) ;
INSERT INTO t5 VALUES (8);
select * from t5 where (a) in (
SELECT t1.a
FROM t1 LEFT JOIN t2 ON t1.a = t2.a
WHERE t2.b NOT IN (SELECT t4.b FROM t4 WHERE t4.b < t1.b)
);
a
8
DROP TABLE t1, t2, t4, t5;
set optimizer_switch=@subselect_sj_tmp; set optimizer_switch=@subselect_sj_tmp;
# #
# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off # BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
......
...@@ -1735,5 +1735,26 @@ EXECUTE st1; ...@@ -1735,5 +1735,26 @@ EXECUTE st1;
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
--echo #
--echo # BUG#849776: Wrong result with semijoin + "Impossible where"
--echo #
CREATE TABLE t1 ( b varchar(1), a integer) ;
INSERT INTO t1 VALUES ('z',8);
CREATE TABLE t2 ( a integer, b varchar(1)) ;
CREATE TABLE t4 ( a integer, b varchar(1)) ;
CREATE TABLE t5 ( a integer) ;
INSERT INTO t5 VALUES (8);
select * from t5 where (a) in (
SELECT t1.a
FROM t1 LEFT JOIN t2 ON t1.a = t2.a
WHERE t2.b NOT IN (SELECT t4.b FROM t4 WHERE t4.b < t1.b)
);
DROP TABLE t1, t2, t4, t5;
# The following command must be the last one the file # The following command must be the last one the file
set optimizer_switch=@subselect_sj_tmp; set optimizer_switch=@subselect_sj_tmp;
...@@ -1405,6 +1405,16 @@ bool Item_in_optimizer::is_top_level_item() ...@@ -1405,6 +1405,16 @@ bool Item_in_optimizer::is_top_level_item()
} }
void Item_in_optimizer::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{
/* This will re-calculate attributes of our Item_in_subselect: */
Item_bool_func::fix_after_pullout(new_parent, ref);
/* Then, re-calculate not_null_tables_cache: */
eval_not_null_tables(NULL);
}
bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg) bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg)
{ {
not_null_tables_cache= 0; not_null_tables_cache= 0;
...@@ -2136,6 +2146,14 @@ bool Item_func_between::eval_not_null_tables(uchar *opt_arg) ...@@ -2136,6 +2146,14 @@ bool Item_func_between::eval_not_null_tables(uchar *opt_arg)
} }
void Item_func_between::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{
/* This will re-calculate attributes of the arguments */
Item_func_opt_neg::fix_after_pullout(new_parent, ref);
/* Then, re-calculate not_null_tables_cache according to our special rules */
eval_not_null_tables(NULL);
}
void Item_func_between::fix_length_and_dec() void Item_func_between::fix_length_and_dec()
{ {
THD *thd= current_thd; THD *thd= current_thd;
...@@ -2516,6 +2534,16 @@ Item_func_if::eval_not_null_tables(uchar *opt_arg) ...@@ -2516,6 +2534,16 @@ Item_func_if::eval_not_null_tables(uchar *opt_arg)
return 0; return 0;
} }
void Item_func_if::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{
/* This will re-calculate attributes of the arguments */
Item_func::fix_after_pullout(new_parent, ref);
/* Then, re-calculate not_null_tables_cache according to our special rules */
eval_not_null_tables(NULL);
}
void void
Item_func_if::fix_length_and_dec() Item_func_if::fix_length_and_dec()
{ {
...@@ -3760,6 +3788,14 @@ Item_func_in::eval_not_null_tables(uchar *opt_arg) ...@@ -3760,6 +3788,14 @@ Item_func_in::eval_not_null_tables(uchar *opt_arg)
} }
void Item_func_in::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{
/* This will re-calculate attributes of the arguments */
Item_func_opt_neg::fix_after_pullout(new_parent, ref);
/* Then, re-calculate not_null_tables_cache according to our special rules */
eval_not_null_tables(NULL);
}
static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y) static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
{ {
return cs->coll->strnncollsp(cs, return cs->coll->strnncollsp(cs,
......
...@@ -262,6 +262,7 @@ class Item_in_optimizer: public Item_bool_func ...@@ -262,6 +262,7 @@ class Item_in_optimizer: public Item_bool_func
virtual void get_cache_parameters(List<Item> &parameters); virtual void get_cache_parameters(List<Item> &parameters);
bool is_top_level_item(); bool is_top_level_item();
bool eval_not_null_tables(uchar *opt_arg); bool eval_not_null_tables(uchar *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
}; };
class Comp_creator class Comp_creator
...@@ -674,6 +675,7 @@ class Item_func_between :public Item_func_opt_neg ...@@ -674,6 +675,7 @@ class Item_func_between :public Item_func_opt_neg
CHARSET_INFO *compare_collation() { return cmp_collation.collation; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
uint decimal_precision() const { return 1; } uint decimal_precision() const { return 1; }
bool eval_not_null_tables(uchar *opt_arg); bool eval_not_null_tables(uchar *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
}; };
...@@ -775,6 +777,7 @@ class Item_func_if :public Item_func ...@@ -775,6 +777,7 @@ class Item_func_if :public Item_func
uint decimal_precision() const; uint decimal_precision() const;
const char *func_name() const { return "if"; } const char *func_name() const { return "if"; }
bool eval_not_null_tables(uchar *opt_arg); bool eval_not_null_tables(uchar *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
}; };
...@@ -1313,6 +1316,7 @@ class Item_func_in :public Item_func_opt_neg ...@@ -1313,6 +1316,7 @@ class Item_func_in :public Item_func_opt_neg
bool is_bool_func() { return 1; } bool is_bool_func() { return 1; }
CHARSET_INFO *compare_collation() { return cmp_collation.collation; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
bool eval_not_null_tables(uchar *opt_arg); bool eval_not_null_tables(uchar *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
}; };
class cmp_item_row :public cmp_item class cmp_item_row :public cmp_item
......
...@@ -149,11 +149,13 @@ void Item_row::fix_after_pullout(st_select_lex *new_parent, Item **ref) ...@@ -149,11 +149,13 @@ void Item_row::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{ {
used_tables_cache= 0; used_tables_cache= 0;
const_item_cache= 1; const_item_cache= 1;
not_null_tables_cache= 0;
for (uint i= 0; i < arg_count; i++) for (uint i= 0; i < arg_count; i++)
{ {
items[i]->fix_after_pullout(new_parent, &items[i]); items[i]->fix_after_pullout(new_parent, &items[i]);
used_tables_cache|= items[i]->used_tables(); used_tables_cache|= items[i]->used_tables();
const_item_cache&= items[i]->const_item(); const_item_cache&= items[i]->const_item();
not_null_tables_cache|= items[i]->not_null_tables();
} }
} }
......
...@@ -2477,8 +2477,7 @@ void Item_in_subselect::fix_after_pullout(st_select_lex *new_parent, Item **ref) ...@@ -2477,8 +2477,7 @@ void Item_in_subselect::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{ {
left_expr->fix_after_pullout(new_parent, &left_expr); left_expr->fix_after_pullout(new_parent, &left_expr);
Item_subselect::fix_after_pullout(new_parent, ref); Item_subselect::fix_after_pullout(new_parent, ref);
//psergey-todo: the above looks odd, why don't we 'aggregate' left_expr with used_tables_cache |= left_expr->used_tables();
//the rest?
} }
void Item_in_subselect::update_used_tables() void Item_in_subselect::update_used_tables()
......
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