Commit 4d2b05b7 authored by unknown's avatar unknown

fix for MDEV-367

The problem was that was_null and null_value variables was reset in each reexecution of IN subquery, but engine rerun only for non-constant subqueries.

Fixed checking constant in Item_equal sort.
Fix constant reporting in Item_subselect.
parent b02ad35e
...@@ -6137,5 +6137,31 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL ...@@ -6137,5 +6137,31 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1;
min_a a min_a a
drop table t1; drop table t1;
#
# MDEV-367: Different results with and without subquery_cache on
# a query with a constant NOT IN condition
#
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1),(2),(3);
set @mdev367_optimizer_switch = @@optimizer_switch;
set optimizer_switch = 'subquery_cache=on';
SELECT * FROM t1 WHERE ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) OR a > 100;
a
SELECT *, ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) FROM t1;
a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
1 NULL
2 NULL
3 NULL
set optimizer_switch=@mdev367_optimizer_switch;
set optimizer_switch = 'subquery_cache=off';
SELECT * FROM t1 WHERE ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) OR a > 100;
a
SELECT *, ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) FROM t1;
a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
1 NULL
2 NULL
3 NULL
set optimizer_switch=@mdev367_optimizer_switch;
DROP TABLE t1;
# return optimizer switch changed in the beginning of this test # return optimizer switch changed in the beginning of this test
set optimizer_switch=@subselect_tmp; set optimizer_switch=@subselect_tmp;
...@@ -6136,6 +6136,32 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL ...@@ -6136,6 +6136,32 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1;
min_a a min_a a
drop table t1; drop table t1;
#
# MDEV-367: Different results with and without subquery_cache on
# a query with a constant NOT IN condition
#
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1),(2),(3);
set @mdev367_optimizer_switch = @@optimizer_switch;
set optimizer_switch = 'subquery_cache=on';
SELECT * FROM t1 WHERE ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) OR a > 100;
a
SELECT *, ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) FROM t1;
a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
1 NULL
2 NULL
3 NULL
set optimizer_switch=@mdev367_optimizer_switch;
set optimizer_switch = 'subquery_cache=off';
SELECT * FROM t1 WHERE ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) OR a > 100;
a
SELECT *, ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) FROM t1;
a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
1 NULL
2 NULL
3 NULL
set optimizer_switch=@mdev367_optimizer_switch;
DROP TABLE t1;
# return optimizer switch changed in the beginning of this test # return optimizer switch changed in the beginning of this test
set optimizer_switch=@subselect_tmp; set optimizer_switch=@subselect_tmp;
set optimizer_switch=default; set optimizer_switch=default;
......
...@@ -6132,6 +6132,32 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL ...@@ -6132,6 +6132,32 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1;
min_a a min_a a
drop table t1; drop table t1;
#
# MDEV-367: Different results with and without subquery_cache on
# a query with a constant NOT IN condition
#
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1),(2),(3);
set @mdev367_optimizer_switch = @@optimizer_switch;
set optimizer_switch = 'subquery_cache=on';
SELECT * FROM t1 WHERE ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) OR a > 100;
a
SELECT *, ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) FROM t1;
a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
1 NULL
2 NULL
3 NULL
set optimizer_switch=@mdev367_optimizer_switch;
set optimizer_switch = 'subquery_cache=off';
SELECT * FROM t1 WHERE ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) OR a > 100;
a
SELECT *, ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) FROM t1;
a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
1 NULL
2 NULL
3 NULL
set optimizer_switch=@mdev367_optimizer_switch;
DROP TABLE t1;
# return optimizer switch changed in the beginning of this test # return optimizer switch changed in the beginning of this test
set optimizer_switch=@subselect_tmp; set optimizer_switch=@subselect_tmp;
set @optimizer_switch_for_subselect_test=null; set @optimizer_switch_for_subselect_test=null;
...@@ -6143,6 +6143,32 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL ...@@ -6143,6 +6143,32 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1;
min_a a min_a a
drop table t1; drop table t1;
#
# MDEV-367: Different results with and without subquery_cache on
# a query with a constant NOT IN condition
#
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1),(2),(3);
set @mdev367_optimizer_switch = @@optimizer_switch;
set optimizer_switch = 'subquery_cache=on';
SELECT * FROM t1 WHERE ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) OR a > 100;
a
SELECT *, ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) FROM t1;
a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
1 NULL
2 NULL
3 NULL
set optimizer_switch=@mdev367_optimizer_switch;
set optimizer_switch = 'subquery_cache=off';
SELECT * FROM t1 WHERE ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) OR a > 100;
a
SELECT *, ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) FROM t1;
a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
1 NULL
2 NULL
3 NULL
set optimizer_switch=@mdev367_optimizer_switch;
DROP TABLE t1;
# return optimizer switch changed in the beginning of this test # return optimizer switch changed in the beginning of this test
set optimizer_switch=@subselect_tmp; set optimizer_switch=@subselect_tmp;
set optimizer_switch=default; set optimizer_switch=default;
......
...@@ -6132,6 +6132,32 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL ...@@ -6132,6 +6132,32 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1;
min_a a min_a a
drop table t1; drop table t1;
#
# MDEV-367: Different results with and without subquery_cache on
# a query with a constant NOT IN condition
#
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1),(2),(3);
set @mdev367_optimizer_switch = @@optimizer_switch;
set optimizer_switch = 'subquery_cache=on';
SELECT * FROM t1 WHERE ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) OR a > 100;
a
SELECT *, ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) FROM t1;
a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
1 NULL
2 NULL
3 NULL
set optimizer_switch=@mdev367_optimizer_switch;
set optimizer_switch = 'subquery_cache=off';
SELECT * FROM t1 WHERE ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) OR a > 100;
a
SELECT *, ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) FROM t1;
a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
1 NULL
2 NULL
3 NULL
set optimizer_switch=@mdev367_optimizer_switch;
DROP TABLE t1;
# return optimizer switch changed in the beginning of this test # return optimizer switch changed in the beginning of this test
set optimizer_switch=@subselect_tmp; set optimizer_switch=@subselect_tmp;
set @optimizer_switch_for_subselect_test=null; set @optimizer_switch_for_subselect_test=null;
......
...@@ -5208,5 +5208,26 @@ SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 U ...@@ -5208,5 +5208,26 @@ SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 U
drop table t1; drop table t1;
--echo #
--echo # MDEV-367: Different results with and without subquery_cache on
--echo # a query with a constant NOT IN condition
--echo #
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1),(2),(3);
set @mdev367_optimizer_switch = @@optimizer_switch;
set optimizer_switch = 'subquery_cache=on';
SELECT * FROM t1 WHERE ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) OR a > 100;
SELECT *, ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) FROM t1;
set optimizer_switch=@mdev367_optimizer_switch;
set optimizer_switch = 'subquery_cache=off';
SELECT * FROM t1 WHERE ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) OR a > 100;
SELECT *, ( 3, 3 ) NOT IN ( SELECT NULL, NULL ) FROM t1;
set optimizer_switch=@mdev367_optimizer_switch;
DROP TABLE t1;
--echo # return optimizer switch changed in the beginning of this test --echo # return optimizer switch changed in the beginning of this test
set optimizer_switch=@subselect_tmp; set optimizer_switch=@subselect_tmp;
...@@ -765,7 +765,9 @@ table_map Item_subselect::used_tables() const ...@@ -765,7 +765,9 @@ table_map Item_subselect::used_tables() const
bool Item_subselect::const_item() const bool Item_subselect::const_item() const
{ {
return thd->lex->context_analysis_only ? FALSE : const_item_cache; return (thd->lex->context_analysis_only ?
FALSE :
forced_const || const_item_cache);
} }
Item *Item_subselect::get_tmp_table_item(THD *thd_arg) Item *Item_subselect::get_tmp_table_item(THD *thd_arg)
...@@ -1484,6 +1486,10 @@ double Item_in_subselect::val_real() ...@@ -1484,6 +1486,10 @@ double Item_in_subselect::val_real()
*/ */
DBUG_ASSERT(0); DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (forced_const)
return value;
DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
! engine->is_executed());
null_value= was_null= FALSE; null_value= was_null= FALSE;
if (exec()) if (exec())
{ {
...@@ -1504,6 +1510,10 @@ longlong Item_in_subselect::val_int() ...@@ -1504,6 +1510,10 @@ longlong Item_in_subselect::val_int()
*/ */
DBUG_ASSERT(0); DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (forced_const)
return value;
DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
! engine->is_executed());
null_value= was_null= FALSE; null_value= was_null= FALSE;
if (exec()) if (exec())
{ {
...@@ -1524,6 +1534,10 @@ String *Item_in_subselect::val_str(String *str) ...@@ -1524,6 +1534,10 @@ String *Item_in_subselect::val_str(String *str)
*/ */
DBUG_ASSERT(0); DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (forced_const)
goto value_is_ready;
DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
! engine->is_executed());
null_value= was_null= FALSE; null_value= was_null= FALSE;
if (exec()) if (exec())
{ {
...@@ -1535,6 +1549,7 @@ String *Item_in_subselect::val_str(String *str) ...@@ -1535,6 +1549,7 @@ String *Item_in_subselect::val_str(String *str)
null_value= TRUE; null_value= TRUE;
return 0; return 0;
} }
value_is_ready:
str->set((ulonglong)value, &my_charset_bin); str->set((ulonglong)value, &my_charset_bin);
return str; return str;
} }
...@@ -1545,6 +1560,8 @@ bool Item_in_subselect::val_bool() ...@@ -1545,6 +1560,8 @@ bool Item_in_subselect::val_bool()
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (forced_const) if (forced_const)
return value; return value;
DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
! engine->is_executed());
null_value= was_null= FALSE; null_value= was_null= FALSE;
if (exec()) if (exec())
{ {
...@@ -1563,6 +1580,10 @@ my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value) ...@@ -1563,6 +1580,10 @@ my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value)
method should not be used method should not be used
*/ */
DBUG_ASSERT(0); DBUG_ASSERT(0);
if (forced_const)
goto value_is_ready;
DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
! engine->is_executed());
null_value= was_null= FALSE; null_value= was_null= FALSE;
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (exec()) if (exec())
...@@ -1572,6 +1593,7 @@ my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value) ...@@ -1572,6 +1593,7 @@ my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value)
} }
if (was_null && !value) if (was_null && !value)
null_value= TRUE; null_value= TRUE;
value_is_ready:
int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value); int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value);
return decimal_value; return decimal_value;
} }
...@@ -3117,6 +3139,8 @@ int subselect_single_select_engine::exec() ...@@ -3117,6 +3139,8 @@ int subselect_single_select_engine::exec()
tab->read_record.read_record= tab->save_read_record; tab->read_record.read_record= tab->save_read_record;
} }
executed= 1; executed= 1;
if (!(uncacheable() & ~UNCACHEABLE_EXPLAIN))
item->make_const();
thd->where= save_where; thd->where= save_where;
thd->lex->current_select= save_select; thd->lex->current_select= save_select;
DBUG_RETURN(join->error || thd->is_fatal_error || thd->is_error()); DBUG_RETURN(join->error || thd->is_fatal_error || thd->is_error());
......
...@@ -11621,9 +11621,9 @@ static int compare_fields_by_table_order(Item *field1, ...@@ -11621,9 +11621,9 @@ static int compare_fields_by_table_order(Item *field1,
bool outer_ref= 0; bool outer_ref= 0;
Item_field *f1= (Item_field *) (field1->real_item()); Item_field *f1= (Item_field *) (field1->real_item());
Item_field *f2= (Item_field *) (field2->real_item()); Item_field *f2= (Item_field *) (field2->real_item());
if (f1->const_item()) if (field1->const_item() || f1->const_item())
return 1; return 1;
if (f2->const_item()) if (field2->const_item() || f2->const_item())
return -1; return -1;
if (f2->used_tables() & OUTER_REF_TABLE_BIT) if (f2->used_tables() & OUTER_REF_TABLE_BIT)
{ {
......
...@@ -616,6 +616,8 @@ bool st_select_lex_unit::exec() ...@@ -616,6 +616,8 @@ bool st_select_lex_unit::exec()
if (executed && !uncacheable && !describe) if (executed && !uncacheable && !describe)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
executed= 1; executed= 1;
if (!(uncacheable & ~UNCACHEABLE_EXPLAIN) && item)
item->make_const();
saved_error= optimize(); saved_error= optimize();
......
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