From 0f0d4720b840c2e3d2c42f9b071c87a048cb558a Mon Sep 17 00:00:00 2001 From: "igor@olga.mysql.com" <> Date: Thu, 14 Jun 2007 18:55:07 -0700 Subject: [PATCH 1/3] Fixed bug #27932: the function LOCATE returned NULL if any of its arguments was evaluated to NULL, while the predicate LOCATE(str,NULL) IS NULL erroneously was evaluated to FALSE. This happened because the Item_func_locate::fix_length_and_dec method by mistake set the value of the maybe_null flag for the function item to 0. In consequence of this the function was considered as the one that could not ever return NULL. --- mysql-test/r/func_str.result | 76 ++++++++++++++++++++++++++++++++++++ mysql-test/t/func_str.test | 33 ++++++++++++++++ sql/item_func.cc | 1 - 3 files changed, 109 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index d8afbe13c76..e79670b3f76 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -2061,4 +2061,80 @@ C 2707236321 DROP TABLE t1, t2; DROP VIEW v1; +SELECT LOCATE('foo', NULL) FROM DUAL; +LOCATE('foo', NULL) +NULL +SELECT LOCATE(NULL, 'o') FROM DUAL; +LOCATE(NULL, 'o') +NULL +SELECT LOCATE(NULL, NULL) FROM DUAL; +LOCATE(NULL, NULL) +NULL +SELECT LOCATE('foo', NULL) IS NULL FROM DUAL; +LOCATE('foo', NULL) IS NULL +1 +SELECT LOCATE(NULL, 'o') IS NULL FROM DUAL; +LOCATE(NULL, 'o') IS NULL +1 +SELECT LOCATE(NULL, NULL) IS NULL FROM DUAL; +LOCATE(NULL, NULL) IS NULL +1 +SELECT ISNULL(LOCATE('foo', NULL)) FROM DUAL; +ISNULL(LOCATE('foo', NULL)) +1 +SELECT ISNULL(LOCATE(NULL, 'o')) FROM DUAL; +ISNULL(LOCATE(NULL, 'o')) +1 +SELECT ISNULL(LOCATE(NULL, NULL)) FROM DUAL; +ISNULL(LOCATE(NULL, NULL)) +1 +SELECT LOCATE('foo', NULL) <=> NULL FROM DUAL; +LOCATE('foo', NULL) <=> NULL +1 +SELECT LOCATE(NULL, 'o') <=> NULL FROM DUAL; +LOCATE(NULL, 'o') <=> NULL +1 +SELECT LOCATE(NULL, NULL) <=> NULL FROM DUAL; +LOCATE(NULL, NULL) <=> NULL +1 +CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, a varchar(10), p varchar(10)); +INSERT INTO t1 VALUES (1, 'foo', 'o'); +INSERT INTO t1 VALUES (2, 'foo', NULL); +INSERT INTO t1 VALUES (3, NULL, 'o'); +INSERT INTO t1 VALUES (4, NULL, NULL); +SELECT id, LOCATE(a,p) FROM t1; +id LOCATE(a,p) +1 0 +2 NULL +3 NULL +4 NULL +SELECT id, LOCATE(a,p) IS NULL FROM t1; +id LOCATE(a,p) IS NULL +1 0 +2 1 +3 1 +4 1 +SELECT id, ISNULL(LOCATE(a,p)) FROM t1; +id ISNULL(LOCATE(a,p)) +1 0 +2 1 +3 1 +4 1 +SELECT id, LOCATE(a,p) <=> NULL FROM t1; +id LOCATE(a,p) <=> NULL +1 0 +2 1 +3 1 +4 1 +SELECT id FROM t1 WHERE LOCATE(a,p) IS NULL; +id +2 +3 +4 +SELECT id FROM t1 WHERE LOCATE(a,p) <=> NULL; +id +2 +3 +4 +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index bca977e6df3..c8fd06cd1cd 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -1076,4 +1076,37 @@ SELECT * FROM (SELECT * FROM v1) x; DROP TABLE t1, t2; DROP VIEW v1; +# +# Bug #27932: LOCATE with argument evaluated to NULL +# + +SELECT LOCATE('foo', NULL) FROM DUAL; +SELECT LOCATE(NULL, 'o') FROM DUAL; +SELECT LOCATE(NULL, NULL) FROM DUAL; +SELECT LOCATE('foo', NULL) IS NULL FROM DUAL; +SELECT LOCATE(NULL, 'o') IS NULL FROM DUAL; +SELECT LOCATE(NULL, NULL) IS NULL FROM DUAL; +SELECT ISNULL(LOCATE('foo', NULL)) FROM DUAL; +SELECT ISNULL(LOCATE(NULL, 'o')) FROM DUAL; +SELECT ISNULL(LOCATE(NULL, NULL)) FROM DUAL; +SELECT LOCATE('foo', NULL) <=> NULL FROM DUAL; +SELECT LOCATE(NULL, 'o') <=> NULL FROM DUAL; +SELECT LOCATE(NULL, NULL) <=> NULL FROM DUAL; + +CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, a varchar(10), p varchar(10)); + +INSERT INTO t1 VALUES (1, 'foo', 'o'); +INSERT INTO t1 VALUES (2, 'foo', NULL); +INSERT INTO t1 VALUES (3, NULL, 'o'); +INSERT INTO t1 VALUES (4, NULL, NULL); + +SELECT id, LOCATE(a,p) FROM t1; +SELECT id, LOCATE(a,p) IS NULL FROM t1; +SELECT id, ISNULL(LOCATE(a,p)) FROM t1; +SELECT id, LOCATE(a,p) <=> NULL FROM t1; +SELECT id FROM t1 WHERE LOCATE(a,p) IS NULL; +SELECT id FROM t1 WHERE LOCATE(a,p) <=> NULL; + +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index ab4a9c50332..17a2c584e9d 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2507,7 +2507,6 @@ longlong Item_func_coercibility::val_int() void Item_func_locate::fix_length_and_dec() { - maybe_null= 0; max_length= MY_INT32_NUM_DECIMAL_DIGITS; agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1); } From 8f09a374ea168ef09ba1bc0b5ddf87eeb89df120 Mon Sep 17 00:00:00 2001 From: "gshchepa/uchum@gleb.loc" <> Date: Sat, 16 Jun 2007 13:05:07 +0500 Subject: [PATCH 2/3] Fixed bug #28625: DECIMAL column was used instead of BIGINT for the minimal possible BIGINT (-9223372036854775808). The Item_func_neg::fix_length_and_dec has been adjusted to to inherit the type of the argument in the case when it's an Item_int object whose value is equal to LONGLONG_MIN. --- mysql-test/r/bigint.result | 26 ++++++++++++++++++++++++++ mysql-test/t/bigint.test | 13 +++++++++++++ sql/item_func.cc | 22 +++++++++++++--------- 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result index f18d1c9b583..064304b27aa 100644 --- a/mysql-test/r/bigint.result +++ b/mysql-test/r/bigint.result @@ -362,3 +362,29 @@ cast(-19999999999999999999 as signed) -9223372036854775808 Warnings: Error 1292 Truncated incorrect DECIMAL value: '' +select -9223372036854775808; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def -9223372036854775808 8 20 20 N 32897 0 63 +-9223372036854775808 +-9223372036854775808 +select -(9223372036854775808); +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def -(9223372036854775808) 8 20 20 N 32897 0 63 +-(9223372036854775808) +-9223372036854775808 +select -((9223372036854775808)); +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def -((9223372036854775808)) 8 20 20 N 32897 0 63 +-((9223372036854775808)) +-9223372036854775808 +select -(-(9223372036854775808)); +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def -(-(9223372036854775808)) 246 21 19 N 129 0 63 +-(-(9223372036854775808)) +9223372036854775808 +select --9223372036854775808, ---9223372036854775808, ----9223372036854775808; +--9223372036854775808 ---9223372036854775808 ----9223372036854775808 +9223372036854775808 -9223372036854775808 9223372036854775808 +select -(-9223372036854775808), -(-(-9223372036854775808)); +-(-9223372036854775808) -(-(-9223372036854775808)) +9223372036854775808 -9223372036854775808 diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test index 9a5fb11229d..1f0f7763e87 100644 --- a/mysql-test/t/bigint.test +++ b/mysql-test/t/bigint.test @@ -294,3 +294,16 @@ drop table t1; select cast(19999999999999999999 as signed); select cast(-19999999999999999999 as signed); + +# +# Bug #28625: -9223372036854775808 doesn't fit in BIGINT. +# + +--enable_metadata +select -9223372036854775808; +select -(9223372036854775808); +select -((9223372036854775808)); +select -(-(9223372036854775808)); +--disable_metadata +select --9223372036854775808, ---9223372036854775808, ----9223372036854775808; +select -(-9223372036854775808), -(-(-9223372036854775808)); diff --git a/sql/item_func.cc b/sql/item_func.cc index 95ff432ca5a..487e91e4917 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1523,16 +1523,20 @@ void Item_func_neg::fix_length_and_dec() Use val() to get value as arg_type doesn't mean that item is Item_int or Item_real due to existence of Item_param. */ - if (hybrid_type == INT_RESULT && - args[0]->type() == INT_ITEM && - ((ulonglong) args[0]->val_int() >= (ulonglong) LONGLONG_MIN)) + if (hybrid_type == INT_RESULT && args[0]->const_item()) { - /* - Ensure that result is converted to DECIMAL, as longlong can't hold - the negated number - */ - hybrid_type= DECIMAL_RESULT; - DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT")); + longlong val= args[0]->val_int(); + if ((ulonglong) val >= (ulonglong) LONGLONG_MIN && + ((ulonglong) val != (ulonglong) LONGLONG_MIN || + args[0]->type() != INT_ITEM)) + { + /* + Ensure that result is converted to DECIMAL, as longlong can't hold + the negated number + */ + hybrid_type= DECIMAL_RESULT; + DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT")); + } } unsigned_flag= 0; DBUG_VOID_RETURN; From dac7ce2d12e39a456b21c4252ef9518ab790c57f Mon Sep 17 00:00:00 2001 From: "gshchepa/uchum@gleb.loc" <> Date: Sat, 16 Jun 2007 17:00:29 +0500 Subject: [PATCH 3/3] bigint.test: Updated test case for bug #28625. --- mysql-test/t/bigint.test | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test index 1f0f7763e87..4aef7395184 100644 --- a/mysql-test/t/bigint.test +++ b/mysql-test/t/bigint.test @@ -299,11 +299,14 @@ select cast(-19999999999999999999 as signed); # Bug #28625: -9223372036854775808 doesn't fit in BIGINT. # +# PS protocol gives different metadata for `Max length' column +--disable_ps_protocol --enable_metadata select -9223372036854775808; select -(9223372036854775808); select -((9223372036854775808)); select -(-(9223372036854775808)); --disable_metadata +--endble_ps_protocol select --9223372036854775808, ---9223372036854775808, ----9223372036854775808; select -(-9223372036854775808), -(-(-9223372036854775808));