Commit 7759826e authored by Marko Mäkelä's avatar Marko Mäkelä

Bug#12637786 Wrong secondary index entries on CHAR and VARCHAR columns

row_build_index_entry(): In innodb_file_format=Barracuda
(ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED), a secondary index on a
full column can refer to a field that is stored off-page in the
clustered index record. Take that into account.

rb:692 approved by Jimmy Yang
parent 39e1ea62
...@@ -967,6 +967,19 @@ ERROR HY000: Too big row ...@@ -967,6 +967,19 @@ ERROR HY000: Too big row
alter table t1 row_format=compact; alter table t1 row_format=compact;
create index t1u on t1 (u(1)); create index t1u on t1 (u(1));
drop table t1; drop table t1;
SET @r=REPEAT('a',500);
CREATE TABLE t1(a INT,
v1 VARCHAR(500), v2 VARCHAR(500), v3 VARCHAR(500),
v4 VARCHAR(500), v5 VARCHAR(500), v6 VARCHAR(500),
v7 VARCHAR(500), v8 VARCHAR(500), v9 VARCHAR(500),
v10 VARCHAR(500), v11 VARCHAR(500), v12 VARCHAR(500),
v13 VARCHAR(500), v14 VARCHAR(500), v15 VARCHAR(500),
v16 VARCHAR(500), v17 VARCHAR(500), v18 VARCHAR(500)
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
CREATE INDEX idx1 ON t1(a,v1);
INSERT INTO t1 VALUES(9,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r);
UPDATE t1 SET a=1000;
DROP TABLE t1;
set global innodb_file_per_table=0; set global innodb_file_per_table=0;
set global innodb_file_format=Antelope; set global innodb_file_format=Antelope;
set global innodb_file_format_check=Antelope; set global innodb_file_format_check=Antelope;
......
...@@ -404,6 +404,22 @@ alter table t1 row_format=compact; ...@@ -404,6 +404,22 @@ alter table t1 row_format=compact;
create index t1u on t1 (u(1)); create index t1u on t1 (u(1));
drop table t1; drop table t1;
# Bug#12637786
SET @r=REPEAT('a',500);
CREATE TABLE t1(a INT,
v1 VARCHAR(500), v2 VARCHAR(500), v3 VARCHAR(500),
v4 VARCHAR(500), v5 VARCHAR(500), v6 VARCHAR(500),
v7 VARCHAR(500), v8 VARCHAR(500), v9 VARCHAR(500),
v10 VARCHAR(500), v11 VARCHAR(500), v12 VARCHAR(500),
v13 VARCHAR(500), v14 VARCHAR(500), v15 VARCHAR(500),
v16 VARCHAR(500), v17 VARCHAR(500), v18 VARCHAR(500)
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
CREATE INDEX idx1 ON t1(a,v1);
INSERT INTO t1 VALUES(9,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r);
UPDATE t1 SET a=1000;
DROP TABLE t1;
eval set global innodb_file_per_table=$per_table; eval set global innodb_file_per_table=$per_table;
eval set global innodb_file_format=$format; eval set global innodb_file_format=$format;
eval set global innodb_file_format_check=$format; eval set global innodb_file_format_check=$format;
......
2011-06-30 The InnoDB Team
* row/row0row.c:
Fix Bug#12637786 Wrong secondary index entries on CHAR and VARCHAR
columns in ROW_FORMAT=DYNAMIC and ROW_FORMAT=COMPRESSED
2011-06-16 The InnoDB Team 2011-06-16 The InnoDB Team
* btr/btr0cur.c, buf/buf0buddy.c, buf/buf0buf.c, buf/buf0lru.c, * btr/btr0cur.c, buf/buf0buddy.c, buf/buf0buf.c, buf/buf0lru.c,
......
...@@ -101,12 +101,27 @@ row_build_index_entry( ...@@ -101,12 +101,27 @@ row_build_index_entry(
dfield_copy(dfield, dfield2); dfield_copy(dfield, dfield2);
if (dfield_is_null(dfield) || ind_field->prefix_len == 0) { if (dfield_is_null(dfield)) {
continue; continue;
} }
/* If a column prefix index, take only the prefix. if (ind_field->prefix_len == 0
Prefix-indexed columns may be externally stored. */ && (!dfield_is_ext(dfield)
|| dict_index_is_clust(index))) {
/* The dfield_copy() above suffices for
columns that are stored in-page, or for
clustered index record columns that are not
part of a column prefix in the PRIMARY KEY. */
continue;
}
/* If the column is stored externally (off-page) in
the clustered index, it must be an ordering field in
the secondary index. In the Antelope format, only
prefix-indexed columns may be stored off-page in the
clustered index record. In the Barracuda format, also
fully indexed long CHAR or VARCHAR columns may be
stored off-page. */
ut_ad(col->ord_part); ut_ad(col->ord_part);
if (UNIV_LIKELY_NULL(ext)) { if (UNIV_LIKELY_NULL(ext)) {
...@@ -119,13 +134,34 @@ row_build_index_entry( ...@@ -119,13 +134,34 @@ row_build_index_entry(
} }
dfield_set_data(dfield, buf, len); dfield_set_data(dfield, buf, len);
} }
if (ind_field->prefix_len == 0) {
/* In the Barracuda format
(ROW_FORMAT=DYNAMIC or
ROW_FORMAT=COMPRESSED), we can have a
secondary index on an entire column
that is stored off-page in the
clustered index. As this is not a
prefix index (prefix_len == 0),
include the entire off-page column in
the secondary index record. */
continue;
}
} else if (dfield_is_ext(dfield)) { } else if (dfield_is_ext(dfield)) {
/* This table should be in Antelope format
(ROW_FORMAT=REDUNDANT or ROW_FORMAT=COMPACT).
In that format, the maximum column prefix
index length is 767 bytes, and the clustered
index record contains a 768-byte prefix of
each off-page column. */
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE); ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
len -= BTR_EXTERN_FIELD_REF_SIZE; len -= BTR_EXTERN_FIELD_REF_SIZE;
ut_a(ind_field->prefix_len <= len ut_a(ind_field->prefix_len <= len
|| dict_index_is_clust(index)); || dict_index_is_clust(index));
} }
/* If a column prefix index, take only the prefix. */
ut_ad(ind_field->prefix_len);
len = dtype_get_at_most_n_mbchars( len = dtype_get_at_most_n_mbchars(
col->prtype, col->mbminlen, col->mbmaxlen, col->prtype, col->mbminlen, col->mbmaxlen,
ind_field->prefix_len, len, dfield_get_data(dfield)); ind_field->prefix_len, len, dfield_get_data(dfield));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment