summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@oracle.com>2011-09-12 10:12:15 +0300
committerMarko Mäkelä <marko.makela@oracle.com>2011-09-12 10:12:15 +0300
commitcc496eb7466487747d26d272f0559df9a07f2e34 (patch)
treeaa87288a228c83a53ffe1f3dfc1851cef20dbc4f /storage
parent13fefeb04ade34418cd9d99aa93bffb69fdae27e (diff)
downloadmariadb-git-cc496eb7466487747d26d272f0559df9a07f2e34.tar.gz
Bug#12601439 CONSISTENT READ FAILURE IN COLUMN PREFIX INDEX
When there is a secondary index on a column prefix of an externally stored column and an entry in the secondary index is shorter than the reserved prefix length, it should mean that the secondary index entry is holding the complete column value. When comparing this secondary index column value to the column in the clustered index row, we must compare the entire prefix that was fetched from the clustered index. The bug was that we would just compare that the column in the clustered index starts with the value found in the secondary index column. This bug affects only the InnoDB Barracuda formats (ROW_FORMAT=DYNAMIC and ROW_FORMAT=COMPRESSED), in which columns that are stored off-page in the clustered index do not contain any prefix in the clustered index record. row_sel_sec_rec_is_for_blob(): Add the parameter prefix_len, for ifield->prefix_len. Add some assertions. Sorry, I did not manage to produce a test case. This patch does produce correct results on the data set that Michael isolated on our test machine. That was with the purge and background rollback suspended, because they would make the bug go away. rb:760 approved by Sunny Bains
Diffstat (limited to 'storage')
-rw-r--r--storage/innodb_plugin/ChangeLog5
-rw-r--r--storage/innodb_plugin/row/row0sel.c20
2 files changed, 22 insertions, 3 deletions
diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog
index 130a0f9afa2..ff6bd10dbe6 100644
--- a/storage/innodb_plugin/ChangeLog
+++ b/storage/innodb_plugin/ChangeLog
@@ -1,3 +1,8 @@
+2011-09-12 The InnoDB Team
+
+ * row/row0sel.c:
+ Fix Bug#12601439 CONSISTENT READ FAILURE IN COLUMN PREFIX INDEX
+
2011-09-08 The InnoDB Team
* btr/btr0cur.c, include/page0page.h, include/row0upd.ic:
diff --git a/storage/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0sel.c
index aa3f6283c4f..c9b409cbedd 100644
--- a/storage/innodb_plugin/row/row0sel.c
+++ b/storage/innodb_plugin/row/row0sel.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -107,12 +107,17 @@ row_sel_sec_rec_is_for_blob(
ulint clust_len, /*!< in: length of clust_field */
const byte* sec_field, /*!< in: column in secondary index */
ulint sec_len, /*!< in: length of sec_field */
+ ulint prefix_len, /*!< in: index column prefix length
+ in bytes */
ulint zip_size) /*!< in: compressed page size, or 0 */
{
ulint len;
byte buf[DICT_MAX_INDEX_COL_LEN];
ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE);
+ ut_ad(prefix_len >= sec_len);
+ ut_ad(prefix_len > 0);
+ ut_a(prefix_len <= sizeof buf);
if (UNIV_UNLIKELY
(!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE,
@@ -124,7 +129,7 @@ row_sel_sec_rec_is_for_blob(
return(FALSE);
}
- len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
+ len = btr_copy_externally_stored_field_prefix(buf, prefix_len,
zip_size,
clust_field, clust_len);
@@ -138,7 +143,7 @@ row_sel_sec_rec_is_for_blob(
}
len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen,
- sec_len, len, (const char*) buf);
+ prefix_len, len, (const char*) buf);
return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
}
@@ -225,11 +230,20 @@ row_sel_sec_rec_is_for_clust_rec(
if (rec_offs_nth_extern(clust_offs, clust_pos)
&& len < sec_len) {
+ /* This function should never be
+ invoked on an Antelope format table,
+ because they should always contain
+ enough prefix in the clustered index
+ record. */
+ ut_ad(dict_table_get_format(clust_index->table)
+ >= DICT_TF_FORMAT_ZIP);
+
if (!row_sel_sec_rec_is_for_blob(
col->mtype, col->prtype,
col->mbminlen, col->mbmaxlen,
clust_field, clust_len,
sec_field, sec_len,
+ ifield->prefix_len,
dict_table_zip_size(
clust_index->table))) {
goto inequal;