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
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
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
set optimizer_switch=@subselect_tmp;
......@@ -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;
min_a a
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
set optimizer_switch=@subselect_tmp;
set optimizer_switch=default;
......
......@@ -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;
min_a a
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
set optimizer_switch=@subselect_tmp;
set @optimizer_switch_for_subselect_test=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;
min_a a
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
set optimizer_switch=@subselect_tmp;
set optimizer_switch=default;
......
......@@ -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;
min_a a
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
set optimizer_switch=@subselect_tmp;
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
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
set optimizer_switch=@subselect_tmp;
......@@ -765,7 +765,9 @@ table_map Item_subselect::used_tables() 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)
......@@ -1484,6 +1486,10 @@ double Item_in_subselect::val_real()
*/
DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
if (forced_const)
return value;
DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
! engine->is_executed());
null_value= was_null= FALSE;
if (exec())
{
......@@ -1504,6 +1510,10 @@ longlong Item_in_subselect::val_int()
*/
DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
if (forced_const)
return value;
DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
! engine->is_executed());
null_value= was_null= FALSE;
if (exec())
{
......@@ -1524,6 +1534,10 @@ String *Item_in_subselect::val_str(String *str)
*/
DBUG_ASSERT(0);
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;
if (exec())
{
......@@ -1535,6 +1549,7 @@ String *Item_in_subselect::val_str(String *str)
null_value= TRUE;
return 0;
}
value_is_ready:
str->set((ulonglong)value, &my_charset_bin);
return str;
}
......@@ -1545,6 +1560,8 @@ bool Item_in_subselect::val_bool()
DBUG_ASSERT(fixed == 1);
if (forced_const)
return value;
DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
! engine->is_executed());
null_value= was_null= FALSE;
if (exec())
{
......@@ -1563,6 +1580,10 @@ my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value)
method should not be used
*/
DBUG_ASSERT(0);
if (forced_const)
goto value_is_ready;
DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
! engine->is_executed());
null_value= was_null= FALSE;
DBUG_ASSERT(fixed == 1);
if (exec())
......@@ -1572,6 +1593,7 @@ my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value)
}
if (was_null && !value)
null_value= TRUE;
value_is_ready:
int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value);
return decimal_value;
}
......@@ -3117,6 +3139,8 @@ int subselect_single_select_engine::exec()
tab->read_record.read_record= tab->save_read_record;
}
executed= 1;
if (!(uncacheable() & ~UNCACHEABLE_EXPLAIN))
item->make_const();
thd->where= save_where;
thd->lex->current_select= save_select;
DBUG_RETURN(join->error || thd->is_fatal_error || thd->is_error());
......
......@@ -11621,9 +11621,9 @@ static int compare_fields_by_table_order(Item *field1,
bool outer_ref= 0;
Item_field *f1= (Item_field *) (field1->real_item());
Item_field *f2= (Item_field *) (field2->real_item());
if (f1->const_item())
if (field1->const_item() || f1->const_item())
return 1;
if (f2->const_item())
if (field2->const_item() || f2->const_item())
return -1;
if (f2->used_tables() & OUTER_REF_TABLE_BIT)
{
......
......@@ -616,6 +616,8 @@ bool st_select_lex_unit::exec()
if (executed && !uncacheable && !describe)
DBUG_RETURN(FALSE);
executed= 1;
if (!(uncacheable & ~UNCACHEABLE_EXPLAIN) && item)
item->make_const();
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