Skip to content

Commit 31366c6

Browse files
committed
MDEV-17548 Incorrect access to off-page column for indexed virtual column
row_build_index_entry_low(): ext does not contain virtual columns. row_upd_store_v_row(): Copy virtual column values This is based on the following fix in MySQL 5.7.24: commit 4ec2158bec73f1582501c4b3e3de250fed9edc9a Author: Sachin Agarwal <sachin.z.agarwal@oracle.com> Date: Fri Aug 24 14:44:13 2018 +0530 Bug #27968952 INNODB CRASH/CORRUPTION WITH TEXT PREFIX INDEXES Problem: There are two problems: 1. If there is one secondary index on extenally stored column and another seconday index on virtual column (whose base column is not externally stored). then while updating seconday index on vitrual column, virtual column data is replaced by externally stoared column. 2. In row update operation, node->row contains shallow copy of virtual data fields. While building an update vector containing all the fields to be modified, compute virtual column. which may causes change in virtual data fields in node->row. In both the above cases, while updating seconday index on virtual column, couldn't find the row and hit an explicite assert inside ROW_NOT_FOUND. Fix: 1. Added check if column is virtual then its ext flag should be ZERO and virtual column data will not be replaced by offset column data. 2. Deep copy of virtual data fields for node->row. RB: #20382 Reviewed by : Jimmy.Yang@oracle.com
1 parent e548d92 commit 31366c6

File tree

4 files changed

+67
-2
lines changed

4 files changed

+67
-2
lines changed

mysql-test/suite/gcol/r/innodb_virtual_index.result

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,35 @@ t1 CREATE TABLE `t1` (
211211
KEY `n` (`col2`)
212212
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
213213
DROP TABLE t1;
214+
#
215+
# Bug #27968952 INNODB CRASH/CORRUPTION WITH TEXT PREFIX INDEXES
216+
#
217+
CREATE TABLE t1(
218+
a INT NOT NULL UNIQUE,
219+
b INT NOT NULL,
220+
c TEXT GENERATED ALWAYS AS (a <> b) VIRTUAL,
221+
d TEXT NOT NULL,
222+
UNIQUE KEY (c(1)), KEY(d(1))
223+
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
224+
SET @t = REPEAT('t',@@innodb_page_size);
225+
INSERT INTO t1 (a,b,d) VALUES (1,0,@t), (0,0,@t);
226+
UPDATE t1 SET b = a;
227+
ERROR 23000: Duplicate entry '0' for key 'c'
228+
REPLACE INTO t1 SET a = 0, b = 1, d = 'd';
229+
SELECT * FROM t1;
230+
a b c d
231+
0 1 1 d
232+
CHECK TABLE t1;
233+
Table Op Msg_type Msg_text
234+
test.t1 check status OK
235+
DROP TABLE t1;
236+
CREATE TABLE t1(
237+
a VARCHAR(1000) GENERATED ALWAYS AS ('1') VIRTUAL,
238+
b VARCHAR(1000) NOT NULL,
239+
c VARCHAR(1000) GENERATED ALWAYS AS (b) STORED,
240+
KEY (b(1)),
241+
KEY (a(1))
242+
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1;
243+
INSERT INTO t1(b) VALUES(REPEAT('b',1000));
244+
DELETE FROM t1;
245+
DROP TABLE t1;

mysql-test/suite/gcol/t/innodb_virtual_index.test

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,34 @@ CREATE TABLE t1 (col1 int(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
232232
ALTER TABLE t1 ADD col2 char(21) AS (col1 * col1), ADD INDEX n (col2);
233233
SHOW CREATE TABLE t1;
234234
DROP TABLE t1;
235+
236+
--echo #
237+
--echo # Bug #27968952 INNODB CRASH/CORRUPTION WITH TEXT PREFIX INDEXES
238+
--echo #
239+
240+
CREATE TABLE t1(
241+
a INT NOT NULL UNIQUE,
242+
b INT NOT NULL,
243+
c TEXT GENERATED ALWAYS AS (a <> b) VIRTUAL,
244+
d TEXT NOT NULL,
245+
UNIQUE KEY (c(1)), KEY(d(1))
246+
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
247+
SET @t = REPEAT('t',@@innodb_page_size);
248+
INSERT INTO t1 (a,b,d) VALUES (1,0,@t), (0,0,@t);
249+
--error ER_DUP_ENTRY
250+
UPDATE t1 SET b = a;
251+
REPLACE INTO t1 SET a = 0, b = 1, d = 'd';
252+
SELECT * FROM t1;
253+
CHECK TABLE t1;
254+
DROP TABLE t1;
255+
256+
CREATE TABLE t1(
257+
a VARCHAR(1000) GENERATED ALWAYS AS ('1') VIRTUAL,
258+
b VARCHAR(1000) NOT NULL,
259+
c VARCHAR(1000) GENERATED ALWAYS AS (b) STORED,
260+
KEY (b(1)),
261+
KEY (a(1))
262+
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1;
263+
INSERT INTO t1(b) VALUES(REPEAT('b',1000));
264+
DELETE FROM t1;
265+
DROP TABLE t1;

storage/innobase/row/row0row.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*****************************************************************************
22
3-
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
3+
Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved.
44
Copyright (c) 2018, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
@@ -295,7 +295,7 @@ row_build_index_entry_low(
295295
stored off-page. */
296296
ut_ad(col->ord_part);
297297

298-
if (ext) {
298+
if (ext && !col->is_virtual()) {
299299
/* See if the column is stored externally. */
300300
const byte* buf = row_ext_lookup(ext, col_no,
301301
&len);

storage/innobase/row/row0upd.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,6 +2157,7 @@ row_upd_store_v_row(
21572157
}
21582158

21592159
dfield_copy_data(dfield, upd_field->old_v_val);
2160+
dfield_dup(dfield, node->heap);
21602161
break;
21612162
}
21622163

@@ -2177,6 +2178,7 @@ row_upd_store_v_row(
21772178
update->old_vrow,
21782179
col_no);
21792180
dfield_copy_data(dfield, vfield);
2181+
dfield_dup(dfield, node->heap);
21802182
}
21812183
} else {
21822184
/* Need to compute, this happens when

0 commit comments

Comments
 (0)