Skip to content

Commit 8c81575

Browse files
committed
Problem was that for cases like:
SELECT ... WHERE XX IN (SELECT YY) this was transformed to something like: SELECT ... WHERE IF_EXISTS(SELECT ... HAVING XX=YY) The bug was that for normal execution XX was fixed in the original outer SELECT context while in PS it was fixed in the sub query context and this confused the optimizer. Fixed by ensuring that XX is always fixed in the outer context.
1 parent 2e941fe commit 8c81575

File tree

6 files changed

+102
-9
lines changed

6 files changed

+102
-9
lines changed

mysql-test/r/subselect_mat.result

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2145,6 +2145,33 @@ drop database mysqltest1;
21452145
drop database mysqltest2;
21462146
drop database mysqltest3;
21472147
drop database mysqltest4;
2148+
#
2149+
# MDEV-7810 Wrong result on execution of a query as a PS
2150+
# (both 1st and further executions)
2151+
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
2152+
INSERT INTO t1 VALUES (0),(8);
2153+
SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2;
2154+
a
2155+
0
2156+
8
2157+
SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a));
2158+
MIN(t3.a)
2159+
0
2160+
SELECT a FROM ( SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2 ) AS sq
2161+
WHERE a IN ( SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a) ) );
2162+
a
2163+
0
2164+
PREPARE stmt FROM "
2165+
SELECT a FROM ( SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2 ) AS sq
2166+
WHERE a IN ( SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a) ) )
2167+
";
2168+
execute stmt;
2169+
a
2170+
0
2171+
execute stmt;
2172+
a
2173+
0
2174+
drop table t1;
21482175
# End of 5.5 tests
21492176
set @subselect_mat_test_optimizer_switch_value=null;
21502177
set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';

mysql-test/r/subselect_sj_mat.result

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2185,4 +2185,31 @@ drop database mysqltest1;
21852185
drop database mysqltest2;
21862186
drop database mysqltest3;
21872187
drop database mysqltest4;
2188+
#
2189+
# MDEV-7810 Wrong result on execution of a query as a PS
2190+
# (both 1st and further executions)
2191+
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
2192+
INSERT INTO t1 VALUES (0),(8);
2193+
SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2;
2194+
a
2195+
0
2196+
8
2197+
SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a));
2198+
MIN(t3.a)
2199+
0
2200+
SELECT a FROM ( SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2 ) AS sq
2201+
WHERE a IN ( SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a) ) );
2202+
a
2203+
0
2204+
PREPARE stmt FROM "
2205+
SELECT a FROM ( SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2 ) AS sq
2206+
WHERE a IN ( SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a) ) )
2207+
";
2208+
execute stmt;
2209+
a
2210+
0
2211+
execute stmt;
2212+
a
2213+
0
2214+
drop table t1;
21882215
# End of 5.5 tests

mysql-test/t/subselect_sj_mat.test

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1841,5 +1841,24 @@ drop database mysqltest2;
18411841
drop database mysqltest3;
18421842
drop database mysqltest4;
18431843

1844-
--echo # End of 5.5 tests
1844+
--echo #
1845+
--echo # MDEV-7810 Wrong result on execution of a query as a PS
1846+
--echo # (both 1st and further executions)
1847+
1848+
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
1849+
INSERT INTO t1 VALUES (0),(8);
1850+
1851+
SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2;
1852+
SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a));
1853+
SELECT a FROM ( SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2 ) AS sq
1854+
WHERE a IN ( SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a) ) );
1855+
PREPARE stmt FROM "
1856+
SELECT a FROM ( SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2 ) AS sq
1857+
WHERE a IN ( SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a) ) )
1858+
";
1859+
execute stmt;
1860+
execute stmt;
18451861

1862+
drop table t1;
1863+
1864+
--echo # End of 5.5 tests

sql/item_subselect.cc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1999,12 +1999,31 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join,
19991999
during JOIN::optimize: this->tmp_having= this->having; this->having= 0;
20002000
*/
20012001
Item* join_having= join->having ? join->having : join->tmp_having;
2002-
20032002
DBUG_ENTER("Item_in_subselect::create_single_in_to_exists_cond");
20042003

20052004
*where_item= NULL;
20062005
*having_item= NULL;
20072006

2007+
/*
2008+
For PS we have to do fix_fields(expr) here to ensure that it's
2009+
evaluated in the outer context. If not, then fix_having() will do
2010+
a fix_fields(expr) in the inner context and mark expr as
2011+
'depended', which will cause update_ref_and_keys() to find wrong
2012+
keys.
2013+
When not running PS, fix_fields(expr) as already been done earlier and
2014+
the following test does nothing.
2015+
*/
2016+
if (expr && !expr->fixed)
2017+
{
2018+
SELECT_LEX *save_current_select= thd->lex->current_select;
2019+
thd->lex->current_select= thd->lex->current_select->outer_select();
2020+
bool tmp;
2021+
tmp= expr->fix_fields(thd, 0);
2022+
thd->lex->current_select= save_current_select;
2023+
if (tmp)
2024+
DBUG_RETURN(true);
2025+
}
2026+
20082027
if (join_having || select_lex->with_sum_func ||
20092028
select_lex->group_list.elements)
20102029
{

sql/sql_base.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6859,6 +6859,7 @@ find_field_in_tables(THD *thd, Item_ident *item,
68596859

68606860
if (item->cached_table)
68616861
{
6862+
DBUG_PRINT("info", ("using cached table"));
68626863
/*
68636864
This shortcut is used by prepared statements. We assume that
68646865
TABLE_LIST *first_table is not changed during query execution (which
@@ -6935,8 +6936,6 @@ find_field_in_tables(THD *thd, Item_ident *item,
69356936
return found;
69366937
}
69376938
}
6938-
else
6939-
item->can_be_depended= TRUE;
69406939

69416940
if (db && lower_case_table_names)
69426941
{

sql/sql_select.cc

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4904,6 +4904,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
49044904
KEY_FIELD *key_fields, *end, *field;
49054905
uint sz;
49064906
uint m= max(select_lex->max_equal_elems,1);
4907+
DBUG_ENTER("update_ref_and_keys");
4908+
DBUG_PRINT("enter", ("normal_tables: %llx", normal_tables));
49074909

49084910
SELECT_LEX *sel=thd->lex->current_select;
49094911
sel->cond_count= 0;
@@ -4950,7 +4952,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
49504952
sz= max(sizeof(KEY_FIELD),sizeof(SARGABLE_PARAM))*
49514953
((sel->cond_count*2 + sel->between_count)*m+1);
49524954
if (!(key_fields=(KEY_FIELD*) thd->alloc(sz)))
4953-
return TRUE; /* purecov: inspected */
4955+
DBUG_RETURN(TRUE); /* purecov: inspected */
49544956
and_level= 0;
49554957
field= end= key_fields;
49564958
*sargables= (SARGABLE_PARAM *) key_fields +
@@ -4959,7 +4961,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
49594961
(*sargables)[0].field= 0;
49604962

49614963
if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64))
4962-
return TRUE;
4964+
DBUG_RETURN(TRUE);
49634965

49644966
if (cond)
49654967
{
@@ -5009,16 +5011,16 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
50095011
for ( ; field != end ; field++)
50105012
{
50115013
if (add_key_part(keyuse,field))
5012-
return TRUE;
5014+
DBUG_RETURN(TRUE);
50135015
}
50145016

50155017
if (select_lex->ftfunc_list->elements)
50165018
{
50175019
if (add_ft_keys(keyuse,join_tab,cond,normal_tables))
5018-
return TRUE;
5020+
DBUG_RETURN(TRUE);
50195021
}
50205022

5021-
return FALSE;
5023+
DBUG_RETURN(FALSE);
50225024
}
50235025

50245026

0 commit comments

Comments
 (0)