| Bug #109449 | functional index could produce wrong result | ||
|---|---|---|---|
| Submitted: | 21 Dec 2022 9:48 | Modified: | 21 Dec 2022 12:15 |
| Reporter: | x j | Email Updates: | |
| Status: | Verified | Impact on me: | |
| Category: | MySQL Server: Optimizer | Severity: | S3 (Non-critical) |
| Version: | 8.0.26, 8.0.31 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
[21 Dec 2022 9:48]
x j
[21 Dec 2022 10:05]
x j
also for generate column with an index on it create table t(a int, b int unsigned as (a-10) virtual, index idx(b)); set @@sql_mode=''; mysql> insert into t(a) values (1); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> select * from t where a - 10 = 0; +------+------+ | a | b | +------+------+ | 1 | 0 | +------+------+ 1 row in set (0.00 sec)
[21 Dec 2022 12:15]
MySQL Verification Team
Hello x j, Thank you for the report and test case. regards, Umesh
[3 Jan 2023 8:04]
huahua xu
test case 1:
mysql> drop table t1;
Query OK, 0 rows affected (0.01 sec)
mysql> create table t1(a int, b int unsigned as (cast(a-10 as unsigned)) virtual, index idx(b));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t1 (a) values (1);
ERROR 1264 (22003): Out of range value for column 'b' at row 1
test case 2:
mysql> drop table t1;
Query OK, 0 rows affected (0.01 sec)
mysql> create table t1(a int, b bigint unsigned as (cast(a-10 as unsigned)) virtual, index idx(b));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t1 (a) values (1);
Query OK, 1 row affected (0.01 sec)
mysql> select * from t1;
+------+----------------------+
| a | b |
+------+----------------------+
| 1 | 18446744073709551607 |
+------+----------------------+
In the case 1, the type of column `b` is defined as Field_long, but it is Field_longlong in the case 2. Obviously, their internal processing logic is different, and I think that it is a bug about `Field_longlong::store`:
diff --git a/sql/field.cc b/sql/field.cc
index fb03f3ae1a1..b38f96c244e 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -3913,7 +3913,8 @@ type_conversion_status Field_longlong::store(longlong nr, bool unsigned_val) {
if field is unsigned and value is signed (< 0) or
if field is signed and value is unsigned we have an overflow
*/
- if (is_unsigned() != unsigned_val) {
+ if (is_unsigned()
+ || is_unsigned() != unsigned_val) {
nr = is_unsigned() ? (ulonglong)0 : (ulonglong)LLONG_MAX;
set_warning(Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, 1);
error = TYPE_WARN_OUT_OF_RANGE;
