mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
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.
This commit is contained in:
parent
0e296947db
commit
4ab180ad5e
3 changed files with 83 additions and 3 deletions
|
@ -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());
|
||||
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
|
|||
insert into t1 (datecol) values (now());
|
||||
insert into t1 (datecol) values (now());
|
||||
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;
|
||||
|
|
21
sql/table.cc
21
sql/table.cc
|
@ -5116,14 +5116,25 @@ int TABLE_LIST::view_check_option(THD *thd, 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 */
|
||||
if (check_constraints &&
|
||||
!(in_use->variables.option_bits & OPTION_NO_CHECK_CONSTRAINT_CHECKS))
|
||||
{
|
||||
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,
|
||||
MYF(ignore_failure ? ME_JUST_WARNING : 0), (*chk)->name.str,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue