summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2020-06-05 12:57:42 +0400
committerAlexander Barkov <bar@mariadb.com>2020-06-06 11:33:11 +0400
commit79cdd7e76bbebf62629066166f43279095a0fcc9 (patch)
treef18fc41438f97b84427815e6b82727706c86b4c0
parenta793ae5bc1270b18ab9359363dedab951f9a912f (diff)
downloadmariadb-git-79cdd7e76bbebf62629066166f43279095a0fcc9.tar.gz
MDEV-20305 Data loss on DOUBLE and DECIMAL conversion to INT
Bit operators (~ ^ | & << >>) and the function BIT_COUNT() always called val_int() for their arguments. It worked correctly only for INT type arguments. In case of DECIMAL and DOUBLE arguments it did not work well: the argument values were truncated to the maximum SIGNED BIGINT value of 9223372036854775807. Fixing the code as follows: - If the argument if of an integer data type, it works using val_int() as before. - If the argument if of some other data type, it gets the argument value using val_decimal(), to avoid truncation, and then converts the result to ulonglong. Using Item_handled_func to switch between the two approaches easier. As an additional advantage, with Item_handled_func it will be easier to implement overloading in the future, so data type plugings will be able to define their own behavioir of bit operators and BIT_COUNT(). Moving the code from the former val_int() implementations as methods to Longlong_null, to avoid code duplication in the INT and DECIMAL branches.
-rw-r--r--mysql-test/main/func_bit.result367
-rw-r--r--mysql-test/main/func_bit.test97
-rw-r--r--mysql-test/main/func_group.result2
-rw-r--r--mysql-test/main/func_str.result4
-rw-r--r--mysql-test/main/func_time.result2
-rw-r--r--mysql-test/suite/engines/iuds/r/type_bit_iuds.result54
-rw-r--r--sql/item_cmpfunc.cc78
-rw-r--r--sql/item_func.cc187
-rw-r--r--sql/item_func.h153
-rw-r--r--sql/my_decimal.h10
-rw-r--r--sql/sql_type.h4
-rw-r--r--sql/sql_type_int.h54
12 files changed, 890 insertions, 122 deletions
diff --git a/mysql-test/main/func_bit.result b/mysql-test/main/func_bit.result
new file mode 100644
index 00000000000..4eb44f76ef3
--- /dev/null
+++ b/mysql-test/main/func_bit.result
@@ -0,0 +1,367 @@
+#
+# Start of 10.5 tests
+#
+#
+# MDEV-20305 Data loss on DOUBLE and DECIMAL conversion to INT
+#
+CREATE PROCEDURE p1(type VARCHAR(64), val VARCHAR(64))
+BEGIN
+EXECUTE IMMEDIATE CONCAT('CREATE TABLE t1 (a ', type, ')');
+SHOW CREATE TABLE t1;
+EXECUTE IMMEDIATE CONCAT('INSERT INTO t1 VALUES (', val, ')');
+SELECT
+a,
+~a,
+a & 18446744073709551615,
+18446744073709551615 & a,
+0 | a,
+a | 0,
+a << 0,
+a >> 0,
+a ^ 1,
+1 ^ a,
+BIT_COUNT(a)
+FROM t1;
+SHOW WARNINGS;
+DROP TABLE t1;
+END;
+$$
+CALL p1('BIGINT UNSIGNED', 18446744073709551615);
+Table t1
+Create Table CREATE TABLE `t1` (
+ `a` bigint(20) unsigned DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+a 18446744073709551615
+~a 0
+a & 18446744073709551615 18446744073709551615
+18446744073709551615 & a 18446744073709551615
+0 | a 18446744073709551615
+a | 0 18446744073709551615
+a << 0 18446744073709551615
+a >> 0 18446744073709551615
+a ^ 1 18446744073709551614
+1 ^ a 18446744073709551614
+BIT_COUNT(a) 64
+CALL p1('DOUBLE', 18446744073709551615);
+Table t1
+Create Table CREATE TABLE `t1` (
+ `a` double DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+a 1.8446744073709552e19
+~a 0
+a & 18446744073709551615 18446744073709551615
+18446744073709551615 & a 18446744073709551615
+0 | a 18446744073709551615
+a | 0 18446744073709551615
+a << 0 18446744073709551615
+a >> 0 18446744073709551615
+a ^ 1 18446744073709551614
+1 ^ a 18446744073709551614
+BIT_COUNT(a) 64
+Level Warning
+Code 1916
+Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+CALL p1('DECIMAL(30,0)', 18446744073709551615);
+Table t1
+Create Table CREATE TABLE `t1` (
+ `a` decimal(30,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+a 18446744073709551615
+~a 0
+a & 18446744073709551615 18446744073709551615
+18446744073709551615 & a 18446744073709551615
+0 | a 18446744073709551615
+a | 0 18446744073709551615
+a << 0 18446744073709551615
+a >> 0 18446744073709551615
+a ^ 1 18446744073709551614
+1 ^ a 18446744073709551614
+BIT_COUNT(a) 64
+CALL p1('BIGINT', -1);
+Table t1
+Create Table CREATE TABLE `t1` (
+ `a` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+a -1
+~a 0
+a & 18446744073709551615 18446744073709551615
+18446744073709551615 & a 18446744073709551615
+0 | a 18446744073709551615
+a | 0 18446744073709551615
+a << 0 18446744073709551615
+a >> 0 18446744073709551615
+a ^ 1 18446744073709551614
+1 ^ a 18446744073709551614
+BIT_COUNT(a) 64
+CALL p1('DOUBLE', -1);
+Table t1
+Create Table CREATE TABLE `t1` (
+ `a` double DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+a -1
+~a 0
+a & 18446744073709551615 18446744073709551615
+18446744073709551615 & a 18446744073709551615
+0 | a 18446744073709551615
+a | 0 18446744073709551615
+a << 0 18446744073709551615
+a >> 0 18446744073709551615
+a ^ 1 18446744073709551614
+1 ^ a 18446744073709551614
+BIT_COUNT(a) 64
+CALL p1('DECIMAL(30,0)', -1);
+Table t1
+Create Table CREATE TABLE `t1` (
+ `a` decimal(30,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+a -1
+~a 0
+a & 18446744073709551615 18446744073709551615
+18446744073709551615 & a 18446744073709551615
+0 | a 18446744073709551615
+a | 0 18446744073709551615
+a << 0 18446744073709551615
+a >> 0 18446744073709551615
+a ^ 1 18446744073709551614
+1 ^ a 18446744073709551614
+BIT_COUNT(a) 64
+CALL p1('BIGINT', -9223372036854775808);
+Table t1
+Create Table CREATE TABLE `t1` (
+ `a` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+a -9223372036854775808
+~a 9223372036854775807
+a & 18446744073709551615 9223372036854775808
+18446744073709551615 & a 9223372036854775808
+0 | a 9223372036854775808
+a | 0 9223372036854775808
+a << 0 9223372036854775808
+a >> 0 9223372036854775808
+a ^ 1 9223372036854775809
+1 ^ a 9223372036854775809
+BIT_COUNT(a) 1
+CALL p1('DOUBLE', -9223372036854775808);
+Table t1
+Create Table CREATE TABLE `t1` (
+ `a` double DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+a -9.223372036854776e18
+~a 9223372036854775807
+a & 18446744073709551615 9223372036854775808
+18446744073709551615 & a 9223372036854775808
+0 | a 9223372036854775808
+a | 0 9223372036854775808
+a << 0 9223372036854775808
+a >> 0 9223372036854775808
+a ^ 1 9223372036854775809
+1 ^ a 9223372036854775809
+BIT_COUNT(a) 1
+Level Warning
+Code 1916
+Message Got overflow when converting '-9223372036854776000' to INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '-9223372036854776000' to INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '-9223372036854776000' to INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '-9223372036854776000' to INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '-9223372036854776000' to INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '-9223372036854776000' to INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '-9223372036854776000' to INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '-9223372036854776000' to INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '-9223372036854776000' to INT. Value truncated
+Level Warning
+Code 1916
+Message Got overflow when converting '-9223372036854776000' to INT. Value truncated
+CALL p1('DECIMAL(30,0)', -9223372036854775808);
+Table t1
+Create Table CREATE TABLE `t1` (
+ `a` decimal(30,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+a -9223372036854775808
+~a 9223372036854775807
+a & 18446744073709551615 9223372036854775808
+18446744073709551615 & a 9223372036854775808
+0 | a 9223372036854775808
+a | 0 9223372036854775808
+a << 0 9223372036854775808
+a >> 0 9223372036854775808
+a ^ 1 9223372036854775809
+1 ^ a 9223372036854775809
+BIT_COUNT(a) 1
+DROP PROCEDURE p1;
+SELECT CAST(CAST(18446744073709551615 AS UNSIGNED) AS DECIMAL(32))<<0 AS c1;
+c1
+18446744073709551615
+SELECT CAST(CAST(18446744073709551615 AS UNSIGNED) AS DOUBLE)<<0 AS c1;
+c1
+18446744073709551615
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+SELECT COALESCE(CAST(CAST(0xFFFFFFFFFFFFFFFF AS UNSIGNED) AS DECIMAL(32))) << 0 AS c1;
+c1
+18446744073709551615
+SELECT COALESCE(CAST(CAST(0xFFFFFFFFFFFFFFFF AS UNSIGNED) AS DOUBLE)) << 0 AS c1;
+c1
+18446744073709551615
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+SELECT 18446744073709551615 ^ 1 AS c1;
+c1
+18446744073709551614
+SELECT 18446744073709551615.0 ^ 1 AS c1;
+c1
+18446744073709551614
+SELECT 18446744073709551615e0 ^ 1 AS c1;
+c1
+18446744073709551614
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+SELECT LAST_VALUE(18446744073709551615) ^ 1 AS c1;
+c1
+18446744073709551614
+SELECT LAST_VALUE(18446744073709551615.0) ^ 1 AS c1;
+c1
+18446744073709551614
+SELECT LAST_VALUE(18446744073709551615e0) ^ 1 AS c1;
+c1
+18446744073709551614
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+SELECT 18446744073709551615 & 18446744073709551615 AS c1;
+c1
+18446744073709551615
+SELECT 18446744073709551615 & 18446744073709551615.0 AS c1;
+c1
+18446744073709551615
+SELECT 18446744073709551615 & 18446744073709551615e0 AS c1;
+c1
+18446744073709551615
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+SELECT 18446744073709551615.0 & 18446744073709551615 AS c1;
+c1
+18446744073709551615
+SELECT 18446744073709551615.0 & 18446744073709551615.0 AS c1;
+c1
+18446744073709551615
+SELECT 18446744073709551615.0 & 18446744073709551615e0 AS c1;
+c1
+18446744073709551615
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+SELECT 18446744073709551615e0 & 18446744073709551615 AS c1;
+c1
+18446744073709551615
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+SELECT 18446744073709551615e0 & 18446744073709551615.0 AS c1;
+c1
+18446744073709551615
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+SELECT 18446744073709551615e0 & 18446744073709551615e0 AS c1;
+c1
+18446744073709551615
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+SELECT 0 | 18446744073709551615 AS c1;
+c1
+18446744073709551615
+SELECT 0 | 18446744073709551615.0 AS c1;
+c1
+18446744073709551615
+SELECT 0 | 18446744073709551615e0 AS c1;
+c1
+18446744073709551615
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+SELECT 18446744073709551615 | 0 AS c1;
+c1
+18446744073709551615
+SELECT 18446744073709551615.0 | 0 AS c1;
+c1
+18446744073709551615
+SELECT 18446744073709551615e0 | 0 AS c1;
+c1
+18446744073709551615
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+SELECT ~18446744073709551615 AS c1;
+c1
+0
+SELECT ~18446744073709551615.0 AS c1;
+c1
+0
+SELECT ~18446744073709551615e0 AS c1;
+c1
+0
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+SELECT BIT_COUNT(18446744073709551615) AS c1;
+c1
+64
+SELECT BIT_COUNT(18446744073709551615.0) AS c1;
+c1
+64
+SELECT BIT_COUNT(18446744073709551615e0) AS c1;
+c1
+64
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated
+SELECT BIT_COUNT(-9223372036854775808) AS c1;
+c1
+1
+SELECT BIT_COUNT(-9223372036854775808.0) AS c1;
+c1
+1
+SELECT BIT_COUNT(-9223372036854775808e0) AS c1;
+c1
+1
+Warnings:
+Warning 1916 Got overflow when converting '-9223372036854776000' to INT. Value truncated
+#
+# End of 10.5 tests
+#
diff --git a/mysql-test/main/func_bit.test b/mysql-test/main/func_bit.test
new file mode 100644
index 00000000000..e4f3189eafc
--- /dev/null
+++ b/mysql-test/main/func_bit.test
@@ -0,0 +1,97 @@
+--echo #
+--echo # Start of 10.5 tests
+--echo #
+
+--echo #
+--echo # MDEV-20305 Data loss on DOUBLE and DECIMAL conversion to INT
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(type VARCHAR(64), val VARCHAR(64))
+BEGIN
+ EXECUTE IMMEDIATE CONCAT('CREATE TABLE t1 (a ', type, ')');
+ SHOW CREATE TABLE t1;
+ EXECUTE IMMEDIATE CONCAT('INSERT INTO t1 VALUES (', val, ')');
+ SELECT
+ a,
+ ~a,
+ a & 18446744073709551615,
+ 18446744073709551615 & a,
+ 0 | a,
+ a | 0,
+ a << 0,
+ a >> 0,
+ a ^ 1,
+ 1 ^ a,
+ BIT_COUNT(a)
+ FROM t1;
+ SHOW WARNINGS;
+ DROP TABLE t1;
+END;
+$$
+DELIMITER ;$$
+
+--vertical_results
+CALL p1('BIGINT UNSIGNED', 18446744073709551615);
+CALL p1('DOUBLE', 18446744073709551615);
+CALL p1('DECIMAL(30,0)', 18446744073709551615);
+
+CALL p1('BIGINT', -1);
+CALL p1('DOUBLE', -1);
+CALL p1('DECIMAL(30,0)', -1);
+
+CALL p1('BIGINT', -9223372036854775808);
+CALL p1('DOUBLE', -9223372036854775808);
+CALL p1('DECIMAL(30,0)', -9223372036854775808);
+--horizontal_results
+
+DROP PROCEDURE p1;
+
+
+SELECT CAST(CAST(18446744073709551615 AS UNSIGNED) AS DECIMAL(32))<<0 AS c1;
+SELECT CAST(CAST(18446744073709551615 AS UNSIGNED) AS DOUBLE)<<0 AS c1;
+
+SELECT COALESCE(CAST(CAST(0xFFFFFFFFFFFFFFFF AS UNSIGNED) AS DECIMAL(32))) << 0 AS c1;
+SELECT COALESCE(CAST(CAST(0xFFFFFFFFFFFFFFFF AS UNSIGNED) AS DOUBLE)) << 0 AS c1;
+
+SELECT 18446744073709551615 ^ 1 AS c1;
+SELECT 18446744073709551615.0 ^ 1 AS c1;
+SELECT 18446744073709551615e0 ^ 1 AS c1;
+
+SELECT LAST_VALUE(18446744073709551615) ^ 1 AS c1;
+SELECT LAST_VALUE(18446744073709551615.0) ^ 1 AS c1;
+SELECT LAST_VALUE(18446744073709551615e0) ^ 1 AS c1;
+
+SELECT 18446744073709551615 & 18446744073709551615 AS c1;
+SELECT 18446744073709551615 & 18446744073709551615.0 AS c1;
+SELECT 18446744073709551615 & 18446744073709551615e0 AS c1;
+SELECT 18446744073709551615.0 & 18446744073709551615 AS c1;
+SELECT 18446744073709551615.0 & 18446744073709551615.0 AS c1;
+SELECT 18446744073709551615.0 & 18446744073709551615e0 AS c1;
+SELECT 18446744073709551615e0 & 18446744073709551615 AS c1;
+SELECT 18446744073709551615e0 & 18446744073709551615.0 AS c1;
+SELECT 18446744073709551615e0 & 18446744073709551615e0 AS c1;
+
+
+SELECT 0 | 18446744073709551615 AS c1;
+SELECT 0 | 18446744073709551615.0 AS c1;
+SELECT 0 | 18446744073709551615e0 AS c1;
+SELECT 18446744073709551615 | 0 AS c1;
+SELECT 18446744073709551615.0 | 0 AS c1;
+SELECT 18446744073709551615e0 | 0 AS c1;
+
+SELECT ~18446744073709551615 AS c1;
+SELECT ~18446744073709551615.0 AS c1;
+SELECT ~18446744073709551615e0 AS c1;
+
+SELECT BIT_COUNT(18446744073709551615) AS c1;
+SELECT BIT_COUNT(18446744073709551615.0) AS c1;
+SELECT BIT_COUNT(18446744073709551615e0) AS c1;
+
+SELECT BIT_COUNT(-9223372036854775808) AS c1;
+SELECT BIT_COUNT(-9223372036854775808.0) AS c1;
+SELECT BIT_COUNT(-9223372036854775808e0) AS c1;
+
+--echo #
+--echo # End of 10.5 tests
+--echo #
diff --git a/mysql-test/main/func_group.result b/mysql-test/main/func_group.result
index 088ddf22e59..1fc92ba90cc 100644
--- a/mysql-test/main/func_group.result
+++ b/mysql-test/main/func_group.result
@@ -2326,7 +2326,7 @@ SELECT MAX('x') << 1, CAST(MAX('x') AS DOUBLE), CAST(MAX('x') AS DECIMAL);
MAX('x') << 1 CAST(MAX('x') AS DOUBLE) CAST(MAX('x') AS DECIMAL)
0 0 0
Warnings:
-Warning 1292 Truncated incorrect INTEGER value: 'x'
+Warning 1292 Truncated incorrect DECIMAL value: 'x'
Warning 1292 Truncated incorrect DOUBLE value: 'x'
Warning 1292 Truncated incorrect DECIMAL value: 'x'
#
diff --git a/mysql-test/main/func_str.result b/mysql-test/main/func_str.result
index 6fc61dc0f5f..992363c6b91 100644
--- a/mysql-test/main/func_str.result
+++ b/mysql-test/main/func_str.result
@@ -3071,7 +3071,7 @@ SELECT ((rpad(1.0,2048,1)) = ('4(') ^ (0.1));
((rpad(1.0,2048,1)) = ('4(') ^ (0.1))
0
Warnings:
-Warning 1292 Truncated incorrect INTEGER value: '4('
+Warning 1292 Truncated incorrect DECIMAL value: '4('
SELECT
pow((rpad(10.0,2048,1)),(b'1111111111111111111111111111111111111111111'));
ERROR 22003: DOUBLE value is out of range in 'pow(rpad(10.0,2048,1),0x07ffffffffff)'
@@ -3079,7 +3079,7 @@ SELECT ((rpad(1.0,2048,1)) + (0) ^ ('../'));
((rpad(1.0,2048,1)) + (0) ^ ('../'))
1.011111111111111
Warnings:
-Warning 1292 Truncated incorrect INTEGER value: '../'
+Warning 1292 Truncated incorrect DECIMAL value: '../'
SELECT stddev_samp(rpad(1.0,2048,1));
stddev_samp(rpad(1.0,2048,1))
NULL
diff --git a/mysql-test/main/func_time.result b/mysql-test/main/func_time.result
index a9b27a15fa7..d44f634db08 100644
--- a/mysql-test/main/func_time.result
+++ b/mysql-test/main/func_time.result
@@ -2795,7 +2795,7 @@ SET sql_mode=DEFAULT;
DO TO_DAYS(SEC_TO_TIME(TIME(CEILING(UUID()))));
DO TO_DAYS(SEC_TO_TIME(MAKEDATE('',RAND(~('')))));
Warnings:
-Warning 1292 Truncated incorrect INTEGER value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1292 Truncated incorrect INTEGER value: ''
Warning 1292 Truncated incorrect seconds value: '20000101'
SELECT SEC_TO_TIME(MAKEDATE(0,RAND(~0)));
diff --git a/mysql-test/suite/engines/iuds/r/type_bit_iuds.result b/mysql-test/suite/engines/iuds/r/type_bit_iuds.result
index 2c84abfd49d..93ed7a9f162 100644
--- a/mysql-test/suite/engines/iuds/r/type_bit_iuds.result
+++ b/mysql-test/suite/engines/iuds/r/type_bit_iuds.result
@@ -56209,9 +56209,9 @@ SELECT 0 + b'101010101010101010101010101010';
715827882
SELECT 0 + (101010101010101010101010101010<<0);
0 + (101010101010101010101010101010<<0)
-9223372036854775807
+18446744073709551615
Warnings:
-Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(0));
CREATE TABLE t2(c1 BIT(0), c2 BIT(0), c3 BIT(0));
INSERT IGNORE INTO t1 VALUES (b'101010101010101010101010101010');
@@ -57001,7 +57001,7 @@ SELECT 0 + (101010101010101010101010101010<<1);
0 + (101010101010101010101010101010<<1)
18446744073709551614
Warnings:
-Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(1));
CREATE TABLE t2(c1 BIT(1), c2 BIT(1), c3 BIT(1));
set @v1=1;
@@ -57840,7 +57840,7 @@ SELECT 0 + (101010101010101010101010101010<<2);
0 + (101010101010101010101010101010<<2)
18446744073709551612
Warnings:
-Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(2));
CREATE TABLE t2(c1 BIT(2), c2 BIT(2), c3 BIT(2));
set @v1=2;
@@ -58698,7 +58698,7 @@ SELECT 0 + (101010101010101010101010101010<<4);
0 + (101010101010101010101010101010<<4)
18446744073709551600
Warnings:
-Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(4));
CREATE TABLE t2(c1 BIT(4), c2 BIT(4), c3 BIT(4));
set @v1=4;
@@ -59620,7 +59620,7 @@ SELECT 0 + (101010101010101010101010101010<<8);
0 + (101010101010101010101010101010<<8)
18446744073709551360
Warnings:
-Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(8));
CREATE TABLE t2(c1 BIT(8), c2 BIT(8), c3 BIT(8));
set @v1=8;
@@ -60827,7 +60827,7 @@ SELECT 0 + (101010101010101010101010101010<<16);
0 + (101010101010101010101010101010<<16)
18446744073709486080
Warnings:
-Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(16));
CREATE TABLE t2(c1 BIT(16), c2 BIT(16), c3 BIT(16));
set @v1=16;
@@ -62239,7 +62239,7 @@ SELECT 0 + (101010101010101010101010101010<<32);
0 + (101010101010101010101010101010<<32)
18446744069414584320
Warnings:
-Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(32));
CREATE TABLE t2(c1 BIT(32), c2 BIT(32), c3 BIT(32));
set @v1=32;
@@ -64312,7 +64312,7 @@ SELECT 0 + (101010101010101010101010101010<<64);
0 + (101010101010101010101010101010<<64)
0
Warnings:
-Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(64));
CREATE TABLE t2(c1 BIT(64), c2 BIT(64), c3 BIT(64));
set @v1=64;
@@ -67487,9 +67487,9 @@ Warnings:
Note 1051 Unknown table 'test.t3'
SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<0);
0 + (1010101010101010101010101010101010101010101010101010101010101010<<0)
-9223372036854775807
+18446744073709551615
Warnings:
-Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(0));
CREATE TABLE t2(c1 BIT(0), c2 BIT(0), c3 BIT(0));
INSERT IGNORE INTO t1 VALUES (b'1010101010101010101010101010101010101010101010101010101010101010');
@@ -68276,7 +68276,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<1)
0 + (1010101010101010101010101010101010101010101010101010101010101010<<1)
18446744073709551614
Warnings:
-Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(1));
CREATE TABLE t2(c1 BIT(1), c2 BIT(1), c3 BIT(1));
set @v1=1;
@@ -69112,7 +69112,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<2)
0 + (1010101010101010101010101010101010101010101010101010101010101010<<2)
18446744073709551612
Warnings:
-Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(2));
CREATE TABLE t2(c1 BIT(2), c2 BIT(2), c3 BIT(2));
set @v1=2;
@@ -69967,7 +69967,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<4)
0 + (1010101010101010101010101010101010101010101010101010101010101010<<4)
18446744073709551600
Warnings:
-Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(4));
CREATE TABLE t2(c1 BIT(4), c2 BIT(4), c3 BIT(4));
set @v1=4;
@@ -70886,7 +70886,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<8)
0 + (1010101010101010101010101010101010101010101010101010101010101010<<8)
18446744073709551360
Warnings:
-Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(8));
CREATE TABLE t2(c1 BIT(8), c2 BIT(8), c3 BIT(8));
set @v1=8;
@@ -72090,7 +72090,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<16
0 + (1010101010101010101010101010101010101010101010101010101010101010<<16)
18446744073709486080
Warnings:
-Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(16));
CREATE TABLE t2(c1 BIT(16), c2 BIT(16), c3 BIT(16));
set @v1=16;
@@ -73499,7 +73499,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<32
0 + (1010101010101010101010101010101010101010101010101010101010101010<<32)
18446744069414584320
Warnings:
-Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(32));
CREATE TABLE t2(c1 BIT(32), c2 BIT(32), c3 BIT(32));
set @v1=32;
@@ -75575,7 +75575,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<64
0 + (1010101010101010101010101010101010101010101010101010101010101010<<64)
0
Warnings:
-Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated
+Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(64));
CREATE TABLE t2(c1 BIT(64), c2 BIT(64), c3 BIT(64));
set @v1=64;
@@ -78750,9 +78750,9 @@ Warnings:
Note 1051 Unknown table 'test.t3'
SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<0);
0 + (10101010101010101010101010101010101010101010101010101010101010101<<0)
-9223372036854775807
+18446744073709551615
Warnings:
-Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated
+Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(0));
CREATE TABLE t2(c1 BIT(0), c2 BIT(0), c3 BIT(0));
INSERT IGNORE INTO t1 VALUES (b'10101010101010101010101010101010101010101010101010101010101010101');
@@ -79539,7 +79539,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<1
0 + (10101010101010101010101010101010101010101010101010101010101010101<<1)
18446744073709551614
Warnings:
-Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated
+Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(1));
CREATE TABLE t2(c1 BIT(1), c2 BIT(1), c3 BIT(1));
set @v1=1;
@@ -80375,7 +80375,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<2
0 + (10101010101010101010101010101010101010101010101010101010101010101<<2)
18446744073709551612
Warnings:
-Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated
+Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(2));
CREATE TABLE t2(c1 BIT(2), c2 BIT(2), c3 BIT(2));
set @v1=2;
@@ -81230,7 +81230,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<4
0 + (10101010101010101010101010101010101010101010101010101010101010101<<4)
18446744073709551600
Warnings:
-Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated
+Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(4));
CREATE TABLE t2(c1 BIT(4), c2 BIT(4), c3 BIT(4));
set @v1=4;
@@ -82149,7 +82149,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<8
0 + (10101010101010101010101010101010101010101010101010101010101010101<<8)
18446744073709551360
Warnings:
-Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated
+Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(8));
CREATE TABLE t2(c1 BIT(8), c2 BIT(8), c3 BIT(8));
set @v1=8;
@@ -83353,7 +83353,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<1
0 + (10101010101010101010101010101010101010101010101010101010101010101<<16)
18446744073709486080
Warnings:
-Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated
+Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(16));
CREATE TABLE t2(c1 BIT(16), c2 BIT(16), c3 BIT(16));
set @v1=16;
@@ -84762,7 +84762,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<3
0 + (10101010101010101010101010101010101010101010101010101010101010101<<32)
18446744069414584320
Warnings:
-Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated
+Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(32));
CREATE TABLE t2(c1 BIT(32), c2 BIT(32), c3 BIT(32));
set @v1=32;
@@ -86838,7 +86838,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<6
0 + (10101010101010101010101010101010101010101010101010101010101010101<<64)
0
Warnings:
-Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated
+Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated
CREATE TABLE t1(c1 BIT(64));
CREATE TABLE t2(c1 BIT(64), c2 BIT(64), c3 BIT(64));
set @v1=64;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 7fe16848082..24914accc6f 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -4733,43 +4733,73 @@ void Item_func_in::mark_as_condition_AND_part(TABLE_LIST *embedding)
}
-longlong Item_func_bit_or::val_int()
+class Func_handler_bit_or_int_to_ulonglong:
+ public Item_handled_func::Handler_ulonglong
{
- DBUG_ASSERT(fixed == 1);
- ulonglong arg1= (ulonglong) args[0]->val_int();
- if (args[0]->null_value)
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
{
- null_value=1; /* purecov: inspected */
- return 0; /* purecov: inspected */
+ DBUG_ASSERT(item->is_fixed());
+ Longlong_null a= item->arguments()[0]->to_longlong_null();
+ return a.is_null() ? a : a | item->arguments()[1]->to_longlong_null();
}
- ulonglong arg2= (ulonglong) args[1]->val_int();
- if (args[1]->null_value)
+};
+
+
+class Func_handler_bit_or_dec_to_ulonglong:
+ public Item_handled_func::Handler_ulonglong
+{
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
{
- null_value=1;
- return 0;
+ DBUG_ASSERT(item->is_fixed());
+ VDec a(item->arguments()[0]);
+ return a.is_null() ? Longlong_null() :
+ a.to_xlonglong_null() | VDec(item->arguments()[1]).to_xlonglong_null();
}
- null_value=0;
- return (longlong) (arg1 | arg2);
+};
+
+
+bool Item_func_bit_or::fix_length_and_dec()
+{
+ static Func_handler_bit_or_int_to_ulonglong ha_int_to_ull;
+ static Func_handler_bit_or_dec_to_ulonglong ha_dec_to_ull;
+ return fix_length_and_dec_op2_std(&ha_int_to_ull, &ha_dec_to_ull);
}
-longlong Item_func_bit_and::val_int()
+class Func_handler_bit_and_int_to_ulonglong:
+ public Item_handled_func::Handler_ulonglong
{
- DBUG_ASSERT(fixed == 1);
- ulonglong arg1= (ulonglong) args[0]->val_int();
- if (args[0]->null_value)
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
{
- null_value=1; /* purecov: inspected */
- return 0; /* purecov: inspected */
+ DBUG_ASSERT(item->is_fixed());
+ Longlong_null a= item->arguments()[0]->to_longlong_null();
+ return a.is_null() ? a : a & item->arguments()[1]->to_longlong_null();
}
- ulonglong arg2= (ulonglong) args[1]->val_int();
- if (args[1]->null_value)
+};
+
+
+class Func_handler_bit_and_dec_to_ulonglong:
+ public Item_handled_func::Handler_ulonglong
+{
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
{
- null_value=1; /* purecov: inspected */
- return 0; /* purecov: inspected */
+ DBUG_ASSERT(item->is_fixed());
+ VDec a(item->arguments()[0]);
+ return a.is_null() ? Longlong_null() :
+ a.to_xlonglong_null() & VDec(item->arguments()[1]).to_xlonglong_null();
}
- null_value=0;
- return (longlong) (arg1 & arg2);
+};
+
+
+bool Item_func_bit_and::fix_length_and_dec()
+{
+ static Func_handler_bit_and_int_to_ulonglong ha_int_to_ull;
+ static Func_handler_bit_and_dec_to_ulonglong ha_dec_to_ull;
+ return fix_length_and_dec_op2_std(&ha_int_to_ull, &ha_dec_to_ull);
}
Item_cond::Item_cond(THD *thd, Item_cond *item)
diff --git a/sql/item_func.cc b/sql/item_func.cc
index da185f9878b..c3deae59960 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2139,44 +2139,103 @@ double Item_func_cot::val_real()
// Shift-functions, same as << and >> in C/C++
-longlong Item_func_shift_left::val_int()
+class Func_handler_shift_left_int_to_ulonglong:
+ public Item_handled_func::Handler_ulonglong
{
- DBUG_ASSERT(fixed == 1);
- uint shift;
- ulonglong res= ((ulonglong) args[0]->val_int() <<
- (shift=(uint) args[1]->val_int()));
- if (args[0]->null_value || args[1]->null_value)
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
{
- null_value=1;
- return 0;
+ DBUG_ASSERT(item->is_fixed());
+ return item->arguments()[0]->to_longlong_null() <<
+ item->arguments()[1]->to_longlong_null();
}
- null_value=0;
- return (shift < sizeof(longlong)*8 ? (longlong) res : 0);
+};
+
+
+class Func_handler_shift_left_decimal_to_ulonglong:
+ public Item_handled_func::Handler_ulonglong
+{
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
+ {
+ DBUG_ASSERT(item->is_fixed());
+ return VDec(item->arguments()[0]).to_xlonglong_null() <<
+ item->arguments()[1]->to_longlong_null();
+ }
+};
+
+
+bool Item_func_shift_left::fix_length_and_dec()
+{
+ static Func_handler_shift_left_int_to_ulonglong ha_int_to_ull;
+ static Func_handler_shift_left_decimal_to_ulonglong ha_dec_to_ull;
+ return fix_length_and_dec_op1_std(&ha_int_to_ull, &ha_dec_to_ull);
}
-longlong Item_func_shift_right::val_int()
+
+class Func_handler_shift_right_int_to_ulonglong:
+ public Item_handled_func::Handler_ulonglong
{
- DBUG_ASSERT(fixed == 1);
- uint shift;
- ulonglong res= (ulonglong) args[0]->val_int() >>
- (shift=(uint) args[1]->val_int());
- if (args[0]->null_value || args[1]->null_value)
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
{
- null_value=1;
- return 0;
+ DBUG_ASSERT(item->fixed == 1);
+ return item->arguments()[0]->to_longlong_null() >>
+ item->arguments()[1]->to_longlong_null();
}
- null_value=0;
- return (shift < sizeof(longlong)*8 ? (longlong) res : 0);
+};
+
+
+class Func_handler_shift_right_decimal_to_ulonglong:
+ public Item_handled_func::Handler_ulonglong
+{
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
+ {
+ DBUG_ASSERT(item->is_fixed());
+ return VDec(item->arguments()[0]).to_xlonglong_null() >>
+ item->arguments()[1]->to_longlong_null();
+ }
+};
+
+
+bool Item_func_shift_right::fix_length_and_dec()
+{
+ static Func_handler_shift_right_int_to_ulonglong ha_int_to_ull;
+ static Func_handler_shift_right_decimal_to_ulonglong ha_dec_to_ull;
+ return fix_length_and_dec_op1_std(&ha_int_to_ull, &ha_dec_to_ull);
}
-longlong Item_func_bit_neg::val_int()
+class Func_handler_bit_neg_int_to_ulonglong:
+ public Item_handled_func::Handler_ulonglong
{
- DBUG_ASSERT(fixed == 1);
- ulonglong res= (ulonglong) args[0]->val_int();
- if ((null_value=args[0]->null_value))
- return 0;
- return ~res;
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
+ {
+ DBUG_ASSERT(item->is_fixed());
+ return ~ item->arguments()[0]->to_longlong_null();
+ }
+};
+
+
+class Func_handler_bit_neg_decimal_to_ulonglong:
+ public Item_handled_func::Handler_ulonglong
+{
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
+ {
+ DBUG_ASSERT(item->is_fixed());
+ return ~ VDec(item->arguments()[0]).to_xlonglong_null();
+ }
+};
+
+
+bool Item_func_bit_neg::fix_length_and_dec()
+{
+ static Func_handler_bit_neg_int_to_ulonglong ha_int_to_ull;
+ static Func_handler_bit_neg_decimal_to_ulonglong ha_dec_to_ull;
+ return fix_length_and_dec_op1_std(&ha_int_to_ull, &ha_dec_to_ull);
}
@@ -3199,13 +3258,39 @@ longlong Item_func_find_in_set::val_int()
return 0;
}
-longlong Item_func_bit_count::val_int()
+
+class Func_handler_bit_count_int_to_slong:
+ public Item_handled_func::Handler_slong2
{
- DBUG_ASSERT(fixed == 1);
- ulonglong value= (ulonglong) args[0]->val_int();
- if ((null_value= args[0]->null_value))
- return 0; /* purecov: inspected */
- return (longlong) my_count_bits(value);
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
+ {
+ DBUG_ASSERT(item->is_fixed());
+ return item->arguments()[0]->to_longlong_null().bit_count();
+ }
+};
+
+
+class Func_handler_bit_count_decimal_to_slong:
+ public Item_handled_func::Handler_slong2
+{
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
+ {
+ DBUG_ASSERT(item->is_fixed());
+ return VDec(item->arguments()[0]).to_xlonglong_null().bit_count();
+ }
+};
+
+
+bool Item_func_bit_count::fix_length_and_dec()
+{
+ static Func_handler_bit_count_int_to_slong ha_int_to_slong;
+ static Func_handler_bit_count_decimal_to_slong ha_dec_to_slong;
+ set_func_handler(args[0]->cmp_type() == INT_RESULT ?
+ (const Handler *) &ha_int_to_slong :
+ (const Handler *) &ha_dec_to_slong);
+ return m_func_handler->fix_length_and_dec(this);
}
@@ -6221,14 +6306,38 @@ void Item_func_match::print(String *str, enum_query_type query_type)
str->append(STRING_WITH_LEN("))"));
}
-longlong Item_func_bit_xor::val_int()
+
+class Func_handler_bit_xor_int_to_ulonglong:
+ public Item_handled_func::Handler_ulonglong
{
- DBUG_ASSERT(fixed == 1);
- ulonglong arg1= (ulonglong) args[0]->val_int();
- ulonglong arg2= (ulonglong) args[1]->val_int();
- if ((null_value= (args[0]->null_value || args[1]->null_value)))
- return 0;
- return (longlong) (arg1 ^ arg2);
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
+ {
+ DBUG_ASSERT(item->is_fixed());
+ return item->arguments()[0]->to_longlong_null() ^
+ item->arguments()[1]->to_longlong_null();
+ }
+};
+
+
+class Func_handler_bit_xor_dec_to_ulonglong:
+ public Item_handled_func::Handler_ulonglong
+{
+public:
+ Longlong_null to_longlong_null(Item_handled_func *item) const
+ {
+ DBUG_ASSERT(item->is_fixed());
+ return VDec(item->arguments()[0]).to_xlonglong_null() ^
+ VDec(item->arguments()[1]).to_xlonglong_null();
+ }
+};
+
+
+bool Item_func_bit_xor::fix_length_and_dec()
+{
+ static const Func_handler_bit_xor_int_to_ulonglong ha_int_to_ull;
+ static const Func_handler_bit_xor_dec_to_ulonglong ha_dec_to_ull;
+ return fix_length_and_dec_op2_std(&ha_int_to_ull, &ha_dec_to_ull);
}
diff --git a/sql/item_func.h b/sql/item_func.h
index 3771992d617..ca72563581b 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -641,6 +641,87 @@ public:
};
+ class Handler_int: public Handler
+ {
+ public:
+ String *val_str(Item_handled_func *item, String *to) const
+ {
+ longlong nr= val_int(item);
+ if (item->null_value)
+ return 0;
+ to->set_int(nr, item->unsigned_flag, item->collation.collation);
+ return to;
+ }
+ String *val_str_ascii(Item_handled_func *item, String *to) const
+ {
+ return item->Item::val_str_ascii(to);
+ }
+ double val_real(Item_handled_func *item) const
+ {
+ return item->unsigned_flag ? (double) ((ulonglong) val_int(item)) :
+ (double) val_int(item);
+ }
+ my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const
+ {
+ return item->val_decimal_from_int(to);
+ }
+ bool get_date(THD *thd, Item_handled_func *item,
+ MYSQL_TIME *to, date_mode_t fuzzydate) const
+ {
+ return item->get_date_from_int(thd, to, fuzzydate);
+ }
+ longlong val_int(Item_handled_func *item) const
+ {
+ Longlong_null tmp= to_longlong_null(item);
+ item->null_value= tmp.is_null();
+ return tmp.value();
+ }
+ virtual Longlong_null to_longlong_null(Item_handled_func *item) const= 0;
+ };
+
+ class Handler_slong: public Handler_int
+ {
+ public:
+ const Type_handler *return_type_handler(const Item_handled_func *item) const
+ {
+ return &type_handler_slong;
+ }
+ bool fix_length_and_dec(Item_handled_func *item) const
+ {
+ item->unsigned_flag= false;
+ item->collation= DTCollation_numeric();
+ item->fix_char_length(11);
+ return false;
+ }
+ };
+
+ class Handler_slong2: public Handler_slong
+ {
+ public:
+ bool fix_length_and_dec(Item_handled_func *func) const
+ {
+ bool rc= Handler_slong::fix_length_and_dec(func);
+ func->max_length= 2;
+ return rc;
+ }
+ };
+
+ class Handler_ulonglong: public Handler_int
+ {
+ public:
+ const Type_handler *return_type_handler(const Item_handled_func *item) const
+ {
+ return &type_handler_ulonglong;
+ }
+ bool fix_length_and_dec(Item_handled_func *item) const
+ {
+ item->unsigned_flag= true;
+ item->collation= DTCollation_numeric();
+ item->fix_char_length(21);
+ return false;
+ }
+ };
+
protected:
const Handler *m_func_handler;
public:
@@ -2188,84 +2269,99 @@ public:
/* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */
-class Item_func_bit: public Item_longlong_func
+class Item_func_bit_operator: public Item_handled_func
{
bool check_arguments() const
{ return check_argument_types_can_return_int(0, arg_count); }
+protected:
+ bool fix_length_and_dec_op1_std(const Handler *ha_int, const Handler *ha_dec)
+ {
+ set_func_handler(args[0]->cmp_type() == INT_RESULT ? ha_int : ha_dec);
+ return m_func_handler->fix_length_and_dec(this);
+ }
+ bool fix_length_and_dec_op2_std(const Handler *ha_int, const Handler *ha_dec)
+ {
+ set_func_handler(args[0]->cmp_type() == INT_RESULT &&
+ args[1]->cmp_type() == INT_RESULT ? ha_int : ha_dec);
+ return m_func_handler->fix_length_and_dec(this);
+ }
public:
- Item_func_bit(THD *thd, Item *a, Item *b): Item_longlong_func(thd, a, b) {}
- Item_func_bit(THD *thd, Item *a): Item_longlong_func(thd, a) {}
- bool fix_length_and_dec() { unsigned_flag= 1; return FALSE; }
-
- virtual inline void print(String *str, enum_query_type query_type)
+ Item_func_bit_operator(THD *thd, Item *a)
+ :Item_handled_func(thd, a) {}
+ Item_func_bit_operator(THD *thd, Item *a, Item *b)
+ :Item_handled_func(thd, a, b) {}
+ void print(String *str, enum_query_type query_type)
{
print_op(str, query_type);
}
bool need_parentheses_in_default() { return true; }
};
-class Item_func_bit_or :public Item_func_bit
+class Item_func_bit_or :public Item_func_bit_operator
{
public:
- Item_func_bit_or(THD *thd, Item *a, Item *b): Item_func_bit(thd, a, b) {}
- longlong val_int();
+ Item_func_bit_or(THD *thd, Item *a, Item *b)
+ :Item_func_bit_operator(thd, a, b) {}
+ bool fix_length_and_dec();
const char *func_name() const { return "|"; }
enum precedence precedence() const { return BITOR_PRECEDENCE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_bit_or>(thd, this); }
};
-class Item_func_bit_and :public Item_func_bit
+class Item_func_bit_and :public Item_func_bit_operator
{
public:
- Item_func_bit_and(THD *thd, Item *a, Item *b): Item_func_bit(thd, a, b) {}
- longlong val_int();
+ Item_func_bit_and(THD *thd, Item *a, Item *b)
+ :Item_func_bit_operator(thd, a, b) {}
+ bool fix_length_and_dec();
const char *func_name() const { return "&"; }
enum precedence precedence() const { return BITAND_PRECEDENCE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_bit_and>(thd, this); }
};
-class Item_func_bit_count :public Item_long_func
+class Item_func_bit_count :public Item_handled_func
{
bool check_arguments() const
{ return args[0]->check_type_can_return_int(func_name()); }
public:
- Item_func_bit_count(THD *thd, Item *a): Item_long_func(thd, a) {}
- longlong val_int();
+ Item_func_bit_count(THD *thd, Item *a): Item_handled_func(thd, a) {}
const char *func_name() const { return "bit_count"; }
- bool fix_length_and_dec() { max_length=2; return FALSE; }
+ bool fix_length_and_dec();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_bit_count>(thd, this); }
};
-class Item_func_shift_left :public Item_func_bit
+class Item_func_shift_left :public Item_func_bit_operator
{
public:
- Item_func_shift_left(THD *thd, Item *a, Item *b): Item_func_bit(thd, a, b) {}
- longlong val_int();
+ Item_func_shift_left(THD *thd, Item *a, Item *b)
+ :Item_func_bit_operator(thd, a, b) {}
+ bool fix_length_and_dec();
const char *func_name() const { return "<<"; }
enum precedence precedence() const { return SHIFT_PRECEDENCE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_shift_left>(thd, this); }
};
-class Item_func_shift_right :public Item_func_bit
+class Item_func_shift_right :public Item_func_bit_operator
{
public:
- Item_func_shift_right(THD *thd, Item *a, Item *b): Item_func_bit(thd, a, b) {}
- longlong val_int();
+ Item_func_shift_right(THD *thd, Item *a, Item *b)
+ :Item_func_bit_operator(thd, a, b) {}
+ bool fix_length_and_dec();
const char *func_name() const { return ">>"; }
enum precedence precedence() const { return SHIFT_PRECEDENCE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_shift_right>(thd, this); }
};
-class Item_func_bit_neg :public Item_func_bit
+class Item_func_bit_neg :public Item_func_bit_operator
{
public:
- Item_func_bit_neg(THD *thd, Item *a): Item_func_bit(thd, a) {}
- longlong val_int();
+ Item_func_bit_neg(THD *thd, Item *a): Item_func_bit_operator(thd, a) {}
+ bool fix_length_and_dec();
const char *func_name() const { return "~"; }
enum precedence precedence() const { return NEG_PRECEDENCE; }
void print(String *str, enum_query_type query_type)
@@ -3156,11 +3252,12 @@ private:
};
-class Item_func_bit_xor : public Item_func_bit
+class Item_func_bit_xor : public Item_func_bit_operator
{
public:
- Item_func_bit_xor(THD *thd, Item *a, Item *b): Item_func_bit(thd, a, b) {}
- longlong val_int();
+ Item_func_bit_xor(THD *thd, Item *a, Item *b)
+ :Item_func_bit_operator(thd, a, b) {}
+ bool fix_length_and_dec();
const char *func_name() const { return "^"; }
enum precedence precedence() const { return BITXOR_PRECEDENCE; }
Item *get_copy(THD *thd)
diff --git a/sql/my_decimal.h b/sql/my_decimal.h
index a7f6fc9e88d..2db08bf01e3 100644
--- a/sql/my_decimal.h
+++ b/sql/my_decimal.h
@@ -195,6 +195,16 @@ public:
return res;
}
longlong to_longlong(bool unsigned_flag) const;
+ /*
+ Return the value as a signed or unsigned longlong, depending on the sign.
+ - Positive values are returned as unsigned.
+ - Negative values are returned as signed.
+ This is used by bit SQL operators: | & ^ ~
+ as well as by the SQL function BIT_COUNT().
+ */
+ longlong to_xlonglong() const
+ { return to_longlong(!sign()); }
+
// Convert to string returning decimal2string() error code
int to_string_native(String *to, uint prec, uint dec, char filler,
uint mask= E_DEC_FATAL_ERROR) const;
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 2f1063a20f6..0850d08c5ae 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -338,6 +338,10 @@ public:
double to_double() const { return m_ptr ? m_ptr->to_double() : 0.0; }
longlong to_longlong(bool unsigned_flag)
{ return m_ptr ? m_ptr->to_longlong(unsigned_flag) : 0; }
+ Longlong_null to_xlonglong_null()
+ {
+ return m_ptr ? Longlong_null(m_ptr->to_xlonglong()) : Longlong_null();
+ }
bool to_bool() const { return m_ptr ? m_ptr->to_bool() : false; }
String *to_string(String *to) const
{
diff --git a/sql/sql_type_int.h b/sql/sql_type_int.h
index d3e9d0318cf..9fd4f0c46a0 100644
--- a/sql/sql_type_int.h
+++ b/sql/sql_type_int.h
@@ -16,6 +16,8 @@
#ifndef SQL_TYPE_INT_INCLUDED
#define SQL_TYPE_INT_INCLUDED
+#include "my_bit.h" // my_count_bits()
+
class Null_flag
{
@@ -43,6 +45,58 @@ public:
Longlong_null(longlong nr, bool is_null)
:Longlong(nr), Null_flag(is_null)
{ }
+ explicit Longlong_null()
+ :Longlong(0), Null_flag(true)
+ { }
+ explicit Longlong_null(longlong nr)
+ :Longlong(nr), Null_flag(false)
+ { }
+ Longlong_null operator|(const Longlong_null &other) const
+ {
+ if (is_null() || other.is_null())
+ return Longlong_null();
+ return Longlong_null(value() | other.value());
+ }
+ Longlong_null operator&(const Longlong_null &other) const
+ {
+ if (is_null() || other.is_null())
+ return Longlong_null();
+ return Longlong_null(value() & other.value());
+ }
+ Longlong_null operator^(const Longlong_null &other) const
+ {
+ if (is_null() || other.is_null())
+ return Longlong_null();
+ return Longlong_null((longlong) (value() ^ other.value()));
+ }
+ Longlong_null operator~() const
+ {
+ if (is_null())
+ return *this;
+ return Longlong_null((longlong) ~ (ulonglong) value());
+ }
+ Longlong_null operator<<(const Longlong_null &llshift) const
+ {
+ if (is_null() || llshift.is_null())
+ return Longlong_null();
+ uint shift= (uint) llshift.value();
+ ulonglong res= ((ulonglong) value()) << shift;
+ return Longlong_null(shift < sizeof(longlong) * 8 ? (longlong) res : 0);
+ }
+ Longlong_null operator>>(const Longlong_null &llshift) const
+ {
+ if (is_null() || llshift.is_null())
+ return Longlong_null();
+ uint shift= (uint) llshift.value();
+ ulonglong res= ((ulonglong) value()) >> shift;
+ return Longlong_null(shift < sizeof(longlong) * 8 ? (longlong) res : 0);
+ }
+ Longlong_null bit_count() const
+ {
+ if (is_null())
+ return *this;
+ return Longlong_null((longlong) my_count_bits((ulonglong) value()));
+ }
};