summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/type_newdecimal.result39
-rw-r--r--mysql-test/t/type_newdecimal.test27
-rw-r--r--sql/item_cmpfunc.cc16
3 files changed, 82 insertions, 0 deletions
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
index 2f6a3ea2a61..56a04971fa1 100644
--- a/mysql-test/r/type_newdecimal.result
+++ b/mysql-test/r/type_newdecimal.result
@@ -2243,3 +2243,42 @@ DROP TABLE t1;
#
# End of 10.1 tests
#
+#
+# Bug#18408499 UNSIGNED BIGINT HIGH VALUES
+# WRONG NUMERICAL COMPARISON RESULTS
+#
+CREATE TABLE t1(value DECIMAL(24,0) NOT NULL);
+INSERT INTO t1(value)
+VALUES('100000000000000000000001'),
+('100000000000000000000002'),
+('100000000000000000000003');
+SELECT * FROM t1 WHERE value = '100000000000000000000002';
+value
+100000000000000000000002
+SELECT * FROM t1 WHERE '100000000000000000000002' = value;
+value
+100000000000000000000002
+SELECT * FROM t1 WHERE value + 0 = '100000000000000000000002';
+value
+100000000000000000000002
+SELECT * FROM t1 WHERE value = 100000000000000000000002;
+value
+100000000000000000000002
+SELECT * FROM t1 WHERE value + 0 = 100000000000000000000002;
+value
+100000000000000000000002
+PREPARE stmt FROM 'SELECT * FROM t1 WHERE value = ?';
+set @a="100000000000000000000002";
+EXECUTE stmt using @a;
+value
+100000000000000000000002
+set @a=100000000000000000000002;
+EXECUTE stmt using @a;
+value
+100000000000000000000002
+DEALLOCATE PREPARE stmt;
+ALTER TABLE t1 ADD INDEX value (value);
+SELECT * FROM t1 WHERE value = '100000000000000000000002';
+value
+100000000000000000000002
+DROP TABLE t1;
diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test
index b84d01e93be..6fb8fd4f97d 100644
--- a/mysql-test/t/type_newdecimal.test
+++ b/mysql-test/t/type_newdecimal.test
@@ -1738,3 +1738,30 @@ DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #
+
+--echo #
+--echo # Bug#18408499 UNSIGNED BIGINT HIGH VALUES
+--echo # WRONG NUMERICAL COMPARISON RESULTS
+--echo #
+
+CREATE TABLE t1(value DECIMAL(24,0) NOT NULL);
+INSERT INTO t1(value)
+VALUES('100000000000000000000001'),
+ ('100000000000000000000002'),
+ ('100000000000000000000003');
+SELECT * FROM t1 WHERE value = '100000000000000000000002';
+SELECT * FROM t1 WHERE '100000000000000000000002' = value;
+SELECT * FROM t1 WHERE value + 0 = '100000000000000000000002';
+SELECT * FROM t1 WHERE value = 100000000000000000000002;
+SELECT * FROM t1 WHERE value + 0 = 100000000000000000000002;
+
+PREPARE stmt FROM 'SELECT * FROM t1 WHERE value = ?';
+set @a="100000000000000000000002";
+EXECUTE stmt using @a;
+set @a=100000000000000000000002;
+EXECUTE stmt using @a;
+DEALLOCATE PREPARE stmt;
+
+ALTER TABLE t1 ADD INDEX value (value);
+SELECT * FROM t1 WHERE value = '100000000000000000000002';
+DROP TABLE t1;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 7a7b2ca2933..e78f73ee03c 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -655,6 +655,22 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg,
return 0;
}
+ if (m_compare_type == REAL_RESULT &&
+ (((*a)->result_type() == DECIMAL_RESULT && !(*a)->const_item() &&
+ (*b)->result_type() == STRING_RESULT && (*b)->const_item()) ||
+ ((*b)->result_type() == DECIMAL_RESULT && !(*b)->const_item() &&
+ (*a)->result_type() == STRING_RESULT && (*a)->const_item())))
+ {
+ /*
+ <non-const decimal expression> <cmp> <const string expression>
+ or
+ <const string expression> <cmp> <non-const decimal expression>
+
+ Do comparison as decimal rather than float, in order not to lose precision.
+ */
+ m_compare_type= DECIMAL_RESULT;
+ }
+
if (m_compare_type == INT_RESULT &&
(*a)->field_type() == MYSQL_TYPE_YEAR &&
(*b)->field_type() == MYSQL_TYPE_YEAR)