Commit 4ab180ad authored by Monty's avatar Monty

MDEV-15461 Check Constraints with binary logging makes insert inconsistent

Problem was that verify_constraints() didn't check if
there was an error as part of evaluating constraints
(can happen in strict mode).

In one-row-insert the error was ignored when using
binary logging as binary logging clear errors if insert
succeeded. In multi-row-insert the error was noticed
for the second row.

After this fix one will get an error for both one and
multi-row inserts if the constraints generates a warning
in strict mode.
parent 0e296947
...@@ -156,3 +156,44 @@ create table t1 (id int auto_increment primary key, datecol datetime, check (dat ...@@ -156,3 +156,44 @@ create table t1 (id int auto_increment primary key, datecol datetime, check (dat
insert into t1 (datecol) values (now()); insert into t1 (datecol) values (now());
insert into t1 (datecol) values (now()); insert into t1 (datecol) values (now());
drop table t1; drop table t1;
CREATE TABLE t1 (
EmployeeID SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(30) NOT NULL CHECK (CHAR_LENGTH(FirstName > 2))
);
INSERT INTO t1 VALUES (NULL, 'Ken');
ERROR 22007: Truncated incorrect DOUBLE value: 'Ken'
SHOW WARNINGS;
Level Code Message
Error 1292 Truncated incorrect DOUBLE value: 'Ken'
Error 4025 CONSTRAINT `FirstName` failed for `test`.`t1`
INSERT INTO t1 VALUES (NULL, 'Ken'),(NULL, 'Brian');
ERROR 22007: Truncated incorrect DOUBLE value: 'Ken'
SHOW WARNINGS;
Level Code Message
Error 1292 Truncated incorrect DOUBLE value: 'Ken'
Error 4025 CONSTRAINT `FirstName` failed for `test`.`t1`
INSERT IGNORE INTO t1 VALUES (NULL, 'Ken');
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'Ken'
INSERT IGNORE INTO t1 VALUES (NULL, 'Ken'),(NULL, 'Brian');
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'Ken'
Warning 1292 Truncated incorrect DOUBLE value: 'Brian'
set sql_mode="";
INSERT INTO t1 VALUES (NULL, 'Ken');
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'Ken'
INSERT INTO t1 VALUES (NULL, 'Ken'),(NULL, 'Brian');
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'Ken'
Warning 1292 Truncated incorrect DOUBLE value: 'Brian'
set sql_mode=default;
select * from t1;
EmployeeID FirstName
1 Ken
2 Ken
3 Brian
4 Ken
5 Ken
6 Brian
drop table t1;
...@@ -111,3 +111,27 @@ create table t1 (id int auto_increment primary key, datecol datetime, check (dat ...@@ -111,3 +111,27 @@ create table t1 (id int auto_increment primary key, datecol datetime, check (dat
insert into t1 (datecol) values (now()); insert into t1 (datecol) values (now());
insert into t1 (datecol) values (now()); insert into t1 (datecol) values (now());
drop table t1; drop table t1;
#
# MDEV-15461 Check Constraints with binary logging makes insert inconsistent
#
CREATE TABLE t1 (
EmployeeID SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(30) NOT NULL CHECK (CHAR_LENGTH(FirstName > 2))
);
--error ER_TRUNCATED_WRONG_VALUE
INSERT INTO t1 VALUES (NULL, 'Ken');
SHOW WARNINGS;
--error ER_TRUNCATED_WRONG_VALUE
INSERT INTO t1 VALUES (NULL, 'Ken'),(NULL, 'Brian');
SHOW WARNINGS;
INSERT IGNORE INTO t1 VALUES (NULL, 'Ken');
INSERT IGNORE INTO t1 VALUES (NULL, 'Ken'),(NULL, 'Brian');
set sql_mode="";
INSERT INTO t1 VALUES (NULL, 'Ken');
INSERT INTO t1 VALUES (NULL, 'Ken'),(NULL, 'Brian');
set sql_mode=default;
select * from t1;
drop table t1;
...@@ -5116,14 +5116,25 @@ int TABLE_LIST::view_check_option(THD *thd, bool ignore_failure) ...@@ -5116,14 +5116,25 @@ int TABLE_LIST::view_check_option(THD *thd, bool ignore_failure)
int TABLE::verify_constraints(bool ignore_failure) int TABLE::verify_constraints(bool ignore_failure)
{ {
/*
We have to check is_error() first as we are checking it for each
constraint to catch fatal warnings.
*/
if (in_use->is_error())
return (VIEW_CHECK_ERROR);
/* go trough check option clauses for fields and table */ /* go trough check option clauses for fields and table */
if (check_constraints && if (check_constraints &&
!(in_use->variables.option_bits & OPTION_NO_CHECK_CONSTRAINT_CHECKS)) !(in_use->variables.option_bits & OPTION_NO_CHECK_CONSTRAINT_CHECKS))
{ {
for (Virtual_column_info **chk= check_constraints ; *chk ; chk++) for (Virtual_column_info **chk= check_constraints ; *chk ; chk++)
{ {
/* yes! NULL is ok, see 4.23.3.4 Table check constraints, part 2, SQL:2016 */ /*
if ((*chk)->expr->val_int() == 0 && !(*chk)->expr->null_value) yes! NULL is ok.
see 4.23.3.4 Table check constraints, part 2, SQL:2016
*/
if (((*chk)->expr->val_int() == 0 && !(*chk)->expr->null_value) ||
in_use->is_error())
{ {
my_error(ER_CONSTRAINT_FAILED, my_error(ER_CONSTRAINT_FAILED,
MYF(ignore_failure ? ME_JUST_WARNING : 0), (*chk)->name.str, MYF(ignore_failure ? ME_JUST_WARNING : 0), (*chk)->name.str,
...@@ -5132,7 +5143,11 @@ int TABLE::verify_constraints(bool ignore_failure) ...@@ -5132,7 +5143,11 @@ int TABLE::verify_constraints(bool ignore_failure)
} }
} }
} }
return(VIEW_CHECK_OK); /*
We have to check in_use() as checking constraints may have generated
warnings that should be treated as errors
*/
return(!in_use->is_error() ? VIEW_CHECK_OK : VIEW_CHECK_ERROR);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment