mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Fix for LP BUG#824425: Prohibiting subqueries in rows for left part of IN/ALL/ANY
Fix for walk() method of subqueries: always call the method on the subquery.
This commit is contained in:
@ -1424,4 +1424,51 @@ CALL p1;
|
|||||||
ERROR 42S22: Unknown column 'f1' in 'where clause'
|
ERROR 42S22: Unknown column 'f1' in 'where clause'
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
#
|
||||||
|
# fix of LP BUG#824425 (prohibiting subqueries in row in
|
||||||
|
# left part of IN/ALL/ANY)
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 ( a int) ;
|
||||||
|
INSERT INTO t1 VALUES (20),(30);
|
||||||
|
CREATE TABLE t2 (a int) ;
|
||||||
|
INSERT INTO t2 VALUES (3),(9);
|
||||||
|
CREATE TABLE t3 ( a int, b int) ;
|
||||||
|
INSERT INTO t3 VALUES (20,5),(30,6);
|
||||||
|
set @optimizer_switch_save=@@optimizer_switch;
|
||||||
|
SET SESSION optimizer_switch='semijoin=OFF,in_to_exists=OFF,materialization=ON,partial_match_rowid_merge=ON,partial_match_table_scan=OFF';
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (
|
||||||
|
( SELECT a FROM t2 WHERE a = 9 )
|
||||||
|
) NOT IN (
|
||||||
|
SELECT b
|
||||||
|
FROM t3
|
||||||
|
);
|
||||||
|
a
|
||||||
|
20
|
||||||
|
30
|
||||||
|
explain extended
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (
|
||||||
|
( SELECT a FROM t2 WHERE a = 9 )
|
||||||
|
) NOT IN (
|
||||||
|
SELECT b
|
||||||
|
FROM t3
|
||||||
|
);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
3 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (not(<expr_cache><(select `test`.`t2`.`a` from `test`.`t2` where (`test`.`t2`.`a` = 9))>(<in_optimizer>((select `test`.`t2`.`a` from `test`.`t2` where (`test`.`t2`.`a` = 9)),(select `test`.`t2`.`a` from `test`.`t2` where (`test`.`t2`.`a` = 9)) in ( <materialize> (select `test`.`t3`.`b` from `test`.`t3` ), <primary_index_lookup>(9 in <temporary table> on distinct_key where ((9 = `<subquery3>`.`b`))))))))
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (
|
||||||
|
( SELECT a FROM t2 WHERE a = 9 ),
|
||||||
|
( SELECT a FROM t2 WHERE a = 3 )
|
||||||
|
) NOT IN (
|
||||||
|
SELECT b , a
|
||||||
|
FROM t3
|
||||||
|
);
|
||||||
|
ERROR 42000: This version of MySQL doesn't yet support 'SUBQUERY in ROW in left expression of IN/ALL/ANY'
|
||||||
|
set optimizer_switch=@optimizer_switch_save;
|
||||||
|
drop table t1,t2,t3;
|
||||||
set @@optimizer_switch=@subselect3_tmp;
|
set @@optimizer_switch=@subselect3_tmp;
|
||||||
|
@ -1433,6 +1433,53 @@ CALL p1;
|
|||||||
ERROR 42S22: Unknown column 'f1' in 'where clause'
|
ERROR 42S22: Unknown column 'f1' in 'where clause'
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
#
|
||||||
|
# fix of LP BUG#824425 (prohibiting subqueries in row in
|
||||||
|
# left part of IN/ALL/ANY)
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 ( a int) ;
|
||||||
|
INSERT INTO t1 VALUES (20),(30);
|
||||||
|
CREATE TABLE t2 (a int) ;
|
||||||
|
INSERT INTO t2 VALUES (3),(9);
|
||||||
|
CREATE TABLE t3 ( a int, b int) ;
|
||||||
|
INSERT INTO t3 VALUES (20,5),(30,6);
|
||||||
|
set @optimizer_switch_save=@@optimizer_switch;
|
||||||
|
SET SESSION optimizer_switch='semijoin=OFF,in_to_exists=OFF,materialization=ON,partial_match_rowid_merge=ON,partial_match_table_scan=OFF';
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (
|
||||||
|
( SELECT a FROM t2 WHERE a = 9 )
|
||||||
|
) NOT IN (
|
||||||
|
SELECT b
|
||||||
|
FROM t3
|
||||||
|
);
|
||||||
|
a
|
||||||
|
20
|
||||||
|
30
|
||||||
|
explain extended
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (
|
||||||
|
( SELECT a FROM t2 WHERE a = 9 )
|
||||||
|
) NOT IN (
|
||||||
|
SELECT b
|
||||||
|
FROM t3
|
||||||
|
);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
3 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (not(<expr_cache><(select `test`.`t2`.`a` from `test`.`t2` where (`test`.`t2`.`a` = 9))>(<in_optimizer>((select `test`.`t2`.`a` from `test`.`t2` where (`test`.`t2`.`a` = 9)),(select `test`.`t2`.`a` from `test`.`t2` where (`test`.`t2`.`a` = 9)) in ( <materialize> (select `test`.`t3`.`b` from `test`.`t3` ), <primary_index_lookup>(9 in <temporary table> on distinct_key where ((9 = `<subquery3>`.`b`))))))))
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (
|
||||||
|
( SELECT a FROM t2 WHERE a = 9 ),
|
||||||
|
( SELECT a FROM t2 WHERE a = 3 )
|
||||||
|
) NOT IN (
|
||||||
|
SELECT b , a
|
||||||
|
FROM t3
|
||||||
|
);
|
||||||
|
ERROR 42000: This version of MySQL doesn't yet support 'SUBQUERY in ROW in left expression of IN/ALL/ANY'
|
||||||
|
set optimizer_switch=@optimizer_switch_save;
|
||||||
|
drop table t1,t2,t3;
|
||||||
set @@optimizer_switch=@subselect3_tmp;
|
set @@optimizer_switch=@subselect3_tmp;
|
||||||
set join_cache_level=default;
|
set join_cache_level=default;
|
||||||
show variables like 'join_cache_level';
|
show variables like 'join_cache_level';
|
||||||
|
@ -1187,5 +1187,52 @@ CALL p1;
|
|||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # fix of LP BUG#824425 (prohibiting subqueries in row in
|
||||||
|
--echo # left part of IN/ALL/ANY)
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 ( a int) ;
|
||||||
|
INSERT INTO t1 VALUES (20),(30);
|
||||||
|
|
||||||
|
CREATE TABLE t2 (a int) ;
|
||||||
|
INSERT INTO t2 VALUES (3),(9);
|
||||||
|
|
||||||
|
CREATE TABLE t3 ( a int, b int) ;
|
||||||
|
INSERT INTO t3 VALUES (20,5),(30,6);
|
||||||
|
|
||||||
|
set @optimizer_switch_save=@@optimizer_switch;
|
||||||
|
SET SESSION optimizer_switch='semijoin=OFF,in_to_exists=OFF,materialization=ON,partial_match_rowid_merge=ON,partial_match_table_scan=OFF';
|
||||||
|
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (
|
||||||
|
( SELECT a FROM t2 WHERE a = 9 )
|
||||||
|
) NOT IN (
|
||||||
|
SELECT b
|
||||||
|
FROM t3
|
||||||
|
);
|
||||||
|
explain extended
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (
|
||||||
|
( SELECT a FROM t2 WHERE a = 9 )
|
||||||
|
) NOT IN (
|
||||||
|
SELECT b
|
||||||
|
FROM t3
|
||||||
|
);
|
||||||
|
|
||||||
|
--error ER_NOT_SUPPORTED_YET
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (
|
||||||
|
( SELECT a FROM t2 WHERE a = 9 ),
|
||||||
|
( SELECT a FROM t2 WHERE a = 3 )
|
||||||
|
) NOT IN (
|
||||||
|
SELECT b , a
|
||||||
|
FROM t3
|
||||||
|
);
|
||||||
|
set optimizer_switch=@optimizer_switch_save;
|
||||||
|
|
||||||
|
drop table t1,t2,t3;
|
||||||
|
|
||||||
# The following command must be the last one the file
|
# The following command must be the last one the file
|
||||||
set @@optimizer_switch=@subselect3_tmp;
|
set @@optimizer_switch=@subselect3_tmp;
|
||||||
|
@ -1023,6 +1023,7 @@ public:
|
|||||||
virtual bool view_used_tables_processor(uchar *arg) { return 0; }
|
virtual bool view_used_tables_processor(uchar *arg) { return 0; }
|
||||||
virtual bool eval_not_null_tables(uchar *opt_arg) { return 0; }
|
virtual bool eval_not_null_tables(uchar *opt_arg) { return 0; }
|
||||||
virtual bool clear_sum_processor(uchar *opt_arg) { return 0; }
|
virtual bool clear_sum_processor(uchar *opt_arg) { return 0; }
|
||||||
|
virtual bool is_subquery_processor (uchar *opt_arg) { return 0; }
|
||||||
|
|
||||||
/* To call bool function for all arguments */
|
/* To call bool function for all arguments */
|
||||||
struct bool_func_call_args
|
struct bool_func_call_args
|
||||||
|
@ -1436,6 +1436,7 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
|
|||||||
cache->setup(args[0]);
|
cache->setup(args[0]);
|
||||||
if (cache->cols() == 1)
|
if (cache->cols() == 1)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(args[0]->type() != ROW_ITEM);
|
||||||
if ((used_tables_cache= args[0]->used_tables()))
|
if ((used_tables_cache= args[0]->used_tables()))
|
||||||
cache->set_used_tables(OUTER_REF_TABLE_BIT);
|
cache->set_used_tables(OUTER_REF_TABLE_BIT);
|
||||||
else
|
else
|
||||||
@ -1446,6 +1447,14 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
|
|||||||
uint n= cache->cols();
|
uint n= cache->cols();
|
||||||
for (uint i= 0; i < n; i++)
|
for (uint i= 0; i < n; i++)
|
||||||
{
|
{
|
||||||
|
/* Check that the expression (part of row) do not contain a subquery */
|
||||||
|
if (args[0]->element_index(i)->walk(&Item::is_subquery_processor,
|
||||||
|
FALSE, NULL))
|
||||||
|
{
|
||||||
|
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
|
||||||
|
"SUBQUERY in ROW in left expression of IN/ALL/ANY");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if (args[0]->element_index(i)->used_tables())
|
if (args[0]->element_index(i)->used_tables())
|
||||||
((Item_cache *)cache->element_index(i))->set_used_tables(OUTER_REF_TABLE_BIT);
|
((Item_cache *)cache->element_index(i))->set_used_tables(OUTER_REF_TABLE_BIT);
|
||||||
else
|
else
|
||||||
|
@ -528,7 +528,7 @@ bool Item_subselect::walk(Item_processor processor, bool walk_subquery,
|
|||||||
invalidated by irreversible cleanups (those happen after an uncorrelated
|
invalidated by irreversible cleanups (those happen after an uncorrelated
|
||||||
subquery has been executed).
|
subquery has been executed).
|
||||||
*/
|
*/
|
||||||
return FALSE;
|
return (this->*processor)(argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (walk_subquery)
|
if (walk_subquery)
|
||||||
|
@ -226,6 +226,7 @@ public:
|
|||||||
const char *func_name() const { DBUG_ASSERT(0); return "subselect"; }
|
const char *func_name() const { DBUG_ASSERT(0); return "subselect"; }
|
||||||
virtual bool expr_cache_is_needed(THD *);
|
virtual bool expr_cache_is_needed(THD *);
|
||||||
virtual void get_cache_parameters(List<Item> ¶meters);
|
virtual void get_cache_parameters(List<Item> ¶meters);
|
||||||
|
virtual bool is_subquery_processor (uchar *opt_arg) { return 1; }
|
||||||
|
|
||||||
friend class select_result_interceptor;
|
friend class select_result_interceptor;
|
||||||
friend class Item_in_optimizer;
|
friend class Item_in_optimizer;
|
||||||
|
Reference in New Issue
Block a user