summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2021-11-20 21:49:25 +0400
committerAlexander Barkov <bar@mariadb.com>2021-11-20 21:49:25 +0400
commite9f171b4fe65399e9ebbb1660198b690582e2ef5 (patch)
treead1e23e9dd8c256a79ee26620533611c6adf5f14
parent7efcc2794d698f62074290232e0f71234c7a4b41 (diff)
downloadmariadb-git-e9f171b4fe65399e9ebbb1660198b690582e2ef5.tar.gz
MDEV-27098 Subquery using the ALL keyword on TIME columns produces a wrong resultbb-10.2-bar
-rw-r--r--mysql-test/r/type_time.result12
-rw-r--r--mysql-test/t/type_time.test10
-rw-r--r--sql/sql_class.cc25
-rw-r--r--sql/sql_class.h1
4 files changed, 46 insertions, 2 deletions
diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result
index 90d09ea595f..6e041236ff9 100644
--- a/mysql-test/r/type_time.result
+++ b/mysql-test/r/type_time.result
@@ -1368,5 +1368,17 @@ Warning 1292 Incorrect datetime value: '1995.0000000'
Note 1003 select `test`.`t1`.`f` AS `f` from `test`.`t1` where '00:00:00.000000' between `test`.`t1`.`f` and <cache>('23:59:59')
DROP TABLE t1;
#
+# MDEV-27098 Subquery using the ALL keyword on TIME columns produces a wrong result
+#
+CREATE TABLE t1 (d TIME);
+INSERT INTO t1 VALUES ('120:00:00'), ('20:00:00'), ('-120:00:00'), ('-220:00:00');
+SELECT * FROM t1 WHERE d >= ALL (SELECT * FROM t1);
+d
+120:00:00
+SELECT * FROM t1 WHERE d <= ALL (SELECT * FROM t1);
+d
+-220:00:00
+DROP TABLE t1;
+#
# End of 10.2 tests
#
diff --git a/mysql-test/t/type_time.test b/mysql-test/t/type_time.test
index 9ef80cf28fb..7c1a411df37 100644
--- a/mysql-test/t/type_time.test
+++ b/mysql-test/t/type_time.test
@@ -824,5 +824,15 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1995.0000000 BETWEEN f AND '23:59:59';
DROP TABLE t1;
--echo #
+--echo # MDEV-27098 Subquery using the ALL keyword on TIME columns produces a wrong result
+--echo #
+
+CREATE TABLE t1 (d TIME);
+INSERT INTO t1 VALUES ('120:00:00'), ('20:00:00'), ('-120:00:00'), ('-220:00:00');
+SELECT * FROM t1 WHERE d >= ALL (SELECT * FROM t1);
+SELECT * FROM t1 WHERE d <= ALL (SELECT * FROM t1);
+DROP TABLE t1;
+
+--echo #
--echo # End of 10.2 tests
--echo #
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 21c06029787..479578679f1 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -3394,7 +3394,7 @@ int select_max_min_finder_subselect::send_data(List<Item> &items)
if (!cache)
{
cache= Item_cache::get_cache(thd, val_item);
- switch (val_item->result_type()) {
+ switch (val_item->cmp_type()) {
case REAL_RESULT:
op= &select_max_min_finder_subselect::cmp_real;
break;
@@ -3407,8 +3407,13 @@ int select_max_min_finder_subselect::send_data(List<Item> &items)
case DECIMAL_RESULT:
op= &select_max_min_finder_subselect::cmp_decimal;
break;
- case ROW_RESULT:
case TIME_RESULT:
+ if (val_item->field_type() == MYSQL_TYPE_TIME)
+ op= &select_max_min_finder_subselect::cmp_time;
+ else
+ op= &select_max_min_finder_subselect::cmp_str;
+ break;
+ case ROW_RESULT:
// This case should never be choosen
DBUG_ASSERT(0);
op= 0;
@@ -3453,6 +3458,22 @@ bool select_max_min_finder_subselect::cmp_int()
return (val1 < val2);
}
+bool select_max_min_finder_subselect::cmp_time()
+{
+ Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
+ longlong val1= cache->val_time_packed(), val2= maxmin->val_time_packed();
+
+ /* Ignore NULLs for ANY and keep them for ALL subqueries */
+ if (cache->null_value)
+ return (is_all && !maxmin->null_value) || (!is_all && maxmin->null_value);
+ if (maxmin->null_value)
+ return !is_all;
+
+ if (fmax)
+ return(val1 > val2);
+ return (val1 < val2);
+}
+
bool select_max_min_finder_subselect::cmp_decimal()
{
Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a767a34d869..9fff422684e 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -5396,6 +5396,7 @@ public:
bool cmp_int();
bool cmp_decimal();
bool cmp_str();
+ bool cmp_time();
};
/* EXISTS subselect interface class */