Commit 28cdbab1 authored by Oleg Smirnov's avatar Oleg Smirnov

MDEV-29681 Server crashes when optimizing SQL with ORDER BY

When parsing statements like (SELECT .. FROM ..) ORDER BY <expr>,
there is a step LEX::add_tail_to_query_expression_body_ext_parens()
which calls LEX::wrap_unit_into_derived(). After that the statement
looks like SELECT * FROM (SELECT .. FROM ..), and parser's
Lex_order_limit_lock structure (ORDER BY <expr>) is assigned to
the new SELECT. But what is missing here is that Items in
Lex_order_limit_lock are left with their original name resolution
contexts, and fix_fields() later resolves the names incorrectly.

For example, when processing
  (SELECT * FROM t1 JOIN t2 ON a=b) ORDER BY a
Item_field 'a' in the ORDER BY clause is left with the name resolution
context of the derived table (first_name_resolution_table='t1'), so
it is resolved to 't1.a', which is incorrect.
After LEX::wrap_unit_into_derived() the statement looks like
  SELECT * FROM (SELECT * FROM t1 JOIN t2 ON a=b) AS '__2' ORDER BY a,
and the name resolution context for Item_field 'a' in the ORDER BY
must be set to the wrapping SELECT's one.

This commit fixes the issue by changing context for Items in
Lex_order_limit_lock after LEX::wrap_unit_into_derived().
parent f7552313
......@@ -3725,4 +3725,124 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.t2.b 1 Using where
DROP TABLE t1,t2;
#
# MDEV-29681 Server crashes when optimizing SQL with ORDER BY
#
CREATE TABLE t1 (b INT);
CREATE TABLE t2 (a INT, c INT);
# First test empty tables
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a+1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 0.00 Const row not found
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 /* select#1 */ select NULL AS `b`,NULL AS `a`,NULL AS `c` from ((/* select#2 */ select NULL AS `b`,NULL AS `a`,NULL AS `c` from `test`.`t1` join `test`.`t2` where 0 limit 3)) `__2` order by NULL + 1
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a=2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 0.00 Const row not found
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 /* select#1 */ select NULL AS `b`,NULL AS `a`,NULL AS `c` from ((/* select#2 */ select NULL AS `b`,NULL AS `a`,NULL AS `c` from `test`.`t1` join `test`.`t2` where 0 limit 3)) `__2` order by NULL = 2
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3)
ORDER BY a+1, a-b DESC, c<>a;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 0.00 Const row not found
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 /* select#1 */ select NULL AS `b`,NULL AS `a`,NULL AS `c` from ((/* select#2 */ select NULL AS `b`,NULL AS `a`,NULL AS `c` from `test`.`t1` join `test`.`t2` where 0 limit 3)) `__2` order by NULL + 1,NULL - NULL desc,NULL <> NULL
# Insert some data
INSERT INTO t1 VALUES (1),(2),(3),(4);
INSERT INTO t2 VALUES (1,1),(2,2),(3,3),(4,4);
(SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a=b, a-10 DESC, b+a, c+a+a+b;
b a c
1 1 1
2 2 2
3 3 3
(SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a=2;
b a c
1 1 1
2 2 2
3 3 3
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3)
ORDER BY a=b, a-10, b+a, c+a+a+b;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3 100.00 Using filesort
2 DERIVED t1 ALL NULL NULL NULL NULL 4 100.00
2 DERIVED t2 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
Note 1003 /* select#1 */ select `__2`.`b` AS `b`,`__2`.`a` AS `a`,`__2`.`c` AS `c` from ((/* select#2 */ select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` limit 3)) `__2` order by `__2`.`a` = `__2`.`b`,`__2`.`a` - 10,`__2`.`b` + `__2`.`a`,`__2`.`c` + `__2`.`a` + `__2`.`a` + `__2`.`b`
# When there is no LIMIT clause the derived table must be merged
(SELECT * FROM t1 JOIN t2 ON a=b) ORDER BY a+16, b+a, c<>b;
b a c
1 1 1
2 2 2
3 3 3
4 4 4
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b) ORDER BY a+16 DESC, b+a, c<>b;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using temporary; Using filesort
1 SIMPLE t2 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
Note 1003 (select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` order by `test`.`t2`.`a` + 16 desc,`test`.`t1`.`b` + `test`.`t2`.`a`,`test`.`t2`.`c` <> `test`.`t1`.`b`)
# Test UNIONs:
(SELECT * FROM t1 JOIN t2 ON a=b UNION
SELECT * FROM t1 JOIN t2 ON a!=b
LIMIT 3)
ORDER BY a+16, b+a, c<>b;
b a c
1 1 1
2 2 2
3 3 3
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b UNION
SELECT * FROM t1 JOIN t2 ON a!=b
LIMIT 3)
ORDER BY a+16, b+a, c<>b;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 32 100.00 Using filesort
2 DERIVED t1 ALL NULL NULL NULL NULL 4 100.00
2 DERIVED t2 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join)
3 UNION t1 ALL NULL NULL NULL NULL 4 100.00
3 UNION t2 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join)
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1003 /* select#1 */ select `__3`.`b` AS `b`,`__3`.`a` AS `a`,`__3`.`c` AS `c` from (/* select#2 */ select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` union /* select#3 */ select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` <> `test`.`t1`.`b` limit 3) `__3` order by `__3`.`a` + 16,`__3`.`b` + `__3`.`a`,`__3`.`c` <> `__3`.`b`
(SELECT * FROM t1 JOIN t2 ON a=b UNION
SELECT NULL, NULL, NULL
LIMIT 3)
ORDER BY b-a-c;
b a c
1 1 1
2 2 2
3 3 3
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b UNION
SELECT NULL, NULL, NULL
LIMIT 3)
ORDER BY b-a-c;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 16 100.00 Using filesort
2 DERIVED t1 ALL NULL NULL NULL NULL 4 100.00
2 DERIVED t2 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join)
3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1003 /* select#1 */ select `__3`.`b` AS `b`,`__3`.`a` AS `a`,`__3`.`c` AS `c` from (/* select#2 */ select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` union /* select#3 */ select NULL AS `NULL`,NULL AS `NULL`,NULL AS `NULL` limit 3) `__3` order by `__3`.`b` - `__3`.`a` - `__3`.`c`
(SELECT * FROM t1 JOIN t2 ON a=b UNION
SELECT NULL, NULL, NULL
ORDER BY a LIMIT 3)
ORDER BY b-a-c LIMIT 1;
b a c
NULL NULL NULL
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b UNION
SELECT NULL, NULL, NULL
ORDER BY a LIMIT 3)
ORDER BY b-a-c LIMIT 1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 16 100.00 Using filesort
2 DERIVED t1 ALL NULL NULL NULL NULL 4 100.00
2 DERIVED t2 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join)
3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL Using filesort
Warnings:
Note 1003 /* select#1 */ select `__3`.`b` AS `b`,`__3`.`a` AS `a`,`__3`.`c` AS `c` from (/* select#2 */ select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` union /* select#3 */ select NULL AS `NULL`,NULL AS `NULL`,NULL AS `NULL` order by `a` limit 3) `__3` order by `__3`.`b` - `__3`.`a` - `__3`.`c` limit 1
DROP TABLE t1, t2;
# End of 10.4 tests
......@@ -2468,4 +2468,63 @@ EXPLAIN SELECT (SELECT 1 FROM t1 WHERE t1.a=t2.b ORDER BY t1.b LIMIT 1) AS c FRO
DROP TABLE t1,t2;
--echo #
--echo # MDEV-29681 Server crashes when optimizing SQL with ORDER BY
--echo #
CREATE TABLE t1 (b INT);
CREATE TABLE t2 (a INT, c INT);
--echo # First test empty tables
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a+1;
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a=2;
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3)
ORDER BY a+1, a-b DESC, c<>a;
--echo # Insert some data
INSERT INTO t1 VALUES (1),(2),(3),(4);
INSERT INTO t2 VALUES (1,1),(2,2),(3,3),(4,4);
--sorted_result
(SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a=b, a-10 DESC, b+a, c+a+a+b;
--sorted_result
(SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a=2;
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3)
ORDER BY a=b, a-10, b+a, c+a+a+b;
--echo # When there is no LIMIT clause the derived table must be merged
--sorted_result
(SELECT * FROM t1 JOIN t2 ON a=b) ORDER BY a+16, b+a, c<>b;
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b) ORDER BY a+16 DESC, b+a, c<>b;
--echo # Test UNIONs:
--sorted_result
(SELECT * FROM t1 JOIN t2 ON a=b UNION
SELECT * FROM t1 JOIN t2 ON a!=b
LIMIT 3)
ORDER BY a+16, b+a, c<>b;
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b UNION
SELECT * FROM t1 JOIN t2 ON a!=b
LIMIT 3)
ORDER BY a+16, b+a, c<>b;
--sorted_result
(SELECT * FROM t1 JOIN t2 ON a=b UNION
SELECT NULL, NULL, NULL
LIMIT 3)
ORDER BY b-a-c;
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b UNION
SELECT NULL, NULL, NULL
LIMIT 3)
ORDER BY b-a-c;
--sorted_result
(SELECT * FROM t1 JOIN t2 ON a=b UNION
SELECT NULL, NULL, NULL
ORDER BY a LIMIT 3)
ORDER BY b-a-c LIMIT 1;
EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b UNION
SELECT NULL, NULL, NULL
ORDER BY a LIMIT 3)
ORDER BY b-a-c LIMIT 1;
DROP TABLE t1, t2;
--echo # End of 10.4 tests
......@@ -9414,8 +9414,17 @@ bool Lex_order_limit_lock::set_to(SELECT_LEX *sel)
"CUBE/ROLLUP", "ORDER BY");
return TRUE;
}
for (ORDER *order= order_list->first; order; order= order->next)
(*order->item)->walk(&Item::change_context_processor, FALSE,
&sel->context);
sel->order_list= *(order_list);
}
if (limit.select_limit)
limit.select_limit->walk(&Item::change_context_processor, FALSE,
&sel->context);
if (limit.offset_limit)
limit.offset_limit->walk(&Item::change_context_processor, FALSE,
&sel->context);
sel->is_set_query_expr_tail= true;
return FALSE;
}
......
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