diff options
author | unknown <gshchepa/uchum@gshchepa.loc> | 2007-04-20 15:31:33 +0500 |
---|---|---|
committer | unknown <gshchepa/uchum@gshchepa.loc> | 2007-04-20 15:31:33 +0500 |
commit | a501fdd695a43905d89d7eb9157d3757d75f79bc (patch) | |
tree | bdf1e76b1cbfea7cafc8a0d548a68d660c6b51e2 | |
parent | 5b0ec8709ad4946260e257916a31d213b6168d26 (diff) | |
parent | a8f639fccc19ef80d67c52e698bf6366fdcf6f94 (diff) | |
download | mariadb-git-a501fdd695a43905d89d7eb9157d3757d75f79bc.tar.gz |
Merge gshchepa.loc:/home/uchum/work/bk-trees/mysql-4.1-opt-27704
into gshchepa.loc:/home/uchum/work/bk-trees/mysql-5.0-opt-27704
mysql-test/r/subselect.result:
Auto merged
mysql-test/t/row.test:
Auto merged
mysql-test/r/row.result:
Test case updated for Bug#27704 (incorrect comparison
of rows with NULL components).
sql/item_cmpfunc.cc:
Bug#27704: incorrect comparison of rows with NULL components.
sql/item_cmpfunc.h:
Bug#27704: incorrect comparison of rows with NULL components.
Cosmetic fix.
-rw-r--r-- | mysql-test/r/row.result | 97 | ||||
-rw-r--r-- | mysql-test/t/row.test | 45 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 18 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 2 |
4 files changed, 157 insertions, 5 deletions
diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result index bb9e2109f0f..702e66fea62 100644 --- a/mysql-test/r/row.result +++ b/mysql-test/r/row.result @@ -193,6 +193,103 @@ SELECT ROW(2,1) IN (ROW(21,2),ROW(ROW(1,1,3),0)); ERROR 21000: Operand should contain 1 column(s) SELECT ROW(2,1) IN (ROW(ROW(1,1,3),0),ROW(21,2)); ERROR 21000: Operand should contain 1 column(s) +CREATE TABLE t1(a int, b int, c int); +INSERT INTO t1 VALUES (1, 2, 3), +(NULL, 2, 3 ), (1, NULL, 3 ), (1, 2, NULL), +(NULL, 2, 3+1), (1, NULL, 3+1), (1, 2+1, NULL), +(NULL, 2, 3-1), (1, NULL, 3-1), (1, 2-1, NULL); +SELECT (1,2,3) = (1, NULL, 3); +(1,2,3) = (1, NULL, 3) +NULL +SELECT (1,2,3) = (1+1, NULL, 3); +(1,2,3) = (1+1, NULL, 3) +0 +SELECT (1,2,3) = (1, NULL, 3+1); +(1,2,3) = (1, NULL, 3+1) +0 +SELECT * FROM t1 WHERE (a,b,c) = (1,2,3); +a b c +1 2 3 +SELECT (1,2,3) <> (1, NULL, 3); +(1,2,3) <> (1, NULL, 3) +NULL +SELECT (1,2,3) <> (1+1, NULL, 3); +(1,2,3) <> (1+1, NULL, 3) +1 +SELECT (1,2,3) <> (1, NULL, 3+1); +(1,2,3) <> (1, NULL, 3+1) +1 +SELECT * FROM t1 WHERE (a,b,c) <> (1,2,3); +a b c +NULL 2 4 +1 NULL 4 +1 3 NULL +NULL 2 2 +1 NULL 2 +1 1 NULL +SELECT (1,2,3) < (NULL, 2, 3); +(1,2,3) < (NULL, 2, 3) +NULL +SELECT (1,2,3) < (1, NULL, 3); +(1,2,3) < (1, NULL, 3) +NULL +SELECT (1,2,3) < (1-1, NULL, 3); +(1,2,3) < (1-1, NULL, 3) +0 +SELECT (1,2,3) < (1+1, NULL, 3); +(1,2,3) < (1+1, NULL, 3) +1 +SELECT * FROM t1 WHERE (a,b,c) < (1,2,3); +a b c +1 1 NULL +SELECT (1,2,3) <= (NULL, 2, 3); +(1,2,3) <= (NULL, 2, 3) +NULL +SELECT (1,2,3) <= (1, NULL, 3); +(1,2,3) <= (1, NULL, 3) +NULL +SELECT (1,2,3) <= (1-1, NULL, 3); +(1,2,3) <= (1-1, NULL, 3) +0 +SELECT (1,2,3) <= (1+1, NULL, 3); +(1,2,3) <= (1+1, NULL, 3) +1 +SELECT * FROM t1 WHERE (a,b,c) <= (1,2,3); +a b c +1 2 3 +1 1 NULL +SELECT (1,2,3) > (NULL, 2, 3); +(1,2,3) > (NULL, 2, 3) +NULL +SELECT (1,2,3) > (1, NULL, 3); +(1,2,3) > (1, NULL, 3) +NULL +SELECT (1,2,3) > (1-1, NULL, 3); +(1,2,3) > (1-1, NULL, 3) +1 +SELECT (1,2,3) > (1+1, NULL, 3); +(1,2,3) > (1+1, NULL, 3) +0 +SELECT * FROM t1 WHERE (a,b,c) > (1,2,3); +a b c +1 3 NULL +SELECT (1,2,3) >= (NULL, 2, 3); +(1,2,3) >= (NULL, 2, 3) +NULL +SELECT (1,2,3) >= (1, NULL, 3); +(1,2,3) >= (1, NULL, 3) +NULL +SELECT (1,2,3) >= (1-1, NULL, 3); +(1,2,3) >= (1-1, NULL, 3) +1 +SELECT (1,2,3) >= (1+1, NULL, 3); +(1,2,3) >= (1+1, NULL, 3) +0 +SELECT * FROM t1 WHERE (a,b,c) >= (1,2,3); +a b c +1 2 3 +1 3 NULL +DROP TABLE t1; SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ; 1 0 0 0 null 1 0 0 0 NULL diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test index bf25359b7be..d2750fecbac 100644 --- a/mysql-test/t/row.test +++ b/mysql-test/t/row.test @@ -110,6 +110,51 @@ SELECT ROW(2,1) IN (ROW(21,2),ROW(ROW(1,1,3),0)); --error 1241 SELECT ROW(2,1) IN (ROW(ROW(1,1,3),0),ROW(21,2)); +# +# Bug#27704: erroneous comparison of rows with NULL components +# +CREATE TABLE t1(a int, b int, c int); +INSERT INTO t1 VALUES (1, 2, 3), + (NULL, 2, 3 ), (1, NULL, 3 ), (1, 2, NULL), + (NULL, 2, 3+1), (1, NULL, 3+1), (1, 2+1, NULL), + (NULL, 2, 3-1), (1, NULL, 3-1), (1, 2-1, NULL); + +SELECT (1,2,3) = (1, NULL, 3); +SELECT (1,2,3) = (1+1, NULL, 3); +SELECT (1,2,3) = (1, NULL, 3+1); +SELECT * FROM t1 WHERE (a,b,c) = (1,2,3); + +SELECT (1,2,3) <> (1, NULL, 3); +SELECT (1,2,3) <> (1+1, NULL, 3); +SELECT (1,2,3) <> (1, NULL, 3+1); +SELECT * FROM t1 WHERE (a,b,c) <> (1,2,3); + +SELECT (1,2,3) < (NULL, 2, 3); +SELECT (1,2,3) < (1, NULL, 3); +SELECT (1,2,3) < (1-1, NULL, 3); +SELECT (1,2,3) < (1+1, NULL, 3); +SELECT * FROM t1 WHERE (a,b,c) < (1,2,3); + +SELECT (1,2,3) <= (NULL, 2, 3); +SELECT (1,2,3) <= (1, NULL, 3); +SELECT (1,2,3) <= (1-1, NULL, 3); +SELECT (1,2,3) <= (1+1, NULL, 3); +SELECT * FROM t1 WHERE (a,b,c) <= (1,2,3); + +SELECT (1,2,3) > (NULL, 2, 3); +SELECT (1,2,3) > (1, NULL, 3); +SELECT (1,2,3) > (1-1, NULL, 3); +SELECT (1,2,3) > (1+1, NULL, 3); +SELECT * FROM t1 WHERE (a,b,c) > (1,2,3); + +SELECT (1,2,3) >= (NULL, 2, 3); +SELECT (1,2,3) >= (1, NULL, 3); +SELECT (1,2,3) >= (1-1, NULL, 3); +SELECT (1,2,3) >= (1+1, NULL, 3); +SELECT * FROM t1 WHERE (a,b,c) >= (1,2,3); + +DROP TABLE t1; + # End of 4.1 tests # diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f9844f6d36e..a2a68151b7a 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -811,8 +811,18 @@ int Arg_comparator::compare_row() if (owner->null_value) { // NULL was compared - if (owner->abort_on_null) - return -1; // We do not need correct NULL returning + switch (owner->functype()) { + case Item_func::NE_FUNC: + break; // NE never aborts on NULL even if abort_on_null is set + case Item_func::LT_FUNC: + case Item_func::LE_FUNC: + case Item_func::GT_FUNC: + case Item_func::GE_FUNC: + return -1; // <, <=, > and >= always fail on NULL + default: // EQ_FUNC + if (owner->abort_on_null) + return -1; // We do not need correct NULL returning + } was_null= 1; owner->null_value= 0; res= 0; // continue comparison (maybe we will meet explicit difference) @@ -823,8 +833,8 @@ int Arg_comparator::compare_row() if (was_null) { /* - There was NULL(s) in comparison in some parts, but there was not - explicit difference in other parts, so we have to return NULL + There was NULL(s) in comparison in some parts, but there was no + explicit difference in other parts, so we have to return NULL. */ owner->null_value= 1; return -1; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 0c4a62aaa24..11b8d34ad65 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -333,7 +333,7 @@ public: bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; } uint decimal_precision() const { return 1; } - void top_level_item() { abort_on_null=1; } + void top_level_item() { abort_on_null= TRUE; } friend class Arg_comparator; }; |