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());
|
||||||
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
|
|||||||
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;
|
||||||
|
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)
|
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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