Skip to content

Commit

Permalink
MDEV-21034 GREATEST() and LEAST() malfunction for NULL
Browse files Browse the repository at this point in the history
There is a convention that Item::val_int() and Item::val_real() return
SQL NULL doing effectively what this code does:
  null_value= true;
  return 0; // Always return 0 for SQL NULL

This is done to optimize boolean value evaluation:
if Item::val_int() or Item::val_real() returned 1 -
that always means TRUE and never can means SQL NULL.
This convention helps to avoid unnecessary testing
Item::null_value after getting a non-zero return value.

Item_func_min_max did not follow this convention.
It could return a non-zero value together with null_value==true.
This made evaluate_join_record() erroneously misinterpret
SQL NULL as TRUE in this call:

  select_cond_result= MY_TEST(select_cond->val_int());

Fixing Item_func_min_max to follow the convention.
  • Loading branch information
abarkov committed Apr 22, 2024
1 parent 361b790 commit 24abbb9
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 2 deletions.
25 changes: 25 additions & 0 deletions mysql-test/main/func_hybrid_type.result
Original file line number Diff line number Diff line change
Expand Up @@ -4313,5 +4313,30 @@ ERROR HY000: Illegal parameter data types bigint unsigned and row for operation
SELECT @@max_allowed_packet=ROW(1,1);
ERROR HY000: Illegal parameter data types bigint unsigned and row for operation '='
#
# MDEV-21034 GREATEST() and LEAST() malfunction for NULL
#
SELECT 5 AS c1 FROM dual WHERE GREATEST(1, NULL);
c1
SELECT 5 AS c1 FROM dual WHERE LEAST(1, NULL);
c1
CREATE TABLE t0 (c0 INT);
INSERT INTO t0 VALUES (1);
SELECT * FROM t0 WHERE GREATEST(c0, NULL);
c0
SELECT * FROM t0 WHERE LEAST(c0, NULL);
c0
DROP TABLE t0;
SELECT 5 AS c1 FROM dual WHERE GREATEST(1e0, NULL);
c1
SELECT 5 AS c1 FROM dual WHERE LEAST(1e0, NULL);
c1
CREATE TABLE t0 (c0 DOUBLE);
INSERT INTO t0 VALUES (1);
SELECT * FROM t0 WHERE GREATEST(c0, NULL);
c0
SELECT * FROM t0 WHERE LEAST(c0, NULL);
c0
DROP TABLE t0;
#
# End of 10.5 tests
#
23 changes: 23 additions & 0 deletions mysql-test/main/func_hybrid_type.test
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,29 @@ SELECT 0x20+ROW(1,1);
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT @@max_allowed_packet=ROW(1,1);

--echo #
--echo # MDEV-21034 GREATEST() and LEAST() malfunction for NULL
--echo #

SELECT 5 AS c1 FROM dual WHERE GREATEST(1, NULL);
SELECT 5 AS c1 FROM dual WHERE LEAST(1, NULL);

CREATE TABLE t0 (c0 INT);
INSERT INTO t0 VALUES (1);
SELECT * FROM t0 WHERE GREATEST(c0, NULL);
SELECT * FROM t0 WHERE LEAST(c0, NULL);
DROP TABLE t0;

SELECT 5 AS c1 FROM dual WHERE GREATEST(1e0, NULL);
SELECT 5 AS c1 FROM dual WHERE LEAST(1e0, NULL);

CREATE TABLE t0 (c0 DOUBLE);
INSERT INTO t0 VALUES (1);
SELECT * FROM t0 WHERE GREATEST(c0, NULL);
SELECT * FROM t0 WHERE LEAST(c0, NULL);
DROP TABLE t0;


--echo #
--echo # End of 10.5 tests
--echo #
4 changes: 2 additions & 2 deletions sql/item_func.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3022,7 +3022,7 @@ double Item_func_min_max::val_real_native()
value=tmp;
}
if ((null_value= args[i]->null_value))
break;
return 0;
}
return value;
}
Expand All @@ -3043,7 +3043,7 @@ longlong Item_func_min_max::val_int_native()
value=tmp;
}
if ((null_value= args[i]->null_value))
break;
return 0;
}
return value;
}
Expand Down

0 comments on commit 24abbb9

Please sign in to comment.