From 67449418edc219e266458e9156fb572d59245e3b Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 10 Jun 2021 23:20:33 +0400 Subject: [PATCH] MCOL-4700 Wrong result of a UNION for INT and INT UNSIGNED --- mysql-test/columnstore/basic/r/union.result | 144 ++++++++++++++++++++ mysql-test/columnstore/basic/t/union.test | 62 +++++++++ utils/dataconvert/dataconvert.cpp | 11 +- 3 files changed, 214 insertions(+), 3 deletions(-) create mode 100644 mysql-test/columnstore/basic/r/union.result create mode 100644 mysql-test/columnstore/basic/t/union.test diff --git a/mysql-test/columnstore/basic/r/union.result b/mysql-test/columnstore/basic/r/union.result new file mode 100644 index 000000000..894367865 --- /dev/null +++ b/mysql-test/columnstore/basic/r/union.result @@ -0,0 +1,144 @@ +SET default_storage_engine=ColumnStore; +DROP DATABASE IF EXISTS mcs_union; +CREATE DATABASE mcs_union; +USE mcs_union; +# +# MCOL-4700 Wrong result of a UNION for INT and INT UNSIGNED +# +CREATE TABLE t1 (a INT, b INT UNSIGNED); +INSERT INTO t1 VALUES (-1,1); +SELECT * FROM (SELECT a FROM t1 UNION SELECT b FROM t1) tu ORDER BY a; +a +-1 +1 +SELECT * FROM (SELECT b FROM t1 UNION SELECT a FROM t1) tu ORDER BY b; +b +-1 +1 +DROP TABLE t1; +CREATE TABLE t1 (a TINYINT); +INSERT INTO t1 VALUES (CAST(0xFFFFFFFFFFFFFF80 AS SIGNED)+2),(-1),(0),(1),(0x7F); +CREATE TABLE t2 (a TINYINT UNSIGNED); +INSERT INTO t2 VALUES (0),(1),(0xFF-2); +(SELECT a FROM t1 UNION ALL SELECT a FROM t2) ORDER BY a; +a +-126 +-1 +0 +0 +1 +1 +127 +253 +(SELECT a FROM t2 UNION ALL SELECT a FROM t1) ORDER BY a; +a +-126 +-1 +0 +0 +1 +1 +127 +253 +DROP TABLE t1,t2; +CREATE TABLE t1 (a SMALLINT); +INSERT INTO t1 VALUES (CAST(0xFFFFFFFFFFFF8000 AS SIGNED)+2),(-1),(0),(1),(0x7FFF); +CREATE TABLE t2 (a INT UNSIGNED); +INSERT INTO t2 VALUES (0),(1),(0xFFFF-2); +(SELECT a FROM t1 UNION ALL SELECT * FROM t2) ORDER BY a; +a +-32766 +-1 +0 +0 +1 +1 +32767 +65533 +(SELECT a FROM t2 UNION ALL SELECT a FROM t1) ORDER BY a; +a +-32766 +-1 +0 +0 +1 +1 +32767 +65533 +DROP TABLE t1,t2; +CREATE TABLE t1 (a MEDIUMINT); +INSERT INTO t1 VALUES (CAST(0xFFFFFFFFFF800000 AS SIGNED)+2),(-1),(0),(1),(0x7FFFFF); +CREATE TABLE t2 (a INT UNSIGNED); +INSERT INTO t2 VALUES (0),(1),(0xFFFFFF-2); +(SELECT a FROM t1 UNION ALL SELECT a FROM t2) ORDER BY a; +a +-8388606 +-1 +0 +0 +1 +1 +8388607 +16777213 +(SELECT a FROM t2 UNION ALL SELECT a FROM t1) ORDER BY a; +a +-8388606 +-1 +0 +0 +1 +1 +8388607 +16777213 +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (CAST(0xFFFFFFFF80000000 AS SIGNED)+2),(-1),(0),(1),(0x7FFFFFFF); +CREATE TABLE t2 (a INT UNSIGNED); +INSERT INTO t2 VALUES (0),(1),(0xFFFFFFFF-2); +(SELECT a FROM t1 UNION ALL SELECT a FROM t2) ORDER BY a; +a +-2147483646 +-1 +0 +0 +1 +1 +2147483647 +4294967293 +(SELECT a FROM t2 UNION ALL SELECT a FROM t1) ORDER BY a; +a +-2147483646 +-1 +0 +0 +1 +1 +2147483647 +4294967293 +DROP TABLE t1,t2; +CREATE TABLE t1 (a BIGINT); +INSERT INTO t1 VALUES (CAST(0x8000000000000000 AS SIGNED)+2),(-1),(0),(1),(0x7FFFFFFFFFFFFFFF); +CREATE TABLE t2 (a BIGINT UNSIGNED); +INSERT INTO t2 VALUES (0),(1),(0xFFFFFFFFFFFFFFFF-2); +(SELECT a FROM t1 UNION ALL SELECT a FROM t2) ORDER BY a; +a +-9223372036854775806 +-1 +0 +0 +1 +1 +9223372036854775807 +18446744073709551613 +(SELECT a FROM t2 UNION ALL SELECT a FROM t1) ORDER BY a; +a +-9223372036854775806 +-1 +0 +0 +1 +1 +9223372036854775807 +18446744073709551613 +DROP TABLE t1,t2; +DROP DATABASE mcs_union; diff --git a/mysql-test/columnstore/basic/t/union.test b/mysql-test/columnstore/basic/t/union.test new file mode 100644 index 000000000..abae3c497 --- /dev/null +++ b/mysql-test/columnstore/basic/t/union.test @@ -0,0 +1,62 @@ +--source ../include/have_columnstore.inc + +SET default_storage_engine=ColumnStore; + +--disable_warnings +DROP DATABASE IF EXISTS mcs_union; +--enable_warnings + +CREATE DATABASE mcs_union; +USE mcs_union; + +--echo # +--echo # MCOL-4700 Wrong result of a UNION for INT and INT UNSIGNED +--echo # + +CREATE TABLE t1 (a INT, b INT UNSIGNED); +INSERT INTO t1 VALUES (-1,1); +SELECT * FROM (SELECT a FROM t1 UNION SELECT b FROM t1) tu ORDER BY a; +SELECT * FROM (SELECT b FROM t1 UNION SELECT a FROM t1) tu ORDER BY b; +DROP TABLE t1; + +CREATE TABLE t1 (a TINYINT); +INSERT INTO t1 VALUES (CAST(0xFFFFFFFFFFFFFF80 AS SIGNED)+2),(-1),(0),(1),(0x7F); +CREATE TABLE t2 (a TINYINT UNSIGNED); +INSERT INTO t2 VALUES (0),(1),(0xFF-2); +(SELECT a FROM t1 UNION ALL SELECT a FROM t2) ORDER BY a; +(SELECT a FROM t2 UNION ALL SELECT a FROM t1) ORDER BY a; +DROP TABLE t1,t2; + +CREATE TABLE t1 (a SMALLINT); +INSERT INTO t1 VALUES (CAST(0xFFFFFFFFFFFF8000 AS SIGNED)+2),(-1),(0),(1),(0x7FFF); +CREATE TABLE t2 (a INT UNSIGNED); +INSERT INTO t2 VALUES (0),(1),(0xFFFF-2); +(SELECT a FROM t1 UNION ALL SELECT * FROM t2) ORDER BY a; +(SELECT a FROM t2 UNION ALL SELECT a FROM t1) ORDER BY a; +DROP TABLE t1,t2; + +CREATE TABLE t1 (a MEDIUMINT); +INSERT INTO t1 VALUES (CAST(0xFFFFFFFFFF800000 AS SIGNED)+2),(-1),(0),(1),(0x7FFFFF); +CREATE TABLE t2 (a INT UNSIGNED); +INSERT INTO t2 VALUES (0),(1),(0xFFFFFF-2); +(SELECT a FROM t1 UNION ALL SELECT a FROM t2) ORDER BY a; +(SELECT a FROM t2 UNION ALL SELECT a FROM t1) ORDER BY a; +DROP TABLE t1,t2; + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (CAST(0xFFFFFFFF80000000 AS SIGNED)+2),(-1),(0),(1),(0x7FFFFFFF); +CREATE TABLE t2 (a INT UNSIGNED); +INSERT INTO t2 VALUES (0),(1),(0xFFFFFFFF-2); +(SELECT a FROM t1 UNION ALL SELECT a FROM t2) ORDER BY a; +(SELECT a FROM t2 UNION ALL SELECT a FROM t1) ORDER BY a; +DROP TABLE t1,t2; + +CREATE TABLE t1 (a BIGINT); +INSERT INTO t1 VALUES (CAST(0x8000000000000000 AS SIGNED)+2),(-1),(0),(1),(0x7FFFFFFFFFFFFFFF); +CREATE TABLE t2 (a BIGINT UNSIGNED); +INSERT INTO t2 VALUES (0),(1),(0xFFFFFFFFFFFFFFFF-2); +(SELECT a FROM t1 UNION ALL SELECT a FROM t2) ORDER BY a; +(SELECT a FROM t2 UNION ALL SELECT a FROM t1) ORDER BY a; +DROP TABLE t1,t2; + +DROP DATABASE mcs_union; diff --git a/utils/dataconvert/dataconvert.cpp b/utils/dataconvert/dataconvert.cpp index 1d4c2f1d9..4cab5a5c9 100644 --- a/utils/dataconvert/dataconvert.cpp +++ b/utils/dataconvert/dataconvert.cpp @@ -3054,10 +3054,15 @@ DataConvert::joinColTypeForUnion(datatypes::SystemCatalog::TypeHolderStd &unione unionedType.colWidth = type.colWidth; } - // If same size and result is signed but source is unsigned... - if (type.colWidth == unionedType.colWidth && !isUnsigned(unionedType.colDataType) && isUnsigned(type.colDataType)) + // If same size but different signedness + if (type.colWidth == unionedType.colWidth && + ((!isUnsigned(unionedType.colDataType) && isUnsigned(type.colDataType)) || + (!isUnsigned(type.colDataType) && isUnsigned(unionedType.colDataType)))) { - unionedType.colDataType = type.colDataType; + unionedType.colDataType = datatypes::SystemCatalog::DECIMAL; + unionedType.colWidth = datatypes::Decimal::isWideDecimalTypeByPrecision(unionedType.precision) ? + datatypes::MAXDECIMALWIDTH : + datatypes::MAXLEGACYWIDTH; } if (type.colDataType == datatypes::SystemCatalog::DECIMAL || type.colDataType == datatypes::SystemCatalog::UDECIMAL)