From 3b38a0223d32fdf5e1eb4f9a0612439c85e638af Mon Sep 17 00:00:00 2001 From: Guilhem Bichot Date: Mon, 12 Mar 2018 14:36:07 +0100 Subject: [PATCH] Bug#27452082 ASSERTION FAILED: !TABLE->IN_USE->IS_ERROR() IN UPDATE_GENERATED_READ_FIELDS It's a SELECT with WHERE "(-1) minus 0x4d". this operation has a result type of "unsigned" (because 0x4d is unsigned integer) and the result (-78) doesn't fit int an unsigned type. This WHERE is evaluated by InnoDB in index condition pushdown: #0 my_error #1 Item_func::raise_numeric_overflow ... #7 Item_cond_and::val_int #8 innobase_index_cond ... #12 handler::index_read_map ... #15 handler::multi_range_read_next ... #20 rr_quick #21 join_init_read_record As val_int() has no "error" return code, the execution continues until frame #12; there we call update_generated_read_fields(), which has an assertion about thd->is_error() which fails. Fix: it would be nice to detect error as soon as it happens, i.e. in innodb code right after it calls val_bool(). But innodb's index condition pushdown functions only have found / not found return codes so they cannot signal "error" to the upper layers. Same is true for MyISAM. Moreover, "thd" isn't easily accessible there. Adding a detection a bit above in the stack (handler::* functions which do index reads) is also possible but would require fixing ~20 functions. The chosen fix here is to change update_generated_*_fields() to return error if thd->is_error() is true. Note that the removed assertion was already one cause of bug 27041382. --- mysql-test/suite/gcol/r/gcol_bugfixes.result | 12 ++++++++++++ mysql-test/suite/gcol/t/gcol_bugfixes.test | 14 ++++++++++++++ sql/table.cc | 5 +++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/gcol/r/gcol_bugfixes.result b/mysql-test/suite/gcol/r/gcol_bugfixes.result index 83857132e879..5fab37a57040 100644 --- a/mysql-test/suite/gcol/r/gcol_bugfixes.result +++ b/mysql-test/suite/gcol/r/gcol_bugfixes.result @@ -868,3 +868,15 @@ LOAD DATA INFILE '../../std_data/loaddata5.dat' INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (c1) ; ERROR 42000: Trigger 'trg1' has an error in its body: 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 't1 VALUES (1)' at line 1' DROP TABLE t1; +# +# Bug#27452082 ASSERTION FAILED: !TABLE->IN_USE->IS_ERROR() IN UPDATE_GENERATED_READ_FIELDS +# +CREATE TABLE t ( +a INT, +b INT GENERATED ALWAYS AS (MAKETIME(1,1,1)) STORED, +KEY (a) +); +INSERT INTO t (a) VALUES (32767),(-1); +SELECT * FROM t WHERE a>-19106 AND a-0x4d; +ERROR 22003: BIGINT UNSIGNED value is out of range in '(`test`.`t`.`a` - 0x4d)' +DROP TABLE t; diff --git a/mysql-test/suite/gcol/t/gcol_bugfixes.test b/mysql-test/suite/gcol/t/gcol_bugfixes.test index 2f27647632d8..267f00aed1a4 100644 --- a/mysql-test/suite/gcol/t/gcol_bugfixes.test +++ b/mysql-test/suite/gcol/t/gcol_bugfixes.test @@ -848,3 +848,17 @@ LOAD DATA INFILE '../../std_data/loaddata5.dat' INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (c1) ; DROP TABLE t1; + +--echo # +--echo # Bug#27452082 ASSERTION FAILED: !TABLE->IN_USE->IS_ERROR() IN UPDATE_GENERATED_READ_FIELDS +--echo # + +CREATE TABLE t ( + a INT, + b INT GENERATED ALWAYS AS (MAKETIME(1,1,1)) STORED, + KEY (a) +); +INSERT INTO t (a) VALUES (32767),(-1); +--error ER_DATA_OUT_OF_RANGE +SELECT * FROM t WHERE a>-19106 AND a-0x4d; +DROP TABLE t; diff --git a/sql/table.cc b/sql/table.cc index dbff157835d1..98bf7e4fc52d 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -6738,7 +6738,7 @@ void repoint_field_to_record(TABLE *table, uchar *old_rec, uchar *new_rec) { bool update_generated_read_fields(uchar *buf, TABLE *table, uint active_index) { DBUG_ENTER("update_generated_read_fields"); DBUG_ASSERT(table && table->vfield); - DBUG_ASSERT(!table->in_use->is_error()); + if (table->in_use->is_error()) DBUG_RETURN(true); if (active_index != MAX_KEY && table->key_read) { /* The covering index is providing all necessary columns, including @@ -6833,7 +6833,8 @@ bool update_generated_write_fields(const MY_BITMAP *bitmap, TABLE *table) { int error = 0; DBUG_ASSERT(table->vfield); - DBUG_ASSERT(!table->in_use->is_error()); + if (table->in_use->is_error()) DBUG_RETURN(true); + /* Iterate over generated fields in the table */ for (vfield_ptr = table->vfield; *vfield_ptr; vfield_ptr++) { Field *vfield;