Bug#54408: txn rollback after recovery: row0umod.c:673

dict_table_get_format(index->table)

The REDUNDANT and COMPACT formats store a local 768-byte prefix of
each externally stored column. No row_ext cache is needed, but we
initialized one nevertheless. When the BLOB pointer was zero, we would
ignore the locally stored prefix as well. This triggered an assertion
failure in row_undo_mod_upd_exist_sec().

row_build(): Allow ext==NULL when a REDUNDANT or COMPACT table
contains externally stored columns.

row_undo_search_clust_to_pcur(), row_upd_store_row(): Invoke
row_build() with ext==NULL on REDUNDANT and COMPACT tables.

rb://382 approved by Jimmy Yang
This commit is contained in:
Marko Mäkelä 2010-06-29 16:00:58 +03:00
parent c43070dabe
commit c8e48de261
3 changed files with 40 additions and 3 deletions

View file

@ -294,7 +294,13 @@ row_build(
ut_ad(dtuple_check_typed(row));
if (j) {
if (!ext) {
/* REDUNDANT and COMPACT formats store a local
768-byte prefix of each externally stored
column. No cache is needed. */
ut_ad(dict_table_get_format(index->table)
< DICT_TF_FORMAT_ZIP);
} else if (j) {
*ext = row_ext_create(j, ext_cols, row,
dict_table_zip_size(index->table),
heap);

View file

@ -199,8 +199,24 @@ row_undo_search_clust_to_pcur(
ret = FALSE;
} else {
row_ext_t** ext;
if (dict_table_get_format(node->table) >= DICT_TF_FORMAT_ZIP) {
/* In DYNAMIC or COMPRESSED format, there is
no prefix of externally stored columns in the
clustered index record. Build a cache of
column prefixes. */
ext = &node->ext;
} else {
/* REDUNDANT and COMPACT formats store a local
768-byte prefix of each externally stored
column. No cache is needed. */
ext = NULL;
node->ext = NULL;
}
node->row = row_build(ROW_COPY_DATA, clust_index, rec,
offsets, NULL, &node->ext, node->heap);
offsets, NULL, ext, node->heap);
if (node->update) {
node->undo_row = dtuple_copy(node->row, node->heap);
row_upd_replace(node->undo_row, &node->undo_ext,

View file

@ -1398,6 +1398,7 @@ row_upd_store_row(
dict_index_t* clust_index;
rec_t* rec;
mem_heap_t* heap = NULL;
row_ext_t** ext;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
const ulint* offsets;
rec_offs_init(offsets_);
@ -1414,8 +1415,22 @@ row_upd_store_row(
offsets = rec_get_offsets(rec, clust_index, offsets_,
ULINT_UNDEFINED, &heap);
if (dict_table_get_format(node->table) >= DICT_TF_FORMAT_ZIP) {
/* In DYNAMIC or COMPRESSED format, there is no prefix
of externally stored columns in the clustered index
record. Build a cache of column prefixes. */
ext = &node->ext;
} else {
/* REDUNDANT and COMPACT formats store a local
768-byte prefix of each externally stored column.
No cache is needed. */
ext = NULL;
node->ext = NULL;
}
node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
NULL, &node->ext, node->heap);
NULL, ext, node->heap);
if (node->is_delete) {
node->upd_row = NULL;
node->upd_ext = NULL;