Skip to content
Permalink
Browse files

MDEV-19771 REPLACE on table with virtual_field can cause crash

Fixes also MDEV-17837

Problem was that we did not ignore warnings from virtual fields when
updated virtual fields for to-be-replaced row.
  • Loading branch information...
montywi committed Jun 15, 2019
1 parent 21eed90 commit c02d6164fbdd5effe758a61d9bb709c581fefef1
Showing with 79 additions and 4 deletions.
  1. +38 −0 mysql-test/suite/vcol/r/vcol_misc.result
  2. +38 −4 mysql-test/suite/vcol/t/vcol_misc.test
  3. +3 −0 sql/sql_insert.cc
@@ -423,5 +423,43 @@ ERROR HY000: Incorrect information in file: './test/t1.frm'
ALTER TABLE t1;
ERROR HY000: Incorrect information in file: './test/t1.frm'
#
# MDEV-19771 REPLACE on table with virtual_field can cause crash in set_ok_status()

create or replace table t1 (pk int primary key, col_bit bit(15) default null,
vcol_bit bit(10) GENERATED ALWAYS AS (`col_bit`) VIRTUAL);
replace INTO `t1` (`pk`,col_bit) VALUES (99,1000);
select pk, col_bit+0, vcol_bit+0 from t1;
pk col_bit+0 vcol_bit+0
99 1000 1000
replace INTO `t1` (`pk`,col_bit) VALUES (99,10000);
select pk, col_bit+0, vcol_bit+0 from t1;
pk col_bit+0 vcol_bit+0
99 10000 1023
REPLACE LOW_PRIORITY INTO `t1` (`pk`) VALUES (99);
Warnings:
Warning 1264 Out of range value for column 'vcol_bit' at row 1
drop table t1;
#
# MDEV-17837 REPLACE on table with virtual_field can cause crash in set_ok_status()
#
SET @old_sql_mode=@@sql_mode;
SET sql_mode= STRICT_ALL_TABLES;
CREATE TABLE t1 (
pk INT,
i TINYINT,
vi TINYINT AS (i+1) PERSISTENT,
PRIMARY KEY(pk)
);
INSERT INTO t1 (pk,i) VALUES (1,1);
TRUNCATE TABLE t1;
INSERT IGNORE INTO t1 (pk,i) VALUES (1,127);
Warnings:
Warning 1264 Out of range value for column 'vi' at row 1
REPLACE INTO t1 (pk,i) VALUES (1,2);
Warnings:
Warning 1264 Out of range value for column 'vi' at row 1
DROP TABLE t1;
SET @sql_mode=@old_sql_mode;
#
# End of 10.2 tests
#
@@ -215,12 +215,12 @@ drop table t1;
create table t1 (a int, b int);
insert into t1 values (3, 30), (4, 20), (1, 20);
create table t2 (c int, d int, v int as (d+1), index idx(c));
insert into t2(c,d) values
insert into t2(c,d) values
(20, 100), (20, 300), (30, 100), (30, 200), (40, 500),
(70, 100), (40, 300), (60, 100), (40, 100), (70, 100);
insert into t2(c,d) values
(70, 100), (40, 300), (60, 100), (40, 100), (70, 100);
insert into t2(c,d) values
(120, 100), (150, 300), (130, 100), (130, 200), (140, 500),
(170, 100), (180, 300), (160, 100), (40, 100), (170, 100);
(170, 100), (180, 300), (160, 100), (40, 100), (170, 100);

set join_cache_level=6;
explain
@@ -391,6 +391,40 @@ SHOW CREATE TABLE t1;
ALTER TABLE t1;
--remove_file $MYSQLD_DATADIR/test/t1.frm

--echo #
--echo # MDEV-19771 REPLACE on table with virtual_field can cause crash in set_ok_status()
--echo

create or replace table t1 (pk int primary key, col_bit bit(15) default null,
vcol_bit bit(10) GENERATED ALWAYS AS (`col_bit`) VIRTUAL);
replace INTO `t1` (`pk`,col_bit) VALUES (99,1000);
select pk, col_bit+0, vcol_bit+0 from t1;
replace INTO `t1` (`pk`,col_bit) VALUES (99,10000);
select pk, col_bit+0, vcol_bit+0 from t1;
REPLACE LOW_PRIORITY INTO `t1` (`pk`) VALUES (99);
drop table t1;

--echo #
--echo # MDEV-17837 REPLACE on table with virtual_field can cause crash in set_ok_status()
--echo #

SET @old_sql_mode=@@sql_mode;
SET sql_mode= STRICT_ALL_TABLES;

CREATE TABLE t1 (
pk INT,
i TINYINT,
vi TINYINT AS (i+1) PERSISTENT,
PRIMARY KEY(pk)
);

INSERT INTO t1 (pk,i) VALUES (1,1);
TRUNCATE TABLE t1;
INSERT IGNORE INTO t1 (pk,i) VALUES (1,127);
REPLACE INTO t1 (pk,i) VALUES (1,2);
DROP TABLE t1;
SET @sql_mode=@old_sql_mode;

--echo #
--echo # End of 10.2 tests
--echo #
@@ -1747,12 +1747,15 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
}
if (table->vfield)
{
my_bool abort_on_warning= thd->abort_on_warning;
/*
We have not yet called update_virtual_fields(VOL_UPDATE_FOR_READ)
in handler methods for the just read row in record[1].
*/
table->move_fields(table->field, table->record[1], table->record[0]);
thd->abort_on_warning= 0;
table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE);
thd->abort_on_warning= abort_on_warning;
table->move_fields(table->field, table->record[0], table->record[1]);
}
if (info->handle_duplicates == DUP_UPDATE)

0 comments on commit c02d616

Please sign in to comment.
You can’t perform that action at this time.