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
EXECUTE st1;
a a
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;
......@@ -1914,6 +1914,23 @@ a a
EXECUTE st1;
a a
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;
#
# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
......
......@@ -1735,5 +1735,26 @@ EXECUTE st1;
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
set optimizer_switch=@subselect_sj_tmp;
......@@ -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)
{
not_null_tables_cache= 0;
......@@ -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()
{
THD *thd= current_thd;
......@@ -2516,6 +2534,16 @@ Item_func_if::eval_not_null_tables(uchar *opt_arg)
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
Item_func_if::fix_length_and_dec()
{
......@@ -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)
{
return cs->coll->strnncollsp(cs,
......
......@@ -262,6 +262,7 @@ public:
virtual void get_cache_parameters(List<Item> &parameters);
bool is_top_level_item();
bool eval_not_null_tables(uchar *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
};
class Comp_creator
......@@ -674,6 +675,7 @@ public:
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
uint decimal_precision() const { return 1; }
bool eval_not_null_tables(uchar *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
};
......@@ -775,6 +777,7 @@ public:
uint decimal_precision() const;
const char *func_name() const { return "if"; }
bool eval_not_null_tables(uchar *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
};
......@@ -1313,6 +1316,7 @@ public:
bool is_bool_func() { return 1; }
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
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
......
......@@ -149,11 +149,13 @@ void Item_row::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{
used_tables_cache= 0;
const_item_cache= 1;
not_null_tables_cache= 0;
for (uint i= 0; i < arg_count; i++)
{
items[i]->fix_after_pullout(new_parent, &items[i]);
used_tables_cache|= items[i]->used_tables();
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)
{
left_expr->fix_after_pullout(new_parent, &left_expr);
Item_subselect::fix_after_pullout(new_parent, ref);
//psergey-todo: the above looks odd, why don't we 'aggregate' left_expr with
//the rest?
used_tables_cache |= left_expr->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