Commit 3c209bfc authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-25994: Crash with union of my_decimal type in ORDER BY clause

When single-row subquery fails with "Subquery reutrns more than 1 row"
error, it will raise an error and return NULL.

On the other hand, Item_singlerow_subselect sets item->maybe_null=0
for table-less subqueries like "(SELECT not_null_value)"  (*)

This discrepancy (item with maybe_null=0 returning NULL) causes the
code in Type_handler_decimal_result::make_sort_key_part() to crash.

Fixed this by allowing inference (*) only when the subquery is NOT a
UNION.
parent 2be617d8
......@@ -3508,4 +3508,24 @@ DELETE FROM t1 ORDER BY c;
DROP TABLE t1;
SET @@SESSION.max_sort_length=DEFAULT;
SET sql_mode=DEFAULT;
#
# MDEV-25994 Crash with union of my_decimal type in ORDER BY clause
#
CREATE TABLE t1 (v1 INTEGER) ;
INSERT INTO t1 (v1) VALUES (8);
UPDATE t1 SET v1 = 1 ORDER BY (SELECT 1.1 UNION SELECT -1);
ERROR 21000: Subquery returns more than 1 row
# This one must be successful
UPDATE t1 SET v1 = 2 ORDER BY (SELECT 1 UNION SELECT 1);
UPDATE t1 SET v1 = 3 ORDER BY (SELECT 'a' UNION SELECT 'b');
ERROR 21000: Subquery returns more than 1 row
# Insert some more data
INSERT INTO t1 (v1) VALUES (8),(9),(100),(-234),(46584),(0);
UPDATE t1 SET v1 = v1+1 ORDER BY (SELECT 100.122 UNION SELECT -189.2);
ERROR 21000: Subquery returns more than 1 row
# This one must be successful
UPDATE t1 SET v1 = v1-200 ORDER BY (SELECT 1 UNION SELECT 1);
UPDATE t1 SET v1 = v1 ORDER BY (SELECT 'abc' UNION SELECT 'bbb');
ERROR 21000: Subquery returns more than 1 row
DROP TABLE t1;
# End of 10.2 tests
......@@ -1261,7 +1261,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL
`a` bigint(20) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
......
......@@ -1265,7 +1265,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL
`a` bigint(20) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
......
......@@ -1268,7 +1268,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL
`a` bigint(20) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
......
......@@ -1264,7 +1264,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL
`a` bigint(20) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
......
......@@ -1267,7 +1267,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL
`a` bigint(20) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
......
......@@ -1264,7 +1264,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL
`a` bigint(20) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
......
......@@ -2331,5 +2331,30 @@ DROP TABLE t1;
SET @@SESSION.max_sort_length=DEFAULT;
SET sql_mode=DEFAULT;
--echo #
--echo # MDEV-25994 Crash with union of my_decimal type in ORDER BY clause
--echo #
CREATE TABLE t1 (v1 INTEGER) ;
INSERT INTO t1 (v1) VALUES (8);
--error ER_SUBQUERY_NO_1_ROW
UPDATE t1 SET v1 = 1 ORDER BY (SELECT 1.1 UNION SELECT -1);
--echo # This one must be successful
UPDATE t1 SET v1 = 2 ORDER BY (SELECT 1 UNION SELECT 1);
--error ER_SUBQUERY_NO_1_ROW
UPDATE t1 SET v1 = 3 ORDER BY (SELECT 'a' UNION SELECT 'b');
-- echo # Insert some more data
INSERT INTO t1 (v1) VALUES (8),(9),(100),(-234),(46584),(0);
--error ER_SUBQUERY_NO_1_ROW
UPDATE t1 SET v1 = v1+1 ORDER BY (SELECT 100.122 UNION SELECT -189.2);
--echo # This one must be successful
UPDATE t1 SET v1 = v1-200 ORDER BY (SELECT 1 UNION SELECT 1);
--error ER_SUBQUERY_NO_1_ROW
UPDATE t1 SET v1 = v1 ORDER BY (SELECT 'abc' UNION SELECT 'bbb');
DROP TABLE t1;
--echo # End of 10.2 tests
......@@ -1266,11 +1266,18 @@ bool Item_singlerow_subselect::fix_length_and_dec()
}
unsigned_flag= value->unsigned_flag;
/*
If there are not tables in subquery then ability to have NULL value
depends on SELECT list (if single row subquery have tables then it
always can be NULL if there are not records fetched).
If the subquery has no tables (1) and is not a UNION (2), like:
(SELECT subq_value)
then its NULLability is the same as subq_value's NULLability.
(1): A subquery that uses a table will return NULL when the table is empty.
(2): A UNION subquery will return NULL if it produces a "Subquery returns
more than one row" error.
*/
if (engine->no_tables())
if (engine->no_tables() &&
engine->engine_type() != subselect_engine::UNION_ENGINE)
maybe_null= engine->may_be_null();
else
{
......
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