diff options
author | Monty <monty@mariadb.org> | 2017-01-10 18:28:24 +0200 |
---|---|---|
committer | Monty <monty@mariadb.org> | 2017-01-11 09:19:45 +0200 |
commit | 5f0c31f928338e8a6ffde098b7ffd3d1a8b02903 (patch) | |
tree | ac246928fcfa0b9fe0c63a5511a3c74fef167f3c | |
parent | 177c191ff4b9c0033665a292fdb5907095ddb823 (diff) | |
download | mariadb-git-5f0c31f928338e8a6ffde098b7ffd3d1a8b02903.tar.gz |
MDEV-11597 Assertion when doing select from virtual column with impossible value
- Changed error handlers interface so that they can change error level in
the handler
- Give warnings and errors when calculating virtual columns
- On insert/update error is fatal in strict mode.
- SELECT and DELETE will only give a warning if a virtual field generates an error
- Added VCOL_UPDATE_FOR_DELETE and VCOL_UPDATE_INDEX_FOR_REPLACE to be able to
easily detect in update_virtual_fields() if we should use an error
handler to mask errors or not.
-rw-r--r-- | mysql-test/suite/vcol/inc/vcol_ins_upd.inc | 65 | ||||
-rw-r--r-- | mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result | 220 | ||||
-rw-r--r-- | mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result | 237 | ||||
-rw-r--r-- | sql/handler.cc | 4 | ||||
-rw-r--r-- | sql/item_func.cc | 4 | ||||
-rw-r--r-- | sql/log.cc | 4 | ||||
-rw-r--r-- | sql/sp.cc | 13 | ||||
-rw-r--r-- | sql/sql_acl.cc | 6 | ||||
-rw-r--r-- | sql/sql_base.cc | 16 | ||||
-rw-r--r-- | sql/sql_base.h | 2 | ||||
-rw-r--r-- | sql/sql_class.cc | 22 | ||||
-rw-r--r-- | sql/sql_class.h | 11 | ||||
-rw-r--r-- | sql/sql_delete.cc | 5 | ||||
-rw-r--r-- | sql/sql_insert.cc | 11 | ||||
-rw-r--r-- | sql/sql_show.cc | 6 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 2 | ||||
-rw-r--r-- | sql/sql_update.cc | 3 | ||||
-rw-r--r-- | sql/table.cc | 49 | ||||
-rw-r--r-- | sql/table.h | 2 | ||||
-rw-r--r-- | storage/federated/ha_federated.cc | 2 | ||||
-rw-r--r-- | storage/federatedx/ha_federatedx.cc | 2 |
21 files changed, 628 insertions, 58 deletions
diff --git a/mysql-test/suite/vcol/inc/vcol_ins_upd.inc b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc index d9a1e062870..a7a43aae529 100644 --- a/mysql-test/suite/vcol/inc/vcol_ins_upd.inc +++ b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc @@ -314,3 +314,68 @@ select * from t1; drop table t1,t2; +--echo # +--echo # Test error handling with virtual columns +--echo # + +CREATE TABLE IF NOT EXISTS t1 ( + f1 DOUBLE, + f2 DOUBLE NOT NULL DEFAULT '0', + f3 DOUBLE, + f4 DOUBLE NOT NULL DEFAULT '0', + v1 DOUBLE AS ( ( f1 DIV ( f1 ) ) <= f2 ) VIRTUAL, + v2 DOUBLE AS ( ( f2 DIV ( f2 ) ) <= f2 ) VIRTUAL, + KEY (v2) +); + +set sql_mode='strict_all_tables,error_for_division_by_zero'; +--error ER_DIVISION_BY_ZERO +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 0, 0, 0); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 1, 1, 1); +--error ER_DIVISION_BY_ZERO +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +INSERT IGNORE INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 1, 1, 1); +select v1 from t1; + +--error ER_DIVISION_BY_ZERO +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0,0,0,0), (2,2,2,2); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (3,3,3,3), (4,4,4,4); +--error ER_DIVISION_BY_ZERO +INSERT INTO t1 (f1, f2, f3, f4) VALUES (5,5,5,5), (1,0,0,0); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (6,6,0,0); + +--error ER_DIVISION_BY_ZERO +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT f3, f4, f3, f4 FROM t1; +select count(*) from t1; +DELETE FROM t1 WHERE v2 != f1 and f1 < 5; +select count(*) from t1; +select * from t1; +--error ER_BAD_NULL_ERROR +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1; +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1 where f2 !=0; +UPDATE t1 SET f3 = v1 WHERE f2 = 2 AND v2 is null; +SELECT * FROM t1; +TRUNCATE TABLE t1; + +set sql_mode='error_for_division_by_zero'; +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 0, 0, 0); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 1, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 1, 1, 1); +select v1 from t1; + +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0,0,0,0), (2,2,2,2); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (3,3,3,3), (4,4,4,4); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (5,5,5,5), (1,0,0,0); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (6,6,0,0); + +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT f3, f4, f3, f4 FROM t1; +select count(*) from t1; +DELETE FROM t1 WHERE v2 != f1 and f1 < 5; +select count(*) from t1; +select * from t1; +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1; +UPDATE t1 SET f3 = v1 WHERE f2 = 2 AND v2 is null; +drop table t1; +set sql_mode=@@global.sql_mode; diff --git a/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result b/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result index d6793e22668..e3853156b4d 100644 --- a/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result +++ b/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result @@ -451,3 +451,223 @@ id name name_hash 2050 name1 9b46b0dd3a8083c070c3b9953bb5f3f95c5ab4da 2051 name2+1 fd4f236320db3956a5ec073c5ec39707d7f05708 drop table t1,t2; +# +# Test error handling with virtual columns +# +CREATE TABLE IF NOT EXISTS t1 ( +f1 DOUBLE, +f2 DOUBLE NOT NULL DEFAULT '0', +f3 DOUBLE, +f4 DOUBLE NOT NULL DEFAULT '0', +v1 DOUBLE AS ( ( f1 DIV ( f1 ) ) <= f2 ) VIRTUAL, +v2 DOUBLE AS ( ( f2 DIV ( f2 ) ) <= f2 ) VIRTUAL, +KEY (v2) +); +set sql_mode='strict_all_tables,error_for_division_by_zero'; +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 0, 0, 0); +ERROR 22012: Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 1, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +ERROR 22012: Division by 0 +INSERT IGNORE INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 1, 1, 1); +select v1 from t1; +v1 +1 +0 +NULL +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0,0,0,0), (2,2,2,2); +ERROR 22012: Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (3,3,3,3), (4,4,4,4); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (5,5,5,5), (1,0,0,0); +ERROR 22012: Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (6,6,0,0); +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT f3, f4, f3, f4 FROM t1; +ERROR 22012: Division by 0 +select count(*) from t1; +count(*) +6 +DELETE FROM t1 WHERE v2 != f1 and f1 < 5; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +select count(*) from t1; +count(*) +3 +select * from t1; +f1 f2 f3 f4 v1 v2 +1 1 1 1 1 1 +1 0 1 1 0 NULL +6 6 0 0 1 1 +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1; +ERROR 23000: Column 'f2' cannot be null +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1 where f2 !=0; +Warnings: +Warning 1365 Division by 0 +UPDATE t1 SET f3 = v1 WHERE f2 = 2 AND v2 is null; +Warnings: +Warning 1365 Division by 0 +SELECT * FROM t1; +f1 f2 f3 f4 v1 v2 +1 1 1 1 1 1 +1 0 1 1 0 NULL +6 6 0 0 1 1 +1 1 10 10 1 1 +1 1 10 10 1 1 +Warnings: +Warning 1365 Division by 0 +TRUNCATE TABLE t1; +set sql_mode='error_for_division_by_zero'; +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 0, 0, 0); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 1, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 1, 1, 1); +select v1 from t1; +v1 +NULL +1 +0 +NULL +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0,0,0,0), (2,2,2,2); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (3,3,3,3), (4,4,4,4); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (5,5,5,5), (1,0,0,0); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (6,6,0,0); +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT f3, f4, f3, f4 FROM t1; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +select count(*) from t1; +count(*) +22 +DELETE FROM t1 WHERE v2 != f1 and f1 < 5; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +select count(*) from t1; +count(*) +15 +select * from t1; +f1 f2 f3 f4 v1 v2 +0 0 0 0 NULL NULL +1 1 1 1 1 1 +1 0 1 1 0 NULL +0 0 0 0 NULL NULL +5 5 5 5 1 1 +1 0 0 0 0 NULL +6 6 0 0 1 1 +0 0 0 0 NULL NULL +1 1 1 1 1 1 +1 1 1 1 1 1 +1 1 1 1 1 1 +0 0 0 0 NULL NULL +5 5 5 5 1 1 +0 0 0 0 NULL NULL +0 0 0 0 NULL NULL +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +UPDATE t1 SET f3 = v1 WHERE f2 = 2 AND v2 is null; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +drop table t1; +set sql_mode=@@global.sql_mode; diff --git a/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result b/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result index 97f6b9be563..dcf957becae 100644 --- a/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result @@ -389,3 +389,240 @@ id name name_hash 2051 name2+1 fd4f236320db3956a5ec073c5ec39707d7f05708 2041 name3+1 93c9096df48221428de46e146abc9f4f94bf7d2e drop table t1,t2; +# +# Test error handling with virtual columns +# +CREATE TABLE IF NOT EXISTS t1 ( +f1 DOUBLE, +f2 DOUBLE NOT NULL DEFAULT '0', +f3 DOUBLE, +f4 DOUBLE NOT NULL DEFAULT '0', +v1 DOUBLE AS ( ( f1 DIV ( f1 ) ) <= f2 ) VIRTUAL, +v2 DOUBLE AS ( ( f2 DIV ( f2 ) ) <= f2 ) VIRTUAL, +KEY (v2) +); +set sql_mode='strict_all_tables,error_for_division_by_zero'; +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 0, 0, 0); +ERROR 22012: Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 1, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +ERROR 22012: Division by 0 +INSERT IGNORE INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 1, 1, 1); +select v1 from t1; +v1 +1 +0 +NULL +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0,0,0,0), (2,2,2,2); +ERROR 22012: Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (3,3,3,3), (4,4,4,4); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (5,5,5,5), (1,0,0,0); +ERROR 22012: Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (6,6,0,0); +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT f3, f4, f3, f4 FROM t1; +ERROR 22012: Division by 0 +select count(*) from t1; +count(*) +13 +DELETE FROM t1 WHERE v2 != f1 and f1 < 5; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +select count(*) from t1; +count(*) +8 +select * from t1; +f1 f2 f3 f4 v1 v2 +1 1 1 1 1 1 +1 0 1 1 0 NULL +5 5 5 5 1 1 +6 6 0 0 1 1 +1 1 1 1 1 1 +1 1 1 1 1 1 +1 1 1 1 1 1 +5 5 5 5 1 1 +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1; +ERROR 23000: Column 'f2' cannot be null +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1 where f2 !=0; +Warnings: +Warning 1365 Division by 0 +UPDATE t1 SET f3 = v1 WHERE f2 = 2 AND v2 is null; +Warnings: +Warning 1365 Division by 0 +SELECT * FROM t1; +f1 f2 f3 f4 v1 v2 +1 1 1 1 1 1 +1 0 1 1 0 NULL +1 1 10 10 1 1 +1 1 10 10 1 1 +1 1 10 10 1 1 +5 5 5 5 1 1 +6 6 0 0 1 1 +1 1 1 1 1 1 +1 1 1 1 1 1 +1 1 1 1 1 1 +1 1 10 10 1 1 +1 1 10 10 1 1 +5 5 5 5 1 1 +1 1 10 10 1 1 +1 1 10 10 1 1 +1 1 10 10 1 1 +1 1 10 10 1 1 +Warnings: +Warning 1365 Division by 0 +TRUNCATE TABLE t1; +set sql_mode='error_for_division_by_zero'; +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 0, 0, 0); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 1, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 1, 1, 1); +select v1 from t1; +v1 +NULL +1 +0 +NULL +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0,0,0,0), (2,2,2,2); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (3,3,3,3), (4,4,4,4); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (5,5,5,5), (1,0,0,0); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (6,6,0,0); +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT f3, f4, f3, f4 FROM t1; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +select count(*) from t1; +count(*) +22 +DELETE FROM t1 WHERE v2 != f1 and f1 < 5; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +select count(*) from t1; +count(*) +15 +select * from t1; +f1 f2 f3 f4 v1 v2 +0 0 0 0 NULL NULL +1 1 1 1 1 1 +1 0 1 1 0 NULL +0 0 0 0 NULL NULL +5 5 5 5 1 1 +1 0 0 0 0 NULL +6 6 0 0 1 1 +0 0 0 0 NULL NULL +1 1 1 1 1 1 +1 1 1 1 1 1 +1 1 1 1 1 1 +0 0 0 0 NULL NULL +5 5 5 5 1 1 +0 0 0 0 NULL NULL +0 0 0 0 NULL NULL +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +UPDATE t1 SET f3 = v1 WHERE f2 = 2 AND v2 is null; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +drop table t1; +set sql_mode=@@global.sql_mode; diff --git a/sql/handler.cc b/sql/handler.cc index a91a97598d6..f06c5d71a5e 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4974,7 +4974,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { @@ -4987,7 +4987,7 @@ public: return TRUE; } - if (level == Sql_condition::WARN_LEVEL_ERROR) + if (*level == Sql_condition::WARN_LEVEL_ERROR) m_unhandled_errors++; return FALSE; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 754ba9d261c..f6162b54806 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4127,7 +4127,7 @@ public: bool handle_condition(THD * /* thd */, uint sql_errno, const char * /* sqlstate */, - Sql_condition::enum_warning_level /* level */, + Sql_condition::enum_warning_level* /* level */, const char *message, Sql_condition ** /* cond_hdl */); }; @@ -4136,7 +4136,7 @@ bool Lock_wait_timeout_handler:: handle_condition(THD *thd, uint sql_errno, const char * /* sqlstate */, - Sql_condition::enum_warning_level /* level */, + Sql_condition::enum_warning_level* /* level */, const char *message, Sql_condition ** /* cond_hdl */) { diff --git a/sql/log.cc b/sql/log.cc index 57984bd03f4..23326532388 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -195,7 +195,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sql_state, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); const char *message() const { return m_message; } @@ -205,7 +205,7 @@ bool Silence_log_table_errors::handle_condition(THD *, uint, const char*, - Sql_condition::enum_warning_level, + Sql_condition::enum_warning_level*, const char* msg, Sql_condition ** cond_hdl) { diff --git a/sql/sp.cc b/sql/sp.cc index 05f075390c1..a1662cefb9e 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -691,7 +691,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); }; @@ -701,13 +701,13 @@ Silence_deprecated_warning::handle_condition( THD *, uint sql_errno, const char*, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char*, Sql_condition ** cond_hdl) { *cond_hdl= NULL; if (sql_errno == ER_WARN_DEPRECATED_SYNTAX && - level == Sql_condition::WARN_LEVEL_WARN) + *level == Sql_condition::WARN_LEVEL_WARN) return TRUE; return FALSE; @@ -780,7 +780,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* message, Sql_condition ** cond_hdl); @@ -794,7 +794,8 @@ bool Bad_db_error_handler::handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level + *level, const char* message, Sql_condition ** cond_hdl) { @@ -1477,7 +1478,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index d2840a81e7e..4a3c9ae75e7 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -10155,7 +10155,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); @@ -10170,12 +10170,12 @@ Silence_routine_definer_errors::handle_condition( THD *thd, uint sql_errno, const char*, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { *cond_hdl= NULL; - if (level == Sql_condition::WARN_LEVEL_ERROR) + if (*level == Sql_condition::WARN_LEVEL_ERROR) { switch (sql_errno) { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 46d7d07dbdf..ac4b8a45107 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -68,7 +68,7 @@ bool No_such_table_error_handler::handle_condition(THD *, uint sql_errno, const char*, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char*, Sql_condition ** cond_hdl) { @@ -79,7 +79,7 @@ No_such_table_error_handler::handle_condition(THD *, return TRUE; } - if (level == Sql_condition::WARN_LEVEL_ERROR) + if (*level == Sql_condition::WARN_LEVEL_ERROR) m_unhandled_errors++; return FALSE; } @@ -112,7 +112,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); @@ -142,7 +142,7 @@ bool Repair_mrg_table_error_handler::handle_condition(THD *, uint sql_errno, const char*, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char*, Sql_condition ** cond_hdl) { @@ -1254,7 +1254,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); @@ -1273,7 +1273,7 @@ private: bool MDL_deadlock_handler::handle_condition(THD *, uint sql_errno, const char*, - Sql_condition::enum_warning_level, + Sql_condition::enum_warning_level*, const char*, Sql_condition ** cond_hdl) { @@ -2834,7 +2834,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { @@ -7900,7 +7900,6 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values, table_arg->update_default_fields(0, ignore_errors)) goto err; /* Update virtual fields */ - thd->abort_on_warning= FALSE; if (table_arg->vfield && table_arg->update_virtual_fields(VCOL_UPDATE_FOR_WRITE)) goto err; @@ -7908,6 +7907,7 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values, thd->no_errors= save_no_errors; DBUG_RETURN(thd->is_error()); err: + DBUG_PRINT("error",("got error")); thd->abort_on_warning= save_abort_on_warning; thd->no_errors= save_no_errors; if (fields.elements) diff --git a/sql/sql_base.h b/sql/sql_base.h index 8f363a73863..374ac56c3d8 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -624,7 +624,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 1837f2878c7..5c7cfdce657 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -640,7 +640,7 @@ char *thd_security_context(THD *thd, bool Drop_table_error_handler::handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { @@ -660,7 +660,7 @@ MDL_deadlock_and_lock_abort_error_handler:: handle_condition(THD *thd, uint sql_errno, const char *sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition **cond_hdl) { @@ -945,7 +945,7 @@ void THD::push_internal_handler(Internal_error_handler *handler) bool THD::handle_condition(uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { @@ -1072,6 +1072,7 @@ Sql_condition* THD::raise_condition(uint sql_errno, Diagnostics_area *da= get_stmt_da(); Sql_condition *cond= NULL; DBUG_ENTER("THD::raise_condition"); + DBUG_ASSERT(level < Sql_condition::WARN_LEVEL_END); if (!(variables.option_bits & OPTION_SQL_NOTES) && (level == Sql_condition::WARN_LEVEL_NOTE)) @@ -1099,24 +1100,23 @@ Sql_condition* THD::raise_condition(uint sql_errno, push_warning and strict SQL_MODE case. */ level= Sql_condition::WARN_LEVEL_ERROR; - killed= KILL_BAD_DATA; } - switch (level) - { + if (handle_condition(sql_errno, sqlstate, &level, msg, &cond)) + DBUG_RETURN(cond); + + switch (level) { case Sql_condition::WARN_LEVEL_NOTE: case Sql_condition::WARN_LEVEL_WARN: got_warning= 1; break; case Sql_condition::WARN_LEVEL_ERROR: break; - default: - DBUG_ASSERT(FALSE); + case Sql_condition::WARN_LEVEL_END: + /* Impossible */ + break; } - if (handle_condition(sql_errno, sqlstate, level, msg, &cond)) - DBUG_RETURN(cond); - if (level == Sql_condition::WARN_LEVEL_ERROR) { mysql_audit_general(this, MYSQL_AUDIT_GENERAL_ERROR, sql_errno, msg); diff --git a/sql/sql_class.h b/sql/sql_class.h index a55e1739318..3a7454e0a89 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1558,6 +1558,7 @@ show_system_thread(enum_thread_type thread) Internal error handlers are exception handlers used by the server implementation. */ + class Internal_error_handler { protected: @@ -1595,7 +1596,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) = 0; @@ -1616,7 +1617,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { @@ -1643,7 +1644,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); @@ -1664,7 +1665,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char *sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition **cond_hdl); @@ -3818,7 +3819,7 @@ private: */ bool handle_condition(uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index e9a3be30060..2f4c2d9a6f8 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -560,10 +560,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ! thd->is_error()) { explain->tracker.on_record_read(); - if (table->vfield) - table->update_virtual_fields(VCOL_UPDATE_FOR_WRITE); thd->inc_examined_row_count(1); - // thd->is_error() is tested to disallow delete row on error + if (table->vfield) + (void) table->update_virtual_fields(VCOL_UPDATE_FOR_DELETE); if (!select || select->skip_record(thd) > 0) { explain->tracker.on_record_after_where(); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index cea42667c48..b9c1dcebee9 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3174,6 +3174,7 @@ bool Delayed_insert::handle_inserts(void) while ((row=rows.get())) { + int tmp_error; stacked_inserts--; mysql_mutex_unlock(&mutex); memcpy(table->record[0],row->record,table->s->reclength); @@ -3250,16 +3251,18 @@ bool Delayed_insert::handle_inserts(void) table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE); thd.clear_error(); // reset error for binlog + tmp_error= 0; if (table->vfield) { /* - Virtual fields where not calculated by caller as the temporary TABLE object used - had vcol_set empty. Better to calculate them here to make the caller faster. + Virtual fields where not calculated by caller as the temporary + TABLE object used had vcol_set empty. Better to calculate them + here to make the caller faster. */ - table->update_virtual_fields(VCOL_UPDATE_FOR_WRITE); + tmp_error= table->update_virtual_fields(VCOL_UPDATE_FOR_WRITE); } - if (write_record(&thd, table, &info)) + if (tmp_error || write_record(&thd, table, &info)) { info.error_count++; // Ignore errors thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 0a2dab91c14..58fc2edc6f2 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1069,7 +1069,7 @@ public: } bool handle_condition(THD *thd, uint sql_errno, const char * /* sqlstate */, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char *message, Sql_condition ** /* cond_hdl */) { /* @@ -4675,7 +4675,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { @@ -4684,7 +4684,7 @@ public: sql_errno == ER_TRG_NO_CREATION_CTX) return true; - if (level != Sql_condition::WARN_LEVEL_ERROR) + if (*level != Sql_condition::WARN_LEVEL_ERROR) return false; if (!thd->get_stmt_da()->is_error()) diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 2d1619018b2..bd02289b135 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -308,7 +308,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* message, Sql_condition ** cond_hdl) { diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 476d1a4e104..c46b80f798b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2403,7 +2403,8 @@ int multi_update::do_updates() field_num++; } while ((tbl= check_opt_it++)); - if (table->vfield && table->update_virtual_fields(VCOL_UPDATE_INDEXED)) + if (table->vfield && + table->update_virtual_fields(VCOL_UPDATE_INDEXED_FOR_UPDATE)) goto err2; table->status|= STATUS_UPDATED; diff --git a/sql/table.cc b/sql/table.cc index 41f764d1e59..4242b870d55 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4932,7 +4932,7 @@ bool TABLE_LIST::prep_check_option(THD *thd, uint8 check_opt_type) void TABLE_LIST::hide_view_error(THD *thd) { - if (thd->killed || thd->get_internal_handler()) + if ((thd->killed && !thd->is_error())|| thd->get_internal_handler()) return; /* Hide "Unknown column" or "Unknown function" error */ DBUG_ASSERT(thd->is_error()); @@ -7308,6 +7308,24 @@ bool is_simple_order(ORDER *order) return TRUE; } +class Turn_errors_to_warnings_handler : public Internal_error_handler +{ +public: + Turn_errors_to_warnings_handler() {} + bool handle_condition(THD *thd, + uint sql_errno, + const char* sqlstate, + Sql_condition::enum_warning_level *level, + const char* msg, + Sql_condition ** cond_hdl) + { + *cond_hdl= NULL; + if (*level == Sql_condition::WARN_LEVEL_ERROR) + *level= Sql_condition::WARN_LEVEL_WARN; + return(0); + } +}; + /* @brief Compute values for virtual columns used in query @@ -7328,9 +7346,22 @@ int TABLE::update_virtual_fields(enum_vcol_update_mode update_mode) DBUG_ENTER("TABLE::update_virtual_fields"); DBUG_PRINT("enter", ("update_mode: %d", update_mode)); Field **vfield_ptr, *vf; + Turn_errors_to_warnings_handler Suppress_errors; + int error; + bool handler_pushed= 0; DBUG_ASSERT(vfield); + error= 0; in_use->reset_arena_for_cached_items(expr_arena); + + /* When reading or deleting row, ignore errors from virtual columns */ + if (update_mode == VCOL_UPDATE_FOR_READ || + update_mode == VCOL_UPDATE_FOR_DELETE || + update_mode == VCOL_UPDATE_INDEXED) + { + in_use->push_internal_handler(&Suppress_errors); + handler_pushed= 1; + } /* Iterate over virtual fields in the table */ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++) { @@ -7347,6 +7378,8 @@ int TABLE::update_virtual_fields(enum_vcol_update_mode update_mode) && bitmap_is_set(vcol_set, vf->field_index); swap_values= 1; break; + case VCOL_UPDATE_FOR_DELETE: + /* Fall trough */ case VCOL_UPDATE_FOR_WRITE: update= bitmap_is_set(vcol_set, vf->field_index); break; @@ -7367,6 +7400,7 @@ int TABLE::update_virtual_fields(enum_vcol_update_mode update_mode) } break; case VCOL_UPDATE_INDEXED: + case VCOL_UPDATE_INDEXED_FOR_UPDATE: /* Read indexed fields that was not updated in VCOL_UPDATE_FOR_READ */ update= (!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) && bitmap_is_set(vcol_set, vf->field_index) && @@ -7377,9 +7411,12 @@ int TABLE::update_virtual_fields(enum_vcol_update_mode update_mode) if (update) { + int field_error __attribute__((unused)) = 0; /* Compute the actual value of the virtual fields */ - vcol_info->expr->save_in_field(vf, 0); - DBUG_PRINT("info", ("field '%s' - updated", vf->field_name)); + if (vcol_info->expr->save_in_field(vf, 0)) + field_error= error= 1; + DBUG_PRINT("info", ("field '%s' - updated error: %d", + vf->field_name, field_error)); if (swap_values && (vf->flags & BLOB_FLAG)) { /* @@ -7396,8 +7433,12 @@ int TABLE::update_virtual_fields(enum_vcol_update_mode update_mode) DBUG_PRINT("info", ("field '%s' - skipped", vf->field_name)); } } + if (handler_pushed) + in_use->pop_internal_handler(); in_use->reset_arena_for_cached_items(0); - DBUG_RETURN(0); + + /* Return 1 only of we got a fatal error, not a warning */ + DBUG_RETURN(in_use->is_error()); } int TABLE::update_virtual_field(Field *vf) diff --git a/sql/table.h b/sql/table.h index facba06a3cc..3b8086dd09f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -328,7 +328,9 @@ enum enum_vcol_update_mode { VCOL_UPDATE_FOR_READ= 0, VCOL_UPDATE_FOR_WRITE, + VCOL_UPDATE_FOR_DELETE, VCOL_UPDATE_INDEXED, + VCOL_UPDATE_INDEXED_FOR_UPDATE, VCOL_UPDATE_FOR_REPLACE }; diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 038415cc188..879a17782aa 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -1653,7 +1653,7 @@ public: public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { return sql_errno >= ER_ABORTING_CONNECTION && diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index a4da84ddaf3..e3506e1a4df 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -1786,7 +1786,7 @@ public: public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { return sql_errno >= ER_ABORTING_CONNECTION && |