mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
MDEV-15243 Crash with virtual fields and row based binary logging
The cause of this was several different bugs: - When using binary logging with binlog_row_image=FULL the all bits in read_set was set, which caused a different (wrong) pattern for marking vcol_set. - TABLE::mark_virtual_columns_for_write() didn't in all cases mark vcol_set with the vcol_field. - TABLE::update_virtual_fields() has to update all vcol fields on REPLACE if binary logging with FULL is used. - VCOL_UPDATE_INDEXED should update all vcol fields part of an index that was not updated by VCOL_UPDATE_FOR_READ - max_row_length() calculated length of NULL and not used fields. This didn't cause any crash, but used more memory than needed.
This commit is contained in:
parent
1c8c6bcd6f
commit
4cd2a0eb56
8 changed files with 569 additions and 49 deletions
70
mysql-test/suite/vcol/r/binlog.result
Normal file
70
mysql-test/suite/vcol/r/binlog.result
Normal file
|
@ -0,0 +1,70 @@
|
|||
include/master-slave.inc
|
||||
[connection master]
|
||||
CREATE TABLE t1 (
|
||||
pk SERIAL,
|
||||
vcol_date DATE AS (col_date) PERSISTENT,
|
||||
vcol_int INT AS (col_int) VIRTUAL,
|
||||
vcol_year YEAR AS (col_year) PERSISTENT,
|
||||
vcol_blob BLOB AS (col_blob) VIRTUAL,
|
||||
col_date DATE,
|
||||
col_int INT NULL,
|
||||
col_blob BLOB NULL,
|
||||
col_year YEAR,
|
||||
PRIMARY KEY(pk)
|
||||
) ENGINE=InnoDB;
|
||||
INSERT INTO t1 (col_date,col_int,col_blob,col_year) VALUES ('2010-04-24',5,'foo',1981);
|
||||
SET SQL_MODE='';
|
||||
set binlog_row_image="FULL";
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
REPLACE INTO v1 SELECT pk, vcol_date, vcol_int, vcol_year, vcol_blob, col_date, col_int, col_blob, 1982 FROM t1;
|
||||
Warnings:
|
||||
Warning 1906 The value specified for generated column 'vcol_date' in table 't1' ignored
|
||||
Warning 1906 The value specified for generated column 'vcol_int' in table 't1' ignored
|
||||
Warning 1906 The value specified for generated column 'vcol_year' in table 't1' ignored
|
||||
Warning 1906 The value specified for generated column 'vcol_blob' in table 't1' ignored
|
||||
select col_date,col_int,col_blob,col_year from v1;
|
||||
col_date col_int col_blob col_year
|
||||
2010-04-24 5 foo 1982
|
||||
connection slave;
|
||||
select col_date,col_int,col_blob,col_year from v1;
|
||||
col_date col_int col_blob col_year
|
||||
2010-04-24 5 foo 1982
|
||||
connection master;
|
||||
DROP VIEW v1;
|
||||
set binlog_row_image="MINIMAL";
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
REPLACE INTO v1 SELECT pk, vcol_date, vcol_int, vcol_year, vcol_blob, col_date, col_int, col_blob, 1983 FROM t1;
|
||||
Warnings:
|
||||
Warning 1906 The value specified for generated column 'vcol_date' in table 't1' ignored
|
||||
Warning 1906 The value specified for generated column 'vcol_int' in table 't1' ignored
|
||||
Warning 1906 The value specified for generated column 'vcol_year' in table 't1' ignored
|
||||
Warning 1906 The value specified for generated column 'vcol_blob' in table 't1' ignored
|
||||
select col_date,col_int,col_blob,col_year from v1;
|
||||
col_date col_int col_blob col_year
|
||||
2010-04-24 5 foo 1983
|
||||
connection slave;
|
||||
select col_date,col_int,col_blob,col_year from v1;
|
||||
col_date col_int col_blob col_year
|
||||
2010-04-24 5 foo 1983
|
||||
connection master;
|
||||
DROP VIEW v1;
|
||||
set @@binlog_row_image="NOBLOB";
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
REPLACE INTO v1 SELECT pk, vcol_date, vcol_int, vcol_year, vcol_blob, col_date, col_int, col_blob, 1984 FROM t1;
|
||||
Warnings:
|
||||
Warning 1906 The value specified for generated column 'vcol_date' in table 't1' ignored
|
||||
Warning 1906 The value specified for generated column 'vcol_int' in table 't1' ignored
|
||||
Warning 1906 The value specified for generated column 'vcol_year' in table 't1' ignored
|
||||
Warning 1906 The value specified for generated column 'vcol_blob' in table 't1' ignored
|
||||
select col_date,col_int,col_blob,col_year from v1;
|
||||
col_date col_int col_blob col_year
|
||||
2010-04-24 5 foo 1984
|
||||
connection slave;
|
||||
select col_date,col_int,col_blob,col_year from v1;
|
||||
col_date col_int col_blob col_year
|
||||
2010-04-24 5 foo 1984
|
||||
connection master;
|
||||
DROP VIEW v1;
|
||||
set @@binlog_row_image=default;
|
||||
DROP TABLE t1;
|
||||
include/rpl_end.inc
|
|
@ -9,8 +9,20 @@ a b c
|
|||
2 3 4
|
||||
drop table t1;
|
||||
create table t1 (a int, c int as(a), p varchar(20) as(y), y char(20), index (p,c));
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`c` int(11) GENERATED ALWAYS AS (`a`) VIRTUAL,
|
||||
`p` varchar(20) GENERATED ALWAYS AS (`y`) VIRTUAL,
|
||||
`y` char(20) DEFAULT NULL,
|
||||
KEY `p` (`p`,`c`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
insert into t1 (a,y) values(1, "yyy");
|
||||
update t1 set a = 100 where a = 1;
|
||||
check table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
drop table t1;
|
||||
create table t1 (
|
||||
a varchar(10000),
|
||||
|
|
361
mysql-test/suite/vcol/r/update_binlog.result
Normal file
361
mysql-test/suite/vcol/r/update_binlog.result
Normal file
|
@ -0,0 +1,361 @@
|
|||
set binlog_row_image="FULL";
|
||||
set @@default_storage_engine="myisam";
|
||||
create table t1 (a int, b int as (a+1), c int as (b+1) stored);
|
||||
insert t1 set a=1;
|
||||
select * from t1;
|
||||
a b c
|
||||
1 2 3
|
||||
update t1 set a=2;
|
||||
select * from t1;
|
||||
a b c
|
||||
2 3 4
|
||||
drop table t1;
|
||||
create table t1 (a int, c int as(a), p varchar(20) as(y), y char(20), index (p,c));
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`c` int(11) GENERATED ALWAYS AS (`a`) VIRTUAL,
|
||||
`p` varchar(20) GENERATED ALWAYS AS (`y`) VIRTUAL,
|
||||
`y` char(20) DEFAULT NULL,
|
||||
KEY `p` (`p`,`c`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
insert into t1 (a,y) values(1, "yyy");
|
||||
update t1 set a = 100 where a = 1;
|
||||
check table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
drop table t1;
|
||||
create table t1 (
|
||||
a varchar(10000),
|
||||
b varchar(3000),
|
||||
c varchar(14000) generated always as (concat(a,b)) virtual,
|
||||
d varchar(5000) generated always as (b) virtual,
|
||||
e int(11) generated always as (10) virtual,
|
||||
h int(11) not null primary key,
|
||||
index(c(100), d(20)));
|
||||
insert t1 (a,b,h) values (repeat('g', 10000), repeat('x', 2800), 1);
|
||||
update t1 set a = repeat(cast(1 as char), 2000);
|
||||
drop table t1;
|
||||
create table t1 (
|
||||
a varchar(10000),
|
||||
b varchar(3000),
|
||||
c varchar(14000) generated always as (concat(a,b)) virtual,
|
||||
i varchar(5000) generated always as (b) virtual,
|
||||
d varchar(5000) generated always as (i) virtual,
|
||||
e int(11) generated always as (10) virtual,
|
||||
h int(11) not null primary key,
|
||||
index(c(100), d(20)));
|
||||
insert t1 (a,b,h) values (repeat('g', 10000), repeat('x', 2800), 1);
|
||||
update t1 set a = repeat(cast(1 as char), 2000);
|
||||
drop table t1;
|
||||
create table t1(a blob not null, b int, c varbinary (10) generated always as (a) virtual, unique (c(9)));
|
||||
insert t1 (a,b) values ('a', 1);
|
||||
replace t1 set a = 'a',b =1;
|
||||
insert t1 (a,b) values ('a', 1) on duplicate key update a='b', b=2;
|
||||
select * from t1;
|
||||
a b c
|
||||
b 2 b
|
||||
drop table t1;
|
||||
create table t (a int primary key, b int, c int as (b), index (c));
|
||||
insert t (a,b) values (9,0);
|
||||
create table t2 select * from t;
|
||||
update t, t2 set t.b=10 where t.a=t2.a;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c
|
||||
9 10 10
|
||||
drop table t, t2;
|
||||
create table t1 (a int, b int, c int, d int, e int);
|
||||
insert t1 values (1,2,3,4,5), (1,2,3,4,5);
|
||||
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
|
||||
create table t (a int primary key,
|
||||
b int, c blob as (b), index (c(57)),
|
||||
d blob, e blob as (d), index (e(57)))
|
||||
replace select * from t1;
|
||||
Warnings:
|
||||
Warning 1906 The value specified for generated column 'c' in table 't' ignored
|
||||
Warning 1906 The value specified for generated column 'e' in table 't' ignored
|
||||
Warning 1906 The value specified for generated column 'c' in table 't' ignored
|
||||
Warning 1906 The value specified for generated column 'e' in table 't' ignored
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
1 2 2 4 4
|
||||
update t set a=10, b=1, d=1;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 1 1 1 1
|
||||
replace t (a,b,d) values (10,2,2);
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 2 2 2 2
|
||||
insert t(a,b,d) values (10) on duplicate key update b=3;
|
||||
ERROR 21S01: Column count doesn't match value count at row 1
|
||||
insert t(a,b,d) values (10,2,2) on duplicate key update b=3, d=3;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 3 3 3 3
|
||||
replace t (a,b,d) select 10,4,4;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 4 4 4 4
|
||||
insert t(a,b,d) select 10,4,4 on duplicate key update b=5, d=5;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 5 5 5 5
|
||||
replace delayed t (a,b,d) values (10,6,6);
|
||||
flush tables;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 6 6 6 6
|
||||
insert delayed t(a,b,d) values (10,6,6) on duplicate key update b=7, d=7;
|
||||
flush tables;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 7 7 7 7
|
||||
load data infile 'MYSQLTEST_VARDIR/tmp/vblobs.txt' replace into table t;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 8 8 8 8
|
||||
update t set a=11, b=9, d=9 where a>5;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
11 9 9 9 9
|
||||
create table t2 select * from t;
|
||||
update t, t2 set t.b=10, t.d=10 where t.a=t2.a;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
11 10 10 10 10
|
||||
update t, t tt set t.b=11, tt.d=11 where t.a=tt.a;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
11 11 11 11 11
|
||||
drop table t, t1, t2;
|
||||
create table t (f1 int, f2 int, f3 int as (f1*2) virtual, key(f3,f2));
|
||||
insert into t (f1,f2) values (1,1),(2,2);
|
||||
create view v as
|
||||
select a2.f1, a2.f2, a1.f3
|
||||
from t a1, t a2
|
||||
where a2.f3 <> 0
|
||||
with local check option;
|
||||
update v set f3 = 52;
|
||||
drop view v;
|
||||
drop table t;
|
||||
set binlog_row_image="MINIMAL";
|
||||
create table t1 (a int, b int as (a+1), c int as (b+1) stored);
|
||||
insert t1 set a=1;
|
||||
select * from t1;
|
||||
a b c
|
||||
1 2 3
|
||||
update t1 set a=2;
|
||||
select * from t1;
|
||||
a b c
|
||||
2 3 4
|
||||
drop table t1;
|
||||
create table t1 (a int, c int as(a), p varchar(20) as(y), y char(20), index (p,c));
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`c` int(11) GENERATED ALWAYS AS (`a`) VIRTUAL,
|
||||
`p` varchar(20) GENERATED ALWAYS AS (`y`) VIRTUAL,
|
||||
`y` char(20) DEFAULT NULL,
|
||||
KEY `p` (`p`,`c`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
insert into t1 (a,y) values(1, "yyy");
|
||||
update t1 set a = 100 where a = 1;
|
||||
check table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
drop table t1;
|
||||
create table t1 (
|
||||
a varchar(10000),
|
||||
b varchar(3000),
|
||||
c varchar(14000) generated always as (concat(a,b)) virtual,
|
||||
d varchar(5000) generated always as (b) virtual,
|
||||
e int(11) generated always as (10) virtual,
|
||||
h int(11) not null primary key,
|
||||
index(c(100), d(20)));
|
||||
insert t1 (a,b,h) values (repeat('g', 10000), repeat('x', 2800), 1);
|
||||
update t1 set a = repeat(cast(1 as char), 2000);
|
||||
drop table t1;
|
||||
create table t1 (
|
||||
a varchar(10000),
|
||||
b varchar(3000),
|
||||
c varchar(14000) generated always as (concat(a,b)) virtual,
|
||||
i varchar(5000) generated always as (b) virtual,
|
||||
d varchar(5000) generated always as (i) virtual,
|
||||
e int(11) generated always as (10) virtual,
|
||||
h int(11) not null primary key,
|
||||
index(c(100), d(20)));
|
||||
insert t1 (a,b,h) values (repeat('g', 10000), repeat('x', 2800), 1);
|
||||
update t1 set a = repeat(cast(1 as char), 2000);
|
||||
drop table t1;
|
||||
create table t1(a blob not null, b int, c varbinary (10) generated always as (a) virtual, unique (c(9)));
|
||||
insert t1 (a,b) values ('a', 1);
|
||||
replace t1 set a = 'a',b =1;
|
||||
insert t1 (a,b) values ('a', 1) on duplicate key update a='b', b=2;
|
||||
select * from t1;
|
||||
a b c
|
||||
b 2 b
|
||||
drop table t1;
|
||||
create table t (a int primary key, b int, c int as (b), index (c));
|
||||
insert t (a,b) values (9,0);
|
||||
create table t2 select * from t;
|
||||
update t, t2 set t.b=10 where t.a=t2.a;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c
|
||||
9 10 10
|
||||
drop table t, t2;
|
||||
create table t1 (a int, b int, c int, d int, e int);
|
||||
insert t1 values (1,2,3,4,5), (1,2,3,4,5);
|
||||
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
|
||||
create table t (a int primary key,
|
||||
b int, c blob as (b), index (c(57)),
|
||||
d blob, e blob as (d), index (e(57)))
|
||||
replace select * from t1;
|
||||
Warnings:
|
||||
Warning 1906 The value specified for generated column 'c' in table 't' ignored
|
||||
Warning 1906 The value specified for generated column 'e' in table 't' ignored
|
||||
Warning 1906 The value specified for generated column 'c' in table 't' ignored
|
||||
Warning 1906 The value specified for generated column 'e' in table 't' ignored
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
1 2 2 4 4
|
||||
update t set a=10, b=1, d=1;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 1 1 1 1
|
||||
replace t (a,b,d) values (10,2,2);
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 2 2 2 2
|
||||
insert t(a,b,d) values (10) on duplicate key update b=3;
|
||||
ERROR 21S01: Column count doesn't match value count at row 1
|
||||
insert t(a,b,d) values (10,2,2) on duplicate key update b=3, d=3;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 3 3 3 3
|
||||
replace t (a,b,d) select 10,4,4;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 4 4 4 4
|
||||
insert t(a,b,d) select 10,4,4 on duplicate key update b=5, d=5;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 5 5 5 5
|
||||
replace delayed t (a,b,d) values (10,6,6);
|
||||
flush tables;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 6 6 6 6
|
||||
insert delayed t(a,b,d) values (10,6,6) on duplicate key update b=7, d=7;
|
||||
flush tables;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 7 7 7 7
|
||||
load data infile 'MYSQLTEST_VARDIR/tmp/vblobs.txt' replace into table t;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
10 8 8 8 8
|
||||
update t set a=11, b=9, d=9 where a>5;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
11 9 9 9 9
|
||||
create table t2 select * from t;
|
||||
update t, t2 set t.b=10, t.d=10 where t.a=t2.a;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
11 10 10 10 10
|
||||
update t, t tt set t.b=11, tt.d=11 where t.a=tt.a;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
select * from t;
|
||||
a b c d e
|
||||
11 11 11 11 11
|
||||
drop table t, t1, t2;
|
||||
create table t (f1 int, f2 int, f3 int as (f1*2) virtual, key(f3,f2));
|
||||
insert into t (f1,f2) values (1,1),(2,2);
|
||||
create view v as
|
||||
select a2.f1, a2.f2, a1.f3
|
||||
from t a1, t a2
|
||||
where a2.f3 <> 0
|
||||
with local check option;
|
||||
update v set f3 = 52;
|
||||
drop view v;
|
||||
drop table t;
|
55
mysql-test/suite/vcol/t/binlog.test
Normal file
55
mysql-test/suite/vcol/t/binlog.test
Normal file
|
@ -0,0 +1,55 @@
|
|||
--source include/have_innodb.inc
|
||||
--source include/have_binlog_format_row.inc
|
||||
--source include/master-slave.inc
|
||||
|
||||
#
|
||||
# MDEV-15243
|
||||
# Server crashes in in Field_blob::pack upon REPLACE into view with virtual
|
||||
# columns with binlog enabled
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (
|
||||
pk SERIAL,
|
||||
vcol_date DATE AS (col_date) PERSISTENT,
|
||||
vcol_int INT AS (col_int) VIRTUAL,
|
||||
vcol_year YEAR AS (col_year) PERSISTENT,
|
||||
vcol_blob BLOB AS (col_blob) VIRTUAL,
|
||||
col_date DATE,
|
||||
col_int INT NULL,
|
||||
col_blob BLOB NULL,
|
||||
col_year YEAR,
|
||||
PRIMARY KEY(pk)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
INSERT INTO t1 (col_date,col_int,col_blob,col_year) VALUES ('2010-04-24',5,'foo',1981);
|
||||
SET SQL_MODE='';
|
||||
|
||||
set binlog_row_image="FULL";
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
REPLACE INTO v1 SELECT pk, vcol_date, vcol_int, vcol_year, vcol_blob, col_date, col_int, col_blob, 1982 FROM t1;
|
||||
select col_date,col_int,col_blob,col_year from v1;
|
||||
sync_slave_with_master;
|
||||
select col_date,col_int,col_blob,col_year from v1;
|
||||
connection master;
|
||||
DROP VIEW v1;
|
||||
set binlog_row_image="MINIMAL";
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
REPLACE INTO v1 SELECT pk, vcol_date, vcol_int, vcol_year, vcol_blob, col_date, col_int, col_blob, 1983 FROM t1;
|
||||
select col_date,col_int,col_blob,col_year from v1;
|
||||
sync_slave_with_master;
|
||||
select col_date,col_int,col_blob,col_year from v1;
|
||||
connection master;
|
||||
DROP VIEW v1;
|
||||
set @@binlog_row_image="NOBLOB";
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
REPLACE INTO v1 SELECT pk, vcol_date, vcol_int, vcol_year, vcol_blob, col_date, col_int, col_blob, 1984 FROM t1;
|
||||
select col_date,col_int,col_blob,col_year from v1;
|
||||
sync_slave_with_master;
|
||||
select col_date,col_int,col_blob,col_year from v1;
|
||||
connection master;
|
||||
DROP VIEW v1;
|
||||
set @@binlog_row_image=default;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--source include/rpl_end.inc
|
|
@ -15,8 +15,10 @@ drop table t1;
|
|||
# this tests TABLE::mark_columns_needed_for_update()
|
||||
#
|
||||
create table t1 (a int, c int as(a), p varchar(20) as(y), y char(20), index (p,c));
|
||||
show create table t1;
|
||||
insert into t1 (a,y) values(1, "yyy");
|
||||
update t1 set a = 100 where a = 1;
|
||||
check table t1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
|
|
14
mysql-test/suite/vcol/t/update_binlog.test
Normal file
14
mysql-test/suite/vcol/t/update_binlog.test
Normal file
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# Check that vcol update works with binlog enabled
|
||||
#
|
||||
|
||||
--source include/have_binlog_format_row.inc
|
||||
|
||||
set binlog_row_image="FULL";
|
||||
set @@default_storage_engine="myisam";
|
||||
|
||||
--source update.test
|
||||
|
||||
set binlog_row_image="MINIMAL";
|
||||
|
||||
--source update.test
|
|
@ -6567,15 +6567,17 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
Remove from read_set spurious columns. The write_set has been
|
||||
handled before in table->mark_columns_needed_for_update.
|
||||
*/
|
||||
|
||||
void THD::binlog_prepare_row_images(TABLE *table)
|
||||
{
|
||||
DBUG_ENTER("THD::binlog_prepare_row_images");
|
||||
/**
|
||||
Remove from read_set spurious columns. The write_set has been
|
||||
handled before in table->mark_columns_needed_for_update.
|
||||
*/
|
||||
|
||||
DBUG_PRINT_BITSET("debug", "table->read_set (before preparing): %s", table->read_set);
|
||||
DBUG_PRINT_BITSET("debug", "table->read_set (before preparing): %s",
|
||||
table->read_set);
|
||||
THD *thd= table->in_use;
|
||||
|
||||
/**
|
||||
|
@ -6593,7 +6595,7 @@ void THD::binlog_prepare_row_images(TABLE *table)
|
|||
*/
|
||||
DBUG_ASSERT(table->read_set != &table->tmp_set);
|
||||
|
||||
switch(thd->variables.binlog_row_image)
|
||||
switch (thd->variables.binlog_row_image)
|
||||
{
|
||||
case BINLOG_ROW_IMAGE_MINIMAL:
|
||||
/* MINIMAL: Mark only PK */
|
||||
|
@ -6623,7 +6625,8 @@ void THD::binlog_prepare_row_images(TABLE *table)
|
|||
table->write_set);
|
||||
}
|
||||
|
||||
DBUG_PRINT_BITSET("debug", "table->read_set (after preparing): %s", table->read_set);
|
||||
DBUG_PRINT_BITSET("debug", "table->read_set (after preparing): %s",
|
||||
table->read_set);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
|
87
sql/table.cc
87
sql/table.cc
|
@ -6566,6 +6566,12 @@ void TABLE::mark_columns_per_binlog_row_image()
|
|||
DBUG_ASSERT(FALSE);
|
||||
}
|
||||
}
|
||||
/*
|
||||
We have to ensure that all virtual columns that are part of read set
|
||||
are calculated.
|
||||
*/
|
||||
if (vcol_set)
|
||||
bitmap_union(vcol_set, read_set);
|
||||
file->column_bitmaps_signal();
|
||||
}
|
||||
|
||||
|
@ -6607,7 +6613,8 @@ bool TABLE::mark_virtual_col(Field *field)
|
|||
/*
|
||||
@brief Mark virtual columns for update/insert commands
|
||||
|
||||
@param insert_fl <-> virtual columns are marked for insert command
|
||||
@param insert_fl true if virtual columns are marked for insert command
|
||||
For the moment this is not used, may be used in future.
|
||||
|
||||
@details
|
||||
The function marks virtual columns used in a update/insert commands
|
||||
|
@ -6632,7 +6639,8 @@ bool TABLE::mark_virtual_col(Field *field)
|
|||
be added to read_set either.
|
||||
*/
|
||||
|
||||
bool TABLE::mark_virtual_columns_for_write(bool insert_fl)
|
||||
bool TABLE::mark_virtual_columns_for_write(bool insert_fl
|
||||
__attribute__((unused)))
|
||||
{
|
||||
Field **vfield_ptr, *tmp_vfield;
|
||||
bool bitmap_updated= false;
|
||||
|
@ -6642,35 +6650,13 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl)
|
|||
{
|
||||
tmp_vfield= *vfield_ptr;
|
||||
if (bitmap_is_set(write_set, tmp_vfield->field_index))
|
||||
bitmap_updated= mark_virtual_col(tmp_vfield);
|
||||
bitmap_updated|= mark_virtual_col(tmp_vfield);
|
||||
else if (tmp_vfield->vcol_info->stored_in_db ||
|
||||
(tmp_vfield->flags & (PART_KEY_FLAG | FIELD_IN_PART_FUNC_FLAG)))
|
||||
{
|
||||
if (insert_fl)
|
||||
{
|
||||
bitmap_set_bit(write_set, tmp_vfield->field_index);
|
||||
mark_virtual_col(tmp_vfield);
|
||||
bitmap_updated= true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MY_BITMAP *save_read_set= read_set, *save_vcol_set= vcol_set;
|
||||
Item *vcol_item= tmp_vfield->vcol_info->expr;
|
||||
DBUG_ASSERT(vcol_item);
|
||||
bitmap_clear_all(&tmp_set);
|
||||
read_set= vcol_set= &tmp_set;
|
||||
vcol_item->walk(&Item::register_field_in_read_map, 1, 0);
|
||||
read_set= save_read_set;
|
||||
vcol_set= save_vcol_set;
|
||||
if (bitmap_is_overlapping(&tmp_set, write_set))
|
||||
{
|
||||
bitmap_set_bit(write_set, tmp_vfield->field_index);
|
||||
bitmap_set_bit(vcol_set, tmp_vfield->field_index);
|
||||
bitmap_union(read_set, &tmp_set);
|
||||
bitmap_union(vcol_set, &tmp_set);
|
||||
bitmap_updated= true;
|
||||
}
|
||||
}
|
||||
bitmap_set_bit(write_set, tmp_vfield->field_index);
|
||||
mark_virtual_col(tmp_vfield);
|
||||
bitmap_updated= true;
|
||||
}
|
||||
}
|
||||
if (bitmap_updated)
|
||||
|
@ -7262,8 +7248,8 @@ bool TABLE_LIST::process_index_hints(TABLE *tbl)
|
|||
}
|
||||
|
||||
/*
|
||||
TODO: get rid of tbl->force_index (on if any FORCE INDEX is specified) and
|
||||
create tbl->force_index_join instead.
|
||||
TODO: get rid of tbl->force_index (on if any FORCE INDEX is specified)
|
||||
and create tbl->force_index_join instead.
|
||||
Then use the correct force_index_XX instead of the global one.
|
||||
*/
|
||||
if (!index_join[INDEX_HINT_FORCE].is_clear_all() ||
|
||||
|
@ -7299,15 +7285,21 @@ size_t max_row_length(TABLE *table, const uchar *data)
|
|||
size_t length= table_s->reclength + 2 * table_s->fields;
|
||||
uint *const beg= table_s->blob_field;
|
||||
uint *const end= beg + table_s->blob_fields;
|
||||
my_ptrdiff_t const rec_offset= (my_ptrdiff_t) (data - table->record[0]);
|
||||
DBUG_ENTER("max_row_length");
|
||||
|
||||
for (uint *ptr= beg ; ptr != end ; ++ptr)
|
||||
{
|
||||
Field_blob* const blob= (Field_blob*) table->field[*ptr];
|
||||
length+= blob->get_length((const uchar*)
|
||||
(data + blob->offset(table->record[0]))) +
|
||||
HA_KEY_BLOB_LENGTH;
|
||||
Field * const field= table->field[*ptr];
|
||||
if (bitmap_is_set(table->read_set, field->field_index) &&
|
||||
!field->is_null(rec_offset))
|
||||
{
|
||||
Field_blob * const blob= (Field_blob*) field;
|
||||
length+= blob->get_length(rec_offset) + HA_KEY_BLOB_LENGTH;
|
||||
}
|
||||
}
|
||||
return length;
|
||||
DBUG_PRINT("exit", ("length: %lld", (longlong) length));
|
||||
DBUG_RETURN(length);
|
||||
}
|
||||
|
||||
|
||||
|
@ -7422,7 +7414,7 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
|
|||
Query_arena backup_arena;
|
||||
Turn_errors_to_warnings_handler Suppress_errors;
|
||||
int error;
|
||||
bool handler_pushed= 0;
|
||||
bool handler_pushed= 0, update_all_columns= 1;
|
||||
DBUG_ASSERT(vfield);
|
||||
|
||||
if (h->keyread_enabled())
|
||||
|
@ -7439,6 +7431,16 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
|
|||
in_use->push_internal_handler(&Suppress_errors);
|
||||
handler_pushed= 1;
|
||||
}
|
||||
else if (update_mode == VCOL_UPDATE_FOR_REPLACE &&
|
||||
in_use->is_current_stmt_binlog_format_row() &&
|
||||
in_use->variables.binlog_row_image != BINLOG_ROW_IMAGE_MINIMAL)
|
||||
{
|
||||
/*
|
||||
If we are doing a replace with not minimal binary logging, we have to
|
||||
calculate all virtual columns.
|
||||
*/
|
||||
update_all_columns= 1;
|
||||
}
|
||||
|
||||
/* Iterate over virtual fields in the table */
|
||||
for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
|
||||
|
@ -7451,8 +7453,8 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
|
|||
bool update= 0, swap_values= 0;
|
||||
switch (update_mode) {
|
||||
case VCOL_UPDATE_FOR_READ:
|
||||
update= !vcol_info->stored_in_db
|
||||
&& bitmap_is_set(vcol_set, vf->field_index);
|
||||
update= (!vcol_info->stored_in_db &&
|
||||
bitmap_is_set(vcol_set, vf->field_index));
|
||||
swap_values= 1;
|
||||
break;
|
||||
case VCOL_UPDATE_FOR_DELETE:
|
||||
|
@ -7460,8 +7462,9 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
|
|||
update= bitmap_is_set(vcol_set, vf->field_index);
|
||||
break;
|
||||
case VCOL_UPDATE_FOR_REPLACE:
|
||||
update= !vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG)
|
||||
&& bitmap_is_set(vcol_set, vf->field_index);
|
||||
update= ((!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) &&
|
||||
bitmap_is_set(vcol_set, vf->field_index)) ||
|
||||
update_all_columns);
|
||||
if (update && (vf->flags & BLOB_FLAG))
|
||||
{
|
||||
/*
|
||||
|
@ -7478,8 +7481,8 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
|
|||
case VCOL_UPDATE_INDEXED:
|
||||
case VCOL_UPDATE_INDEXED_FOR_UPDATE:
|
||||
/* Read indexed fields that was not updated in VCOL_UPDATE_FOR_READ */
|
||||
update= !vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) &&
|
||||
bitmap_is_set(vcol_set, vf->field_index);
|
||||
update= (!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) &&
|
||||
!bitmap_is_set(vcol_set, vf->field_index));
|
||||
swap_values= 1;
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue