Commit 2f203da8 authored by unknown's avatar unknown

Fix LP BUG#778413

Analysis:
The subquery is evaluated first during ref-optimization of the outer
query because the subquery is considered constant from the perspective
of the outer query. Thus an attempt is made to evaluate the MAX subquery
and use the new constant to drive an index nested loops join.
During this evaluation the inner-most subquery replaces the JOIN_TAB
with a new one that fetches the data from a temp table.
The function select_describe crashes at the lines:
        TABLE_LIST *real_table= table->pos_in_table_list; 
	item_list.push_back(new Item_string(real_table->alias,
					    strlen(real_table->alias),
					    cs));
because 'table' is a temp table, and it has no corresponding table
reference. This 'real_table' is NULL, and real_table->alias results
in a crash.

Solution:
In the spirit of MWL#89 prevent the evaluation of expensive predicates
during optimization. This patch prevents the evaluation of expensive
predicates during ref optimization.


sql/item_subselect.h:
  Remove unused class member. Not needed for the fix, but noticed now and removed.
parent 707e66e1
...@@ -2412,7 +2412,7 @@ EXPLAIN SELECT 1 FROM t1 AS t1_outer1 JOIN t1 AS t1_outer2 ...@@ -2412,7 +2412,7 @@ EXPLAIN SELECT 1 FROM t1 AS t1_outer1 JOIN t1 AS t1_outer2
ON t1_outer1.a = (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) ON t1_outer1.a = (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2)
AND t1_outer1.b = t1_outer2.b; AND t1_outer1.b = t1_outer2.b;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer1 ref a a 5 const 1 Using where; Using index 1 PRIMARY t1_outer1 ref a a 5 const 1 Using index
1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using where; Using index; Using join buffer (flat, BNL join) 1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using where; Using index; Using join buffer (flat, BNL join)
2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by 2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
EXPLAIN SELECT (SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x EXPLAIN SELECT (SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
......
...@@ -370,7 +370,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -370,7 +370,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index 3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
Warnings: Warnings:
Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1 Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce'); t8 WHERE pseudo='joce');
ERROR 21000: Operand should contain 1 column(s) ERROR 21000: Operand should contain 1 column(s)
...@@ -549,7 +549,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -549,7 +549,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index 1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings: Warnings:
Note 1003 select '3' AS `numreponse` from `test`.`t1` where (('1' = '1')) Note 1003 select '3' AS `numreponse` from `test`.`t1` where (('1' = '1') and ('3' = 3))
drop table t1; drop table t1;
CREATE TABLE t1 (a int(1)); CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
......
...@@ -1762,3 +1762,23 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -1762,3 +1762,23 @@ id select_type table type possible_keys key key_len ref rows Extra
SELECT * FROM t1 WHERE ( 6 ) NOT IN ( SELECT t2.f3 FROM t2 JOIN t3 ON t3.f10 = t2.f10); SELECT * FROM t1 WHERE ( 6 ) NOT IN ( SELECT t2.f3 FROM t2 JOIN t3 ON t3.f10 = t2.f10);
f4 f4
drop table t1,t2,t3; drop table t1,t2,t3;
#
# LP BUG#778413 Third crash in select_describe() in maria-5.3-mwl89
#
CREATE TABLE t1 ( f11 int) ;
INSERT INTO t1 VALUES (1),(1);
CREATE TABLE t2 ( f1 int NOT NULL) ;
INSERT INTO t2 VALUES (20);
CREATE TABLE t3 (f3 int) ;
INSERT INTO t3 VALUES (2),(2);
EXPLAIN SELECT * FROM t2
WHERE t2.f1 = (
SELECT MAX( f3 ) FROM t3
WHERE EXISTS (
SELECT DISTINCT f11
FROM t1));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 system NULL NULL NULL NULL 1
2 SUBQUERY t3 ALL NULL NULL NULL NULL 2
3 SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using temporary
drop table t1, t2, t3;
...@@ -374,7 +374,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -374,7 +374,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index 3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
Warnings: Warnings:
Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1 Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce'); t8 WHERE pseudo='joce');
ERROR 21000: Operand should contain 1 column(s) ERROR 21000: Operand should contain 1 column(s)
...@@ -553,7 +553,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -553,7 +553,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index 1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings: Warnings:
Note 1003 select '3' AS `numreponse` from `test`.`t1` where (('1' = '1')) Note 1003 select '3' AS `numreponse` from `test`.`t1` where (('1' = '1') and ('3' = 3))
drop table t1; drop table t1;
CREATE TABLE t1 (a int(1)); CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
......
...@@ -371,7 +371,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -371,7 +371,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index 3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
Warnings: Warnings:
Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1 Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce'); t8 WHERE pseudo='joce');
ERROR 21000: Operand should contain 1 column(s) ERROR 21000: Operand should contain 1 column(s)
...@@ -550,7 +550,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -550,7 +550,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index 1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings: Warnings:
Note 1003 select '3' AS `numreponse` from `test`.`t1` where (('1' = '1')) Note 1003 select '3' AS `numreponse` from `test`.`t1` where (('1' = '1') and ('3' = 3))
drop table t1; drop table t1;
CREATE TABLE t1 (a int(1)); CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
......
...@@ -371,7 +371,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -371,7 +371,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index 3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
Warnings: Warnings:
Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1 Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce'); t8 WHERE pseudo='joce');
ERROR 21000: Operand should contain 1 column(s) ERROR 21000: Operand should contain 1 column(s)
...@@ -550,7 +550,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -550,7 +550,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index 1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings: Warnings:
Note 1003 select '3' AS `numreponse` from `test`.`t1` where (('1' = '1')) Note 1003 select '3' AS `numreponse` from `test`.`t1` where (('1' = '1') and ('3' = 3))
drop table t1; drop table t1;
CREATE TABLE t1 (a int(1)); CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
......
...@@ -1434,3 +1434,26 @@ SELECT * FROM t1 WHERE ( 6 ) NOT IN ( SELECT t2.f3 FROM t2 JOIN t3 ON t3.f10 = t ...@@ -1434,3 +1434,26 @@ SELECT * FROM t1 WHERE ( 6 ) NOT IN ( SELECT t2.f3 FROM t2 JOIN t3 ON t3.f10 = t
SELECT * FROM t1 WHERE ( 6 ) NOT IN ( SELECT t2.f3 FROM t2 JOIN t3 ON t3.f10 = t2.f10); SELECT * FROM t1 WHERE ( 6 ) NOT IN ( SELECT t2.f3 FROM t2 JOIN t3 ON t3.f10 = t2.f10);
drop table t1,t2,t3; drop table t1,t2,t3;
--echo #
--echo # LP BUG#778413 Third crash in select_describe() in maria-5.3-mwl89
--echo #
CREATE TABLE t1 ( f11 int) ;
INSERT INTO t1 VALUES (1),(1);
CREATE TABLE t2 ( f1 int NOT NULL) ;
INSERT INTO t2 VALUES (20);
CREATE TABLE t3 (f3 int) ;
INSERT INTO t3 VALUES (2),(2);
EXPLAIN SELECT * FROM t2
WHERE t2.f1 = (
SELECT MAX( f3 ) FROM t3
WHERE EXISTS (
SELECT DISTINCT f11
FROM t1));
drop table t1, t2, t3;
...@@ -5755,7 +5755,7 @@ void Item_equal::update_const() ...@@ -5755,7 +5755,7 @@ void Item_equal::update_const()
Item *item; Item *item;
while ((item= it++)) while ((item= it++))
{ {
if (item->const_item()) if (item->const_item() && !item->is_expensive())
{ {
if (item == equal_items.head()) if (item == equal_items.head())
with_const= TRUE; with_const= TRUE;
......
...@@ -619,7 +619,6 @@ class subselect_engine: public Sql_alloc ...@@ -619,7 +619,6 @@ class subselect_engine: public Sql_alloc
class subselect_single_select_engine: public subselect_engine class subselect_single_select_engine: public subselect_engine
{ {
bool prepared; /* simple subselect is prepared */ bool prepared; /* simple subselect is prepared */
bool optimized; /* simple subselect is optimized */
bool executed; /* simple subselect is executed */ bool executed; /* simple subselect is executed */
st_select_lex *select_lex; /* corresponding select_lex */ st_select_lex *select_lex; /* corresponding select_lex */
JOIN * join; /* corresponding JOIN structure */ JOIN * join; /* corresponding JOIN structure */
......
...@@ -9469,7 +9469,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item, ...@@ -9469,7 +9469,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
Item *orig_field_item= 0; Item *orig_field_item= 0;
if (left_item->type() == Item::FIELD_ITEM && if (left_item->type() == Item::FIELD_ITEM &&
!((Item_field*)left_item)->depended_from && !((Item_field*)left_item)->depended_from &&
right_item->const_item()) right_item->const_item() && !right_item->is_expensive())
{ {
orig_field_item= left_item; orig_field_item= left_item;
field_item= (Item_field *) left_item; field_item= (Item_field *) left_item;
...@@ -9477,7 +9477,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item, ...@@ -9477,7 +9477,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
} }
else if (right_item->type() == Item::FIELD_ITEM && else if (right_item->type() == Item::FIELD_ITEM &&
!((Item_field*)right_item)->depended_from && !((Item_field*)right_item)->depended_from &&
left_item->const_item()) left_item->const_item() && !left_item->is_expensive())
{ {
orig_field_item= right_item; orig_field_item= right_item;
field_item= (Item_field *) right_item; field_item= (Item_field *) right_item;
......
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