mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03: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:
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user