Many files:

Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.


innobase/btr/btr0btr.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/btr/btr0cur.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/btr/btr0pcur.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/btr/btr0sea.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/data/data0data.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/data/data0type.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/dict/dict0boot.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/dict/dict0crea.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/dict/dict0dict.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/dict/dict0load.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/dict/dict0mem.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/fil/fil0fil.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/fsp/fsp0fsp.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/ibuf/ibuf0ibuf.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/btr0btr.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/btr0btr.ic:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/btr0cur.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/btr0cur.ic:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/btr0pcur.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/btr0sea.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/data0type.ic:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/dict0dict.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/dict0dict.ic:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/dict0mem.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/lock0lock.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/lock0lock.ic:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/mtr0log.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/mtr0mtr.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/page0cur.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/page0cur.ic:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/page0page.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/page0page.ic:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/rem0cmp.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/rem0cmp.ic:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/rem0rec.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/rem0rec.ic:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/row0row.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/row0row.ic:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/row0upd.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/row0upd.ic:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/row0vers.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/row0vers.ic:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/srv0srv.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/trx0rec.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/ut0byte.h:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/include/ut0byte.ic:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/lock/lock0lock.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/log/log0recv.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/mtr/mtr0log.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/page/page0cur.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/page/page0page.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/pars/pars0pars.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/rem/rem0cmp.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/rem/rem0rec.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/row/row0ins.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/row/row0mysql.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/row/row0purge.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/row/row0row.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/row/row0sel.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/row/row0umod.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/row/row0undo.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/row/row0upd.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/row/row0vers.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/srv/srv0srv.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/trx/trx0rec.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
innobase/trx/trx0undo.c:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
sql/ha_innodb.cc:
  Implement more compact InnoDB record format.
  Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
This commit is contained in:
unknown 2004-12-02 19:45:07 +02:00
parent 4a9ef43a49
commit d2c4b54540
67 changed files with 5641 additions and 2488 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -45,12 +45,12 @@ btr_pcur_free_for_mysql(
mem_free(cursor->old_rec_buf);
cursor->old_rec = NULL;
cursor->old_rec_buf = NULL;
}
cursor->btr_cur.page_cur.rec = NULL;
cursor->old_rec = NULL;
cursor->old_n_fields = 0;
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
cursor->latch_mode = BTR_NO_LATCHES;
@ -133,9 +133,10 @@ btr_pcur_store_position(
cursor->old_stored = BTR_PCUR_OLD_STORED;
cursor->old_rec = dict_tree_copy_rec_order_prefix(tree, rec,
&(cursor->old_rec_buf),
&(cursor->buf_size));
&cursor->old_n_fields,
&cursor->old_rec_buf,
&cursor->buf_size);
cursor->block_when_stored = buf_block_align(page);
cursor->modify_clock = buf_frame_get_modify_clock(page);
}
@ -166,6 +167,8 @@ btr_pcur_copy_stored_position(
pcur_receive->old_rec = pcur_receive->old_rec_buf
+ (pcur_donate->old_rec - pcur_donate->old_rec_buf);
}
pcur_receive->old_n_fields = pcur_donate->old_n_fields;
}
/******************************************************************
@ -228,6 +231,7 @@ btr_pcur_restore_position(
}
ut_a(cursor->old_rec);
ut_a(cursor->old_n_fields);
page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor));
@ -242,17 +246,32 @@ btr_pcur_restore_position(
buf_page_dbg_add_level(page, SYNC_TREE_NODE);
#endif /* UNIV_SYNC_DEBUG */
if (cursor->rel_pos == BTR_PCUR_ON) {
#ifdef UNIV_DEBUG
rec_t* rec;
ulint* offsets1;
ulint* offsets2;
dict_index_t* index;
#endif /* UNIV_DEBUG */
cursor->latch_mode = latch_mode;
#ifdef UNIV_DEBUG
rec = btr_pcur_get_rec(cursor);
index = dict_tree_find_index(
btr_cur_get_tree(
btr_pcur_get_btr_cur(cursor)),
rec);
heap = mem_heap_create(256);
offsets1 = rec_get_offsets(cursor->old_rec,
index, ULINT_UNDEFINED, heap);
offsets2 = rec_get_offsets(rec,
index, ULINT_UNDEFINED, heap);
ut_ad(cmp_rec_rec(cursor->old_rec,
btr_pcur_get_rec(cursor),
dict_tree_find_index(
btr_cur_get_tree(
btr_pcur_get_btr_cur(cursor)),
btr_pcur_get_rec(cursor)))
== 0);
rec, offsets1, offsets2,
cursor->old_n_fields,
index) == 0);
mem_heap_free(heap);
#endif /* UNIV_DEBUG */
return(TRUE);
}
@ -265,7 +284,8 @@ btr_pcur_restore_position(
heap = mem_heap_create(256);
tree = btr_cur_get_tree(btr_pcur_get_btr_cur(cursor));
tuple = dict_tree_build_data_tuple(tree, cursor->old_rec, heap);
tuple = dict_tree_build_data_tuple(tree, cursor->old_rec,
cursor->old_n_fields, heap);
/* Save the old search mode of the cursor */
old_mode = cursor->search_mode;
@ -287,7 +307,10 @@ btr_pcur_restore_position(
if (cursor->rel_pos == BTR_PCUR_ON
&& btr_pcur_is_on_user_rec(cursor, mtr)
&& 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor))) {
&& 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
rec_get_offsets(btr_pcur_get_rec(cursor),
btr_pcur_get_btr_cur(cursor)->index,
ULINT_UNDEFINED, heap))) {
/* We have to store the NEW value for the modify clock, since
the cursor can now be on a different page! But we can retain
@ -376,6 +399,7 @@ btr_pcur_move_to_next_page(
ut_ad(next_page_no != FIL_NULL);
next_page = btr_page_get(space, next_page_no, cursor->latch_mode, mtr);
ut_a(page_is_comp(next_page) == page_is_comp(page));
buf_block_align(next_page)->check_index_page_at_flush = TRUE;
btr_leaf_page_release(page, cursor->latch_mode, mtr);

View File

@ -416,7 +416,7 @@ btr_search_update_hash_ref(
&& (block->curr_n_fields == info->n_fields)
&& (block->curr_n_bytes == info->n_bytes)
&& (block->curr_side == info->side)) {
mem_heap_t* heap;
rec = btr_cur_get_rec(cursor);
if (!page_rec_is_user_rec(rec)) {
@ -425,10 +425,11 @@ btr_search_update_hash_ref(
}
tree_id = ((cursor->index)->tree)->id;
fold = rec_fold(rec, block->curr_n_fields,
block->curr_n_bytes, tree_id);
heap = mem_heap_create(100);
fold = rec_fold(rec, rec_get_offsets(rec, cursor->index,
ULINT_UNDEFINED, heap), block->curr_n_fields,
block->curr_n_bytes, tree_id);
mem_heap_free(heap);
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
@ -535,15 +536,17 @@ btr_search_check_guess(
or PAGE_CUR_GE */
mtr_t* mtr) /* in: mtr */
{
page_t* page;
rec_t* rec;
rec_t* prev_rec;
rec_t* next_rec;
ulint n_unique;
ulint match;
ulint bytes;
int cmp;
page_t* page;
rec_t* rec;
rec_t* prev_rec;
rec_t* next_rec;
ulint n_unique;
ulint match;
ulint bytes;
int cmp;
mem_heap_t* heap = mem_heap_create(100);
ulint* offsets = NULL;
n_unique = dict_index_get_n_unique_in_tree(cursor->index);
rec = btr_cur_get_rec(cursor);
@ -554,23 +557,25 @@ btr_search_check_guess(
match = 0;
bytes = 0;
cmp = page_cmp_dtuple_rec_with_match(tuple, rec, &match, &bytes);
offsets = rec_get_offsets(rec, cursor->index, n_unique, heap);
cmp = page_cmp_dtuple_rec_with_match(tuple, rec,
offsets, &match, &bytes);
if (mode == PAGE_CUR_GE) {
if (cmp == 1) {
mem_heap_free(heap);
return(FALSE);
}
cursor->up_match = match;
if (match >= n_unique) {
mem_heap_free(heap);
return(TRUE);
}
} else if (mode == PAGE_CUR_LE) {
if (cmp == -1) {
mem_heap_free(heap);
return(FALSE);
}
@ -578,12 +583,12 @@ btr_search_check_guess(
} else if (mode == PAGE_CUR_G) {
if (cmp != -1) {
mem_heap_free(heap);
return(FALSE);
}
} else if (mode == PAGE_CUR_L) {
if (cmp != 1) {
mem_heap_free(heap);
return(FALSE);
}
}
@ -591,7 +596,7 @@ btr_search_check_guess(
if (can_only_compare_to_cursor_rec) {
/* Since we could not determine if our guess is right just by
looking at the record under the cursor, return FALSE */
mem_heap_free(heap);
return(FALSE);
}
@ -605,17 +610,15 @@ btr_search_check_guess(
prev_rec = page_rec_get_prev(rec);
if (prev_rec == page_get_infimum_rec(page)) {
if (btr_page_get_prev(page, mtr) != FIL_NULL) {
return(FALSE);
}
return(TRUE);
mem_heap_free(heap);
return(btr_page_get_prev(page, mtr) == FIL_NULL);
}
offsets = rec_reget_offsets(prev_rec, cursor->index,
offsets, n_unique, heap);
cmp = page_cmp_dtuple_rec_with_match(tuple, prev_rec,
&match, &bytes);
offsets, &match, &bytes);
mem_heap_free(heap);
if (mode == PAGE_CUR_GE) {
if (cmp != 1) {
@ -636,6 +639,7 @@ btr_search_check_guess(
next_rec = page_rec_get_next(rec);
if (next_rec == page_get_supremum_rec(page)) {
mem_heap_free(heap);
if (btr_page_get_next(page, mtr) == FIL_NULL) {
@ -647,8 +651,12 @@ btr_search_check_guess(
return(FALSE);
}
cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec, &match, &bytes);
offsets = rec_reget_offsets(next_rec, cursor->index,
offsets, n_unique, heap);
cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec,
offsets, &match, &bytes);
mem_heap_free(heap);
if (mode == PAGE_CUR_LE) {
if (cmp != -1) {
@ -1003,8 +1011,7 @@ static
void
btr_search_build_page_hash_index(
/*=============================*/
dict_index_t* index, /* in: index for which to build, or NULL if
not known */
dict_index_t* index, /* in: index for which to build */
page_t* page, /* in: index page, s- or x-latched */
ulint n_fields,/* in: hash this many full fields */
ulint n_bytes,/* in: hash this many bytes from the next
@ -1024,7 +1031,11 @@ btr_search_build_page_hash_index(
ulint* folds;
rec_t** recs;
ulint i;
mem_heap_t* heap;
ulint* offsets;
ut_ad(index);
block = buf_block_align(page);
table = btr_search_sys->hash_index;
@ -1061,9 +1072,9 @@ btr_search_build_page_hash_index(
return;
}
if (index && (dict_index_get_n_unique_in_tree(index) < n_fields
if (dict_index_get_n_unique_in_tree(index) < n_fields
|| (dict_index_get_n_unique_in_tree(index) == n_fields
&& n_bytes > 0))) {
&& n_bytes > 0)) {
return;
}
@ -1072,6 +1083,7 @@ btr_search_build_page_hash_index(
folds = mem_alloc(n_recs * sizeof(ulint));
recs = mem_alloc(n_recs * sizeof(rec_t*));
heap = mem_heap_create(100);
n_cached = 0;
@ -1082,18 +1094,19 @@ btr_search_build_page_hash_index(
rec = page_get_infimum_rec(page);
rec = page_rec_get_next(rec);
offsets = rec_get_offsets(rec, index, n_fields + (n_bytes > 0), heap);
if (rec != sup) {
ut_a(n_fields <= rec_get_n_fields(rec));
ut_a(n_fields <= rec_offs_n_fields(offsets));
if (n_bytes > 0) {
ut_a(n_fields < rec_get_n_fields(rec));
ut_a(n_fields < rec_offs_n_fields(offsets));
}
}
/* FIXME: in a mixed tree, all records may not have enough ordering
fields: */
fold = rec_fold(rec, n_fields, n_bytes, tree_id);
fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id);
if (side == BTR_SEARCH_LEFT_SIDE) {
@ -1117,7 +1130,10 @@ btr_search_build_page_hash_index(
break;
}
next_fold = rec_fold(next_rec, n_fields, n_bytes, tree_id);
offsets = rec_reget_offsets(next_rec, index,
offsets, n_fields + (n_bytes > 0), heap);
next_fold = rec_fold(next_rec, offsets, n_fields,
n_bytes, tree_id);
if (fold != next_fold) {
/* Insert an entry into the hash index */
@ -1145,13 +1161,7 @@ btr_search_build_page_hash_index(
if (block->is_hashed && ((block->curr_n_fields != n_fields)
|| (block->curr_n_bytes != n_bytes)
|| (block->curr_side != side))) {
rw_lock_x_unlock(&btr_search_latch);
mem_free(folds);
mem_free(recs);
return;
goto exit_func;
}
block->is_hashed = TRUE;
@ -1166,10 +1176,12 @@ btr_search_build_page_hash_index(
ha_insert_for_fold(table, folds[i], recs[i]);
}
exit_func:
rw_lock_x_unlock(&btr_search_latch);
mem_free(folds);
mem_free(recs);
mem_heap_free(heap);
}
/************************************************************************
@ -1181,10 +1193,13 @@ parameters as page (this often happens when a page is split). */
void
btr_search_move_or_delete_hash_entries(
/*===================================*/
page_t* new_page, /* in: records are copied to this page */
page_t* page) /* in: index page from which records were
copied, and the copied records will be deleted
from this page */
page_t* new_page, /* in: records are copied
to this page */
page_t* page, /* in: index page from which
records were copied, and the
copied records will be deleted
from this page */
dict_index_t* index) /* in: record descriptor */
{
buf_block_t* block;
buf_block_t* new_block;
@ -1194,6 +1209,7 @@ btr_search_move_or_delete_hash_entries(
block = buf_block_align(page);
new_block = buf_block_align(new_page);
ut_a(page_is_comp(page) == page_is_comp(new_page));
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
@ -1224,8 +1240,8 @@ btr_search_move_or_delete_hash_entries(
rw_lock_s_unlock(&btr_search_latch);
ut_a(n_fields + n_bytes > 0);
btr_search_build_page_hash_index(NULL, new_page, n_fields,
btr_search_build_page_hash_index(index, new_page, n_fields,
n_bytes, side);
ut_a(n_fields == block->curr_n_fields);
ut_a(n_bytes == block->curr_n_bytes);
@ -1253,6 +1269,7 @@ btr_search_update_hash_on_delete(
ulint fold;
dulint tree_id;
ibool found;
mem_heap_t* heap;
rec = btr_cur_get_rec(cursor);
@ -1272,9 +1289,11 @@ btr_search_update_hash_on_delete(
table = btr_search_sys->hash_index;
tree_id = cursor->index->tree->id;
fold = rec_fold(rec, block->curr_n_fields, block->curr_n_bytes,
tree_id);
heap = mem_heap_create(100);
fold = rec_fold(rec, rec_get_offsets(rec, cursor->index,
ULINT_UNDEFINED, heap), block->curr_n_fields,
block->curr_n_bytes, tree_id);
mem_heap_free(heap);
rw_lock_x_lock(&btr_search_latch);
found = ha_search_and_delete_if_found(table, fold, rec);
@ -1355,6 +1374,8 @@ btr_search_update_hash_on_insert(
ulint n_bytes;
ulint side;
ibool locked = FALSE;
mem_heap_t* heap;
ulint* offsets;
table = btr_search_sys->hash_index;
@ -1383,15 +1404,22 @@ btr_search_update_hash_on_insert(
next_rec = page_rec_get_next(ins_rec);
page = buf_frame_align(rec);
ins_fold = rec_fold(ins_rec, n_fields, n_bytes, tree_id);
heap = mem_heap_create(100);
offsets = rec_get_offsets(ins_rec, cursor->index,
ULINT_UNDEFINED, heap);
ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, tree_id);
if (next_rec != page_get_supremum_rec(page)) {
next_fold = rec_fold(next_rec, n_fields, n_bytes, tree_id);
offsets = rec_reget_offsets(next_rec, cursor->index,
offsets, n_fields + (n_bytes > 0), heap);
next_fold = rec_fold(next_rec, offsets, n_fields,
n_bytes, tree_id);
}
if (rec != page_get_infimum_rec(page)) {
fold = rec_fold(rec, n_fields, n_bytes, tree_id);
offsets = rec_reget_offsets(rec, cursor->index,
offsets, n_fields + (n_bytes > 0), heap);
fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id);
} else {
if (side == BTR_SEARCH_LEFT_SIDE) {
@ -1461,6 +1489,7 @@ check_next_rec:
}
function_exit:
mem_heap_free(heap);
if (locked) {
rw_lock_x_unlock(&btr_search_latch);
}
@ -1470,9 +1499,10 @@ function_exit:
Validates the search system. */
ibool
btr_search_validate(void)
/*=====================*/
btr_search_validate(
/*================*/
/* out: TRUE if ok */
dict_index_t* index) /* in: record descriptor */
{
buf_block_t* block;
page_t* page;
@ -1480,6 +1510,8 @@ btr_search_validate(void)
ulint n_page_dumps = 0;
ibool ok = TRUE;
ulint i;
mem_heap_t* heap = mem_heap_create(100);
ulint* offsets = NULL;
rw_lock_x_lock(&btr_search_latch);
@ -1489,9 +1521,13 @@ btr_search_validate(void)
while (node != NULL) {
block = buf_block_align(node->data);
page = buf_frame_align(node->data);
offsets = rec_reget_offsets((rec_t*) node->data, index,
offsets, block->curr_n_fields
+ (block->curr_n_bytes > 0), heap);
if (!block->is_hashed
|| node->fold != rec_fold((rec_t*)(node->data),
offsets,
block->curr_n_fields,
block->curr_n_bytes,
btr_page_get_index_id(page))) {
@ -1507,12 +1543,13 @@ btr_search_validate(void)
(ulong) ut_dulint_get_low(btr_page_get_index_id(page)),
(ulong) node->fold,
(ulong) rec_fold((rec_t*)(node->data),
offsets,
block->curr_n_fields,
block->curr_n_bytes,
btr_page_get_index_id(page)));
fputs("InnoDB: Record ", stderr);
rec_print(stderr, (rec_t*)(node->data));
rec_print(stderr, (rec_t*)node->data, offsets);
fprintf(stderr, "\nInnoDB: on that page."
"Page mem address %p, is hashed %lu, n fields %lu, n bytes %lu\n"
"side %lu\n",
@ -1536,6 +1573,7 @@ btr_search_validate(void)
}
rw_lock_x_unlock(&btr_search_latch);
mem_heap_free(heap);
return(ok);
}

View File

@ -500,7 +500,7 @@ dtuple_convert_big_rec(
ut_a(dtuple_check_typed_no_assert(entry));
size = rec_get_converted_size(entry);
size = rec_get_converted_size(index, entry);
if (size > 1000000000) {
fprintf(stderr,
@ -524,9 +524,10 @@ dtuple_convert_big_rec(
n_fields = 0;
while ((rec_get_converted_size(entry)
>= page_get_free_space_of_empty() / 2)
|| rec_get_converted_size(entry) >= REC_MAX_DATA_SIZE) {
while (rec_get_converted_size(index, entry)
>= ut_min(page_get_free_space_of_empty(
index->table->comp) / 2,
REC_MAX_DATA_SIZE)) {
longest = 0;
for (i = dict_index_get_n_unique_in_tree(index);

View File

@ -195,7 +195,7 @@ dtype_validate(
ut_a((type->mtype >= DATA_VARCHAR) && (type->mtype <= DATA_MYSQL));
if (type->mtype == DATA_SYS) {
ut_a(type->prtype <= DATA_MIX_ID);
ut_a((type->prtype & DATA_MYSQL_TYPE_MASK) < DATA_N_SYS_COLS);
}
return(TRUE);

View File

@ -158,7 +158,7 @@ dict_hdr_create(
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
DICT_HDR_SPACE, DICT_TABLES_ID, mtr);
DICT_HDR_SPACE, DICT_TABLES_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@ -168,7 +168,7 @@ dict_hdr_create(
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_UNIQUE, DICT_HDR_SPACE,
DICT_TABLE_IDS_ID, mtr);
DICT_TABLE_IDS_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@ -178,7 +178,7 @@ dict_hdr_create(
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
DICT_HDR_SPACE, DICT_COLUMNS_ID, mtr);
DICT_HDR_SPACE, DICT_COLUMNS_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@ -188,7 +188,7 @@ dict_hdr_create(
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
DICT_HDR_SPACE, DICT_INDEXES_ID, mtr);
DICT_HDR_SPACE, DICT_INDEXES_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@ -198,7 +198,7 @@ dict_hdr_create(
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
DICT_HDR_SPACE, DICT_FIELDS_ID, mtr);
DICT_HDR_SPACE, DICT_FIELDS_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@ -254,7 +254,7 @@ dict_boot(void)
/* Insert into the dictionary cache the descriptions of the basic
system tables */
/*-------------------------*/
table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE,8);
table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, FALSE);
dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
@ -290,7 +290,7 @@ dict_boot(void)
index->id = DICT_TABLE_IDS_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
table = dict_mem_table_create("SYS_COLUMNS",DICT_HDR_SPACE,7);
table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, FALSE);
dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY,0,0,0);
dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);
@ -316,7 +316,7 @@ dict_boot(void)
index->id = DICT_COLUMNS_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
table = dict_mem_table_create("SYS_INDEXES",DICT_HDR_SPACE,7);
table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, FALSE);
dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY, 0,0,0);
dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
@ -349,7 +349,7 @@ dict_boot(void)
index->id = DICT_INDEXES_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE,3);
table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, FALSE);
dict_mem_table_add_col(table, "INDEX_ID", DATA_BINARY, 0,0,0);
dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);

View File

@ -84,7 +84,8 @@ dict_create_sys_tables_tuple(
dfield = dtuple_get_nth_field(entry, 5);
ptr = mem_heap_alloc(heap, 4);
mach_write_to_4(ptr, table->mix_len);
mach_write_to_4(ptr, (table->mix_len & 0x7fffffff) |
((ulint) table->comp << 31));
dfield_set_data(dfield, ptr, 4);
/* 8: CLUSTER_NAME ---------------------*/
@ -624,7 +625,7 @@ dict_create_index_tree_step(
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
index->page_no = btr_create(index->type, index->space, index->id,
&mtr);
table->comp, &mtr);
/* printf("Created a new index tree in space %lu root page %lu\n",
index->space, index->page_no); */
@ -660,8 +661,9 @@ dict_drop_index_tree(
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
ptr = rec_get_nth_field(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
ut_a(!dict_sys->sys_indexes->comp);
ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
ut_ad(len == 4);
@ -673,8 +675,9 @@ dict_drop_index_tree(
return;
}
ptr = rec_get_nth_field(rec, DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
ptr = rec_get_nth_field_old(rec,
DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
ut_ad(len == 4);
space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
@ -699,8 +702,8 @@ dict_drop_index_tree(
root_page_no); */
btr_free_root(space, root_page_no, mtr);
page_rec_write_index_page_no(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
FIL_NULL, mtr);
page_rec_write_index_page_no(rec,
DICT_SYS_INDEXES_PAGE_NO_FIELD, FIL_NULL, mtr);
}
/*************************************************************************

View File

@ -814,23 +814,22 @@ dict_table_add_to_cache(
system columns. */
dict_mem_table_add_col(table, "DB_ROW_ID", DATA_SYS,
DATA_ROW_ID, 0, 0);
DATA_ROW_ID | DATA_NOT_NULL, DATA_ROW_ID_LEN, 0);
#if DATA_ROW_ID != 0
#error "DATA_ROW_ID != 0"
#endif
dict_mem_table_add_col(table, "DB_TRX_ID", DATA_SYS,
DATA_TRX_ID, 0, 0);
DATA_TRX_ID | DATA_NOT_NULL, DATA_TRX_ID_LEN, 0);
#if DATA_TRX_ID != 1
#error "DATA_TRX_ID != 1"
#endif
dict_mem_table_add_col(table, "DB_ROLL_PTR", DATA_SYS,
DATA_ROLL_PTR, 0, 0);
DATA_ROLL_PTR | DATA_NOT_NULL, DATA_ROLL_PTR_LEN, 0);
#if DATA_ROLL_PTR != 2
#error "DATA_ROLL_PTR != 2"
#endif
dict_mem_table_add_col(table, "DB_MIX_ID", DATA_SYS,
DATA_MIX_ID, 0, 0);
DATA_MIX_ID | DATA_NOT_NULL, DATA_MIX_ID_LEN, 0);
#if DATA_MIX_ID != 3
#error "DATA_MIX_ID != 3"
#endif
@ -1588,7 +1587,7 @@ dict_index_find_cols(
/***********************************************************************
Adds a column to index. */
UNIV_INLINE
void
dict_index_add_col(
/*===============*/
@ -1604,6 +1603,34 @@ dict_index_add_col(
field = dict_index_get_nth_field(index, index->n_def - 1);
field->col = col;
field->fixed_len = dtype_get_fixed_size(&col->type);
if (prefix_len && field->fixed_len > prefix_len) {
field->fixed_len = prefix_len;
}
/* Long fixed-length fields that need external storage are treated as
variable-length fields, so that the extern flag can be embedded in
the length word. */
if (field->fixed_len > DICT_MAX_COL_PREFIX_LEN) {
field->fixed_len = 0;
}
if (!(dtype_get_prtype(&col->type) & DATA_NOT_NULL)) {
index->n_nullable++;
}
if (index->n_def > 1) {
const dict_field_t* field2 =
dict_index_get_nth_field(index, index->n_def - 2);
field->fixed_offs = (!field2->fixed_len ||
field2->fixed_offs == ULINT_UNDEFINED)
? ULINT_UNDEFINED
: field2->fixed_len + field2->fixed_offs;
} else {
field->fixed_offs = 0;
}
}
/***********************************************************************
@ -3580,9 +3607,10 @@ dict_tree_find_index_low(
&& (table->type != DICT_TABLE_ORDINARY)) {
/* Get the mix id of the record */
ut_a(!table->comp);
mix_id = mach_dulint_read_compressed(
rec_get_nth_field(rec, table->mix_len, &len));
rec_get_nth_field_old(rec, table->mix_len, &len));
while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
@ -3715,7 +3743,8 @@ dict_tree_build_node_ptr(
on non-leaf levels we remove the last field, which
contains the page number of the child page */
n_unique = rec_get_n_fields(rec);
ut_a(!ind->table->comp);
n_unique = rec_get_n_fields_old(rec);
if (level > 0) {
ut_a(n_unique > 1);
@ -3744,9 +3773,11 @@ dict_tree_build_node_ptr(
field = dtuple_get_nth_field(tuple, n_unique);
dfield_set_data(field, buf, 4);
dtype_set(dfield_get_type(field), DATA_SYS_CHILD, 0, 0, 0);
dtype_set(dfield_get_type(field), DATA_SYS_CHILD, DATA_NOT_NULL, 4, 0);
rec_copy_prefix_to_dtuple(tuple, rec, n_unique, heap);
rec_copy_prefix_to_dtuple(tuple, rec, ind, n_unique, heap);
dtuple_set_info_bits(tuple, dtuple_get_info_bits(tuple) |
REC_STATUS_NODE_PTR);
ut_ad(dtuple_check_typed(tuple));
@ -3763,27 +3794,26 @@ dict_tree_copy_rec_order_prefix(
/* out: pointer to the prefix record */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to copy prefix */
ulint* n_fields,/* out: number of fields copied */
byte** buf, /* in/out: memory buffer for the copied prefix,
or NULL */
ulint* buf_size)/* in/out: buffer size */
{
dict_index_t* ind;
rec_t* order_rec;
ulint n_fields;
ind = dict_tree_find_index_low(tree, rec);
dict_index_t* index;
ulint n;
index = dict_tree_find_index_low(tree, rec);
n_fields = dict_index_get_n_unique_in_tree(ind);
if (tree->type & DICT_UNIVERSAL) {
n_fields = rec_get_n_fields(rec);
ut_a(!index->table->comp);
n = rec_get_n_fields_old(rec);
} else {
n = dict_index_get_n_unique_in_tree(index);
}
order_rec = rec_copy_prefix_to_buf(rec, n_fields, buf, buf_size);
return(order_rec);
}
*n_fields = n;
return(rec_copy_prefix_to_buf(rec, index, n, buf, buf_size));
}
/**************************************************************************
Builds a typed data tuple out of a physical record. */
@ -3794,21 +3824,21 @@ dict_tree_build_data_tuple(
/* out, own: data tuple */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to build data tuple */
ulint n_fields,/* in: number of data fields */
mem_heap_t* heap) /* in: memory heap where tuple created */
{
dtuple_t* tuple;
dict_index_t* ind;
ulint n_fields;
ind = dict_tree_find_index_low(tree, rec);
n_fields = rec_get_n_fields(rec);
ut_ad(ind->table->comp || n_fields <= rec_get_n_fields_old(rec));
tuple = dtuple_create(heap, n_fields);
dict_index_copy_types(tuple, ind, n_fields);
rec_copy_prefix_to_dtuple(tuple, rec, n_fields, heap);
rec_copy_prefix_to_dtuple(tuple, rec, ind, n_fields, heap);
ut_ad(dtuple_check_typed(tuple));
@ -3826,6 +3856,27 @@ dict_index_calc_min_rec_len(
ulint sum = 0;
ulint i;
if (index->table->comp) {
ulint nullable = 0;
sum = REC_N_NEW_EXTRA_BYTES;
for (i = 0; i < dict_index_get_n_fields(index); i++) {
dtype_t*t = dict_index_get_nth_type(index, i);
ulint size = dtype_get_fixed_size(t);
sum += size;
if (!size) {
size = dtype_get_len(t);
sum += size < 128 ? 1 : 2;
}
if (!(dtype_get_prtype(t) & DATA_NOT_NULL))
nullable++;
}
/* round the NULL flags up to full bytes */
sum += (nullable + 7) / 8;
return(sum);
}
for (i = 0; i < dict_index_get_n_fields(index); i++) {
sum += dtype_get_fixed_size(dict_index_get_nth_type(index, i));
}
@ -3836,7 +3887,7 @@ dict_index_calc_min_rec_len(
sum += dict_index_get_n_fields(index);
}
sum += REC_N_EXTRA_BYTES;
sum += REC_N_OLD_EXTRA_BYTES;
return(sum);
}

View File

@ -55,6 +55,7 @@ dict_get_first_table_name_in_db(
sys_tables = dict_table_get_low("SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
ut_a(!sys_tables->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@ -77,7 +78,7 @@ loop:
return(NULL);
}
field = rec_get_nth_field(rec, 0, &len);
field = rec_get_nth_field_old(rec, 0, &len);
if (len < strlen(name)
|| ut_memcmp(name, field, strlen(name)) != 0) {
@ -90,7 +91,7 @@ loop:
return(NULL);
}
if (!rec_get_deleted_flag(rec)) {
if (!rec_get_deleted_flag(rec, sys_tables->comp)) {
/* We found one */
@ -163,9 +164,9 @@ loop:
return;
}
field = rec_get_nth_field(rec, 0, &len);
field = rec_get_nth_field_old(rec, 0, &len);
if (!rec_get_deleted_flag(rec)) {
if (!rec_get_deleted_flag(rec, sys_tables->comp)) {
/* We found one */
@ -229,6 +230,7 @@ dict_check_tablespaces_or_store_max_id(
sys_tables = dict_table_get_low("SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
ut_a(!sys_tables->comp);
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
TRUE, &mtr);
@ -255,15 +257,15 @@ loop:
return;
}
field = rec_get_nth_field(rec, 0, &len);
field = rec_get_nth_field_old(rec, 0, &len);
if (!rec_get_deleted_flag(rec)) {
if (!rec_get_deleted_flag(rec, sys_tables->comp)) {
/* We found one */
char* name = mem_strdupl((char*) field, len);
field = rec_get_nth_field(rec, 9, &len);
field = rec_get_nth_field_old(rec, 9, &len);
ut_a(len == 4);
space_id = mach_read_from_4(field);
@ -328,6 +330,7 @@ dict_load_columns(
sys_columns = dict_table_get_low("SYS_COLUMNS");
sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
ut_a(!sys_columns->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@ -346,28 +349,27 @@ dict_load_columns(
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
ut_a(!rec_get_deleted_flag(rec));
field = rec_get_nth_field(rec, 0, &len);
ut_a(!rec_get_deleted_flag(rec, sys_columns->comp));
field = rec_get_nth_field_old(rec, 0, &len);
ut_ad(len == 8);
ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
field = rec_get_nth_field(rec, 1, &len);
field = rec_get_nth_field_old(rec, 1, &len);
ut_ad(len == 4);
ut_a(i == mach_read_from_4(field));
ut_a(0 == ut_strcmp("NAME",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_columns), 4))->name));
dict_index_get_nth_field(sys_index, 4))->name));
field = rec_get_nth_field(rec, 4, &len);
field = rec_get_nth_field_old(rec, 4, &len);
name = mem_heap_strdupl(heap, (char*) field, len);
field = rec_get_nth_field(rec, 5, &len);
field = rec_get_nth_field_old(rec, 5, &len);
mtype = mach_read_from_4(field);
field = rec_get_nth_field(rec, 6, &len);
field = rec_get_nth_field_old(rec, 6, &len);
prtype = mach_read_from_4(field);
if (dtype_is_non_binary_string_type(mtype, prtype)
@ -379,15 +381,14 @@ dict_load_columns(
data_mysql_default_charset_coll);
}
field = rec_get_nth_field(rec, 7, &len);
field = rec_get_nth_field_old(rec, 7, &len);
col_len = mach_read_from_4(field);
ut_a(0 == ut_strcmp("PREC",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_columns), 8))->name));
dict_index_get_nth_field(sys_index, 8))->name));
field = rec_get_nth_field(rec, 8, &len);
field = rec_get_nth_field_old(rec, 8, &len);
prec = mach_read_from_4(field);
dict_mem_table_add_col(table, name, mtype, prtype, col_len,
@ -452,6 +453,7 @@ dict_load_fields(
sys_fields = dict_table_get_low("SYS_FIELDS");
sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
ut_a(!sys_fields->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@ -469,15 +471,15 @@ dict_load_fields(
rec = btr_pcur_get_rec(&pcur);
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
if (rec_get_deleted_flag(rec)) {
if (rec_get_deleted_flag(rec, sys_fields->comp)) {
dict_load_report_deleted_index(table->name, i);
}
field = rec_get_nth_field(rec, 0, &len);
field = rec_get_nth_field_old(rec, 0, &len);
ut_ad(len == 8);
ut_a(ut_memcmp(buf, field, len) == 0);
field = rec_get_nth_field(rec, 1, &len);
field = rec_get_nth_field_old(rec, 1, &len);
ut_a(len == 4);
/* The next field stores the field position in the index
@ -503,10 +505,9 @@ dict_load_fields(
ut_a(0 == ut_strcmp("COL_NAME",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_fields), 4))->name));
dict_index_get_nth_field(sys_index, 4))->name));
field = rec_get_nth_field(rec, 4, &len);
field = rec_get_nth_field_old(rec, 4, &len);
dict_mem_index_add_field(index,
mem_heap_strdupl(heap, (char*) field, len), 0, prefix_len);
@ -565,6 +566,7 @@ dict_load_indexes(
sys_indexes = dict_table_get_low("SYS_INDEXES");
sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
ut_a(!sys_indexes->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@ -585,14 +587,14 @@ dict_load_indexes(
rec = btr_pcur_get_rec(&pcur);
field = rec_get_nth_field(rec, 0, &len);
field = rec_get_nth_field_old(rec, 0, &len);
ut_ad(len == 8);
if (ut_memcmp(buf, field, len) != 0) {
break;
}
if (rec_get_deleted_flag(rec)) {
if (rec_get_deleted_flag(rec, table->comp)) {
dict_load_report_deleted_index(table->name,
ULINT_UNDEFINED);
@ -602,33 +604,31 @@ dict_load_indexes(
return(FALSE);
}
field = rec_get_nth_field(rec, 1, &len);
field = rec_get_nth_field_old(rec, 1, &len);
ut_ad(len == 8);
id = mach_read_from_8(field);
ut_a(0 == ut_strcmp("NAME",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_indexes), 4))->name));
field = rec_get_nth_field(rec, 4, &name_len);
dict_index_get_nth_field(sys_index, 4))->name));
field = rec_get_nth_field_old(rec, 4, &name_len);
name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
field = rec_get_nth_field(rec, 5, &len);
field = rec_get_nth_field_old(rec, 5, &len);
n_fields = mach_read_from_4(field);
field = rec_get_nth_field(rec, 6, &len);
field = rec_get_nth_field_old(rec, 6, &len);
type = mach_read_from_4(field);
field = rec_get_nth_field(rec, 7, &len);
field = rec_get_nth_field_old(rec, 7, &len);
space = mach_read_from_4(field);
ut_a(0 == ut_strcmp("PAGE_NO",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_indexes), 8))->name));
dict_index_get_nth_field(sys_index, 8))->name));
field = rec_get_nth_field(rec, 8, &len);
field = rec_get_nth_field_old(rec, 8, &len);
page_no = mach_read_from_4(field);
if (page_no == FIL_NULL) {
@ -731,6 +731,7 @@ dict_load_table(
sys_tables = dict_table_get_low("SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
ut_a(!sys_tables->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@ -743,7 +744,7 @@ dict_load_table(
rec = btr_pcur_get_rec(&pcur);
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
|| rec_get_deleted_flag(rec)) {
|| rec_get_deleted_flag(rec, sys_tables->comp)) {
/* Not found */
btr_pcur_close(&pcur);
@ -753,7 +754,7 @@ dict_load_table(
return(NULL);
}
field = rec_get_nth_field(rec, 0, &len);
field = rec_get_nth_field_old(rec, 0, &len);
/* Check if the table name in record is the searched one */
if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
@ -767,10 +768,9 @@ dict_load_table(
ut_a(0 == ut_strcmp("SPACE",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_tables), 9))->name));
dict_index_get_nth_field(sys_index, 9))->name));
field = rec_get_nth_field(rec, 9, &len);
field = rec_get_nth_field_old(rec, 9, &len);
space = mach_read_from_4(field);
/* Check if the tablespace exists and has the right name */
@ -792,43 +792,45 @@ dict_load_table(
ut_a(0 == ut_strcmp("N_COLS",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_tables), 4))->name));
dict_index_get_nth_field(sys_index, 4))->name));
field = rec_get_nth_field(rec, 4, &len);
field = rec_get_nth_field_old(rec, 4, &len);
n_cols = mach_read_from_4(field);
table = dict_mem_table_create(name, space, n_cols);
/* table->comp will be initialized later, in this function */
table = dict_mem_table_create(name, space, n_cols, FALSE);
table->ibd_file_missing = ibd_file_missing;
ut_a(0 == ut_strcmp("ID",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_tables), 3))->name));
dict_index_get_nth_field(sys_index, 3))->name));
field = rec_get_nth_field(rec, 3, &len);
field = rec_get_nth_field_old(rec, 3, &len);
table->id = mach_read_from_8(field);
field = rec_get_nth_field(rec, 5, &len);
field = rec_get_nth_field_old(rec, 5, &len);
table->type = mach_read_from_4(field);
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
ut_error;
#if 0 /* clustered tables have not been implemented yet */
field = rec_get_nth_field(rec, 6, &len);
field = rec_get_nth_field_old(rec, 6, &len);
table->mix_id = mach_read_from_8(field);
field = rec_get_nth_field(rec, 8, &len);
field = rec_get_nth_field_old(rec, 8, &len);
table->cluster_name = mem_heap_strdupl(heap, (char*) field, len);
#endif
}
/* The high-order bit of MIX_LEN is the "compact format" flag */
field = rec_get_nth_field_old(rec, 7, &len);
table->comp = !!(mach_read_from_1(field) & 0x80);
if ((table->type == DICT_TABLE_CLUSTER)
|| (table->type == DICT_TABLE_CLUSTER_MEMBER)) {
field = rec_get_nth_field(rec, 7, &len);
table->mix_len = mach_read_from_4(field);
table->mix_len = mach_read_from_4(field) & 0x7fffffff;
}
btr_pcur_close(&pcur);
@ -906,6 +908,7 @@ dict_load_table_on_id(
sys_tables = dict_sys->sys_tables;
sys_table_ids = dict_table_get_next_index(
dict_table_get_first_index(sys_tables));
ut_a(!sys_tables->comp);
heap = mem_heap_create(256);
tuple = dtuple_create(heap, 1);
@ -922,7 +925,7 @@ dict_load_table_on_id(
rec = btr_pcur_get_rec(&pcur);
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
|| rec_get_deleted_flag(rec)) {
|| rec_get_deleted_flag(rec, sys_tables->comp)) {
/* Not found */
btr_pcur_close(&pcur);
@ -937,7 +940,7 @@ dict_load_table_on_id(
table ID and NAME */
rec = btr_pcur_get_rec(&pcur);
field = rec_get_nth_field(rec, 0, &len);
field = rec_get_nth_field_old(rec, 0, &len);
ut_ad(len == 8);
/* Check if the table id in record is the one searched for */
@ -951,7 +954,7 @@ dict_load_table_on_id(
}
/* Now we get the table name from the record */
field = rec_get_nth_field(rec, 1, &len);
field = rec_get_nth_field_old(rec, 1, &len);
/* Load the table definition to memory */
table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len));
@ -1019,6 +1022,7 @@ dict_load_foreign_cols(
sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
ut_a(!sys_foreign_cols->comp);
tuple = dtuple_create(foreign->heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@ -1033,21 +1037,21 @@ dict_load_foreign_cols(
rec = btr_pcur_get_rec(&pcur);
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
ut_a(!rec_get_deleted_flag(rec));
field = rec_get_nth_field(rec, 0, &len);
ut_a(!rec_get_deleted_flag(rec, sys_foreign_cols->comp));
field = rec_get_nth_field_old(rec, 0, &len);
ut_a(len == ut_strlen(id));
ut_a(ut_memcmp(id, field, len) == 0);
field = rec_get_nth_field(rec, 1, &len);
field = rec_get_nth_field_old(rec, 1, &len);
ut_a(len == 4);
ut_a(i == mach_read_from_4(field));
field = rec_get_nth_field(rec, 4, &len);
field = rec_get_nth_field_old(rec, 4, &len);
foreign->foreign_col_names[i] =
mem_heap_strdupl(foreign->heap, (char*) field, len);
field = rec_get_nth_field(rec, 5, &len);
field = rec_get_nth_field_old(rec, 5, &len);
foreign->referenced_col_names[i] =
mem_heap_strdupl(foreign->heap, (char*) field, len);
@ -1091,6 +1095,7 @@ dict_load_foreign(
sys_foreign = dict_table_get_low("SYS_FOREIGN");
sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
ut_a(!sys_foreign->comp);
tuple = dtuple_create(heap2, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@ -1103,7 +1108,7 @@ dict_load_foreign(
rec = btr_pcur_get_rec(&pcur);
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
|| rec_get_deleted_flag(rec)) {
|| rec_get_deleted_flag(rec, sys_foreign->comp)) {
/* Not found */
fprintf(stderr,
@ -1117,7 +1122,7 @@ dict_load_foreign(
return(DB_ERROR);
}
field = rec_get_nth_field(rec, 0, &len);
field = rec_get_nth_field_old(rec, 0, &len);
/* Check if the id in record is the searched one */
if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
@ -1140,7 +1145,8 @@ dict_load_foreign(
foreign = dict_mem_foreign_create();
foreign->n_fields = mach_read_from_4(rec_get_nth_field(rec, 5, &len));
foreign->n_fields =
mach_read_from_4(rec_get_nth_field_old(rec, 5, &len));
ut_a(len == 4);
@ -1151,11 +1157,11 @@ dict_load_foreign(
foreign->id = mem_heap_strdup(foreign->heap, id);
field = rec_get_nth_field(rec, 3, &len);
field = rec_get_nth_field_old(rec, 3, &len);
foreign->foreign_table_name =
mem_heap_strdupl(foreign->heap, (char*) field, len);
field = rec_get_nth_field(rec, 4, &len);
field = rec_get_nth_field_old(rec, 4, &len);
foreign->referenced_table_name =
mem_heap_strdupl(foreign->heap, (char*) field, len);
@ -1224,6 +1230,7 @@ dict_load_foreigns(
return(DB_ERROR);
}
ut_a(!sys_foreign->comp);
mtr_start(&mtr);
/* Get the secondary index based on FOR_NAME from table
@ -1255,7 +1262,7 @@ loop:
name and a foreign constraint ID */
rec = btr_pcur_get_rec(&pcur);
field = rec_get_nth_field(rec, 0, &len);
field = rec_get_nth_field_old(rec, 0, &len);
/* Check if the table name in the record is the one searched for; the
following call does the comparison in the latin1_swedish_ci
@ -1278,13 +1285,13 @@ loop:
goto next_rec;
}
if (rec_get_deleted_flag(rec)) {
if (rec_get_deleted_flag(rec, sys_foreign->comp)) {
goto next_rec;
}
/* Now we get a foreign key constraint id */
field = rec_get_nth_field(rec, 1, &len);
field = rec_get_nth_field_old(rec, 1, &len);
id = mem_heap_strdupl(heap, (char*) field, len);
btr_pcur_store_position(&pcur, &mtr);

View File

@ -35,7 +35,8 @@ dict_mem_table_create(
the table is placed; this parameter is
ignored if the table is made a member of
a cluster */
ulint n_cols) /* in: number of columns */
ulint n_cols, /* in: number of columns */
ibool comp) /* in: TRUE=compact page format */
{
dict_table_t* table;
mem_heap_t* heap;
@ -54,6 +55,7 @@ dict_mem_table_create(
table->space = space;
table->ibd_file_missing = FALSE;
table->tablespace_discarded = FALSE;
table->comp = comp;
table->n_def = 0;
table->n_cols = n_cols + DATA_N_SYS_COLS;
table->mem_fix = 0;
@ -110,7 +112,8 @@ dict_mem_cluster_create(
{
dict_table_t* cluster;
cluster = dict_mem_table_create(name, space, n_cols);
/* Clustered tables cannot work with the compact record format. */
cluster = dict_mem_table_create(name, space, n_cols, FALSE);
cluster->type = DICT_TABLE_CLUSTER;
cluster->mix_len = mix_len;
@ -197,7 +200,7 @@ dict_mem_index_create(
index->name = mem_heap_strdup(heap, index_name);
index->table_name = table_name;
index->table = NULL;
index->n_def = 0;
index->n_def = index->n_nullable = 0;
index->n_fields = n_fields;
index->fields = mem_heap_alloc(heap, 1 + n_fields
* sizeof(dict_field_t));

View File

@ -1579,30 +1579,38 @@ fil_op_write_log(
mtr_t* mtr) /* in: mini-transaction handle */
{
byte* log_ptr;
ulint len;
log_ptr = mlog_open(mtr, 11 + 2);
if (!log_ptr) {
/* Logging in mtr is switched off during crash recovery:
in that case mlog_open returns NULL */
return;
}
log_ptr = mlog_open(mtr, 30);
log_ptr = mlog_write_initial_log_record_for_file_op(type, space_id, 0,
log_ptr, mtr);
/* Let us store the strings as null-terminated for easier readability
and handling */
mach_write_to_2(log_ptr, ut_strlen(name) + 1);
len = strlen(name) + 1;
mach_write_to_2(log_ptr, len);
log_ptr += 2;
mlog_close(mtr, log_ptr);
mlog_catenate_string(mtr, (byte*) name, ut_strlen(name) + 1);
mlog_catenate_string(mtr, (byte*) name, len);
if (type == MLOG_FILE_RENAME) {
log_ptr = mlog_open(mtr, 30);
mach_write_to_2(log_ptr, ut_strlen(new_name) + 1);
ulint len = strlen(new_name) + 1;
log_ptr = mlog_open(mtr, 2 + len);
ut_a(log_ptr);
mach_write_to_2(log_ptr, len);
log_ptr += 2;
mlog_close(mtr, log_ptr);
mlog_catenate_string(mtr, (byte*) new_name,
ut_strlen(new_name) + 1);
mlog_catenate_string(mtr, (byte*) new_name, len);
}
}
#endif

View File

@ -910,7 +910,7 @@ fsp_header_init(
if (space == 0) {
fsp_fill_free_list(FALSE, space, header, mtr);
btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, space,
ut_dulint_add(DICT_IBUF_ID_MIN, space), mtr);
ut_dulint_add(DICT_IBUF_ID_MIN, space), FALSE, mtr);
} else {
fsp_fill_free_list(TRUE, space, header, mtr);
}

View File

@ -46,7 +46,7 @@ Note that contary to what we planned in the 1990's, there will only be one
insert buffer tree, and that is in the system tablespace of InnoDB.
1. The first field is the space id.
2. The second field is a one-byte marker which differentiates records from
2. The second field is a one-byte marker (0) which differentiates records from
the < 4.1.x storage format.
3. The third field is the page number.
4. The fourth field contains the type info, where we have also added 2 bytes to
@ -55,7 +55,14 @@ insert buffer tree, and that is in the system tablespace of InnoDB.
can use in the binary search on the index page in the ibuf merge phase.
5. The rest of the fields contain the fields of the actual index record.
*/
In versions >= 5.0.3:
The first byte of the fourth field is an additional marker (0) if the record
is in the compact format. The presence of this marker can be detected by
looking at the length of the field modulo DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE.
The high-order bit of the character set field in the type info is the
"nullable" flag for the field. */
/* PREVENTING DEADLOCKS IN THE INSERT BUFFER SYSTEM
@ -525,8 +532,8 @@ ibuf_data_init_for_space(
ibuf_exit();
sprintf(buf, "SYS_IBUF_TABLE_%lu", (ulong) space);
table = dict_mem_table_create(buf, space, 2);
/* use old-style record format for the insert buffer */
table = dict_mem_table_create(buf, space, 2, FALSE);
dict_mem_table_add_col(table, "PAGE_NO", DATA_BINARY, 0, 0, 0);
dict_mem_table_add_col(table, "TYPES", DATA_BINARY, 0, 0, 0);
@ -1049,20 +1056,20 @@ ibuf_rec_get_page_no(
ulint len;
ut_ad(ibuf_inside());
ut_ad(rec_get_n_fields(rec) > 2);
ut_ad(rec_get_n_fields_old(rec) > 2);
field = rec_get_nth_field(rec, 1, &len);
field = rec_get_nth_field_old(rec, 1, &len);
if (len == 1) {
/* This is of the >= 4.1.x record format */
ut_a(trx_sys_multiple_tablespace_format);
field = rec_get_nth_field(rec, 2, &len);
field = rec_get_nth_field_old(rec, 2, &len);
} else {
ut_a(trx_doublewrite_must_reset_space_ids);
ut_a(!trx_sys_multiple_tablespace_format);
field = rec_get_nth_field(rec, 0, &len);
field = rec_get_nth_field_old(rec, 0, &len);
}
ut_a(len == 4);
@ -1084,15 +1091,15 @@ ibuf_rec_get_space(
ulint len;
ut_ad(ibuf_inside());
ut_ad(rec_get_n_fields(rec) > 2);
ut_ad(rec_get_n_fields_old(rec) > 2);
field = rec_get_nth_field(rec, 1, &len);
field = rec_get_nth_field_old(rec, 1, &len);
if (len == 1) {
/* This is of the >= 4.1.x record format */
ut_a(trx_sys_multiple_tablespace_format);
field = rec_get_nth_field(rec, 0, &len);
field = rec_get_nth_field_old(rec, 0, &len);
ut_a(len == 4);
return(mach_read_from_4(field));
@ -1104,6 +1111,161 @@ ibuf_rec_get_space(
return(0);
}
/************************************************************************
Creates a dummy index for inserting a record to a non-clustered index.
*/
static
dict_index_t*
ibuf_dummy_index_create(
/*====================*/
/* out: dummy index */
ulint n, /* in: number of fields */
ibool comp) /* in: TRUE=use compact record format */
{
dict_table_t* table;
dict_index_t* index;
table = dict_mem_table_create("IBUF_DUMMY",
DICT_HDR_SPACE, n, comp);
index = dict_mem_index_create("IBUF_DUMMY", "IBUF_DUMMY",
DICT_HDR_SPACE, 0, n);
index->table = table;
/* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
index->cached = TRUE;
return(index);
}
/************************************************************************
Add a column to the dummy index */
static
void
ibuf_dummy_index_add_col(
/*====================*/
dict_index_t* index, /* in: dummy index */
dtype_t* type) /* in: the data type of the column */
{
ulint i = index->table->n_def;
dict_mem_table_add_col(index->table, "DUMMY",
dtype_get_mtype(type),
dtype_get_prtype(type),
dtype_get_len(type),
dtype_get_prec(type));
dict_index_add_col(index,
dict_table_get_nth_col(index->table, i), 0, 0);
}
/************************************************************************
Deallocates a dummy index for inserting a record to a non-clustered index.
*/
static
void
ibuf_dummy_index_free(
/*====================*/
dict_index_t* index) /* in: dummy index */
{
dict_table_t* table = index->table;
mem_heap_free(index->heap);
mutex_free(&(table->autoinc_mutex));
mem_heap_free(table->heap);
}
/*************************************************************************
Builds the entry to insert into a non-clustered index when we have the
corresponding record in an ibuf index. */
static
dtuple_t*
ibuf_build_entry_from_ibuf_rec(
/*===========================*/
/* out, own: entry to insert to
a non-clustered index; NOTE that
as we copy pointers to fields in
ibuf_rec, the caller must hold a
latch to the ibuf_rec page as long
as the entry is used! */
rec_t* ibuf_rec, /* in: record in an insert buffer */
mem_heap_t* heap, /* in: heap where built */
dict_index_t** pindex) /* out, own: dummy index that
describes the entry */
{
dtuple_t* tuple;
dfield_t* field;
ulint n_fields;
byte* types;
const byte* data;
ulint len;
ulint i;
dict_index_t* index;
data = rec_get_nth_field_old(ibuf_rec, 1, &len);
if (len > 1) {
/* This a < 4.1.x format record */
ut_a(trx_doublewrite_must_reset_space_ids);
ut_a(!trx_sys_multiple_tablespace_format);
n_fields = rec_get_n_fields_old(ibuf_rec) - 2;
tuple = dtuple_create(heap, n_fields);
types = rec_get_nth_field_old(ibuf_rec, 1, &len);
ut_a(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
for (i = 0; i < n_fields; i++) {
field = dtuple_get_nth_field(tuple, i);
data = rec_get_nth_field_old(ibuf_rec, i + 2, &len);
dfield_set_data(field, data, len);
dtype_read_for_order_and_null_size(
dfield_get_type(field),
types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
}
*pindex = ibuf_dummy_index_create(n_fields, FALSE);
return(tuple);
}
/* This a >= 4.1.x format record */
ut_a(trx_sys_multiple_tablespace_format);
ut_a(*data == 0);
ut_a(rec_get_n_fields_old(ibuf_rec) > 4);
n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
tuple = dtuple_create(heap, n_fields);
types = rec_get_nth_field_old(ibuf_rec, 3, &len);
ut_a(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE <= 1);
index = ibuf_dummy_index_create(n_fields,
len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
if (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) {
/* compact record format */
len--;
ut_a(*types == 0);
types++;
}
ut_a(len == n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
for (i = 0; i < n_fields; i++) {
field = dtuple_get_nth_field(tuple, i);
data = rec_get_nth_field_old(ibuf_rec, i + 4, &len);
dfield_set_data(field, data, len);
dtype_new_read_for_order_and_null_size(
dfield_get_type(field),
types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
ibuf_dummy_index_add_col(index, dfield_get_type(field));
}
*pindex = index;
return(tuple);
}
/************************************************************************
Returns the space taken by a stored non-clustered index entry if converted to
an index record. */
@ -1125,43 +1287,60 @@ ibuf_rec_get_volume(
ulint i;
ut_ad(ibuf_inside());
ut_ad(rec_get_n_fields(ibuf_rec) > 2);
data = rec_get_nth_field(ibuf_rec, 1, &len);
ut_ad(rec_get_n_fields_old(ibuf_rec) > 2);
data = rec_get_nth_field_old(ibuf_rec, 1, &len);
if (len > 1) {
/* < 4.1.x format record */
/* < 4.1.x format record */
ut_a(trx_doublewrite_must_reset_space_ids);
ut_a(!trx_sys_multiple_tablespace_format);
n_fields = rec_get_n_fields(ibuf_rec) - 2;
n_fields = rec_get_n_fields_old(ibuf_rec) - 2;
types = rec_get_nth_field(ibuf_rec, 1, &len);
types = rec_get_nth_field_old(ibuf_rec, 1, &len);
ut_ad(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
} else {
/* >= 4.1.x format record */
/* >= 4.1.x format record */
ut_a(trx_sys_multiple_tablespace_format);
ut_a(*data == 0);
types = rec_get_nth_field_old(ibuf_rec, 3, &len);
ut_a(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE <= 1);
if (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) {
/* compact record format */
ulint volume;
dict_index_t* dummy_index;
mem_heap_t* heap = mem_heap_create(500);
dtuple_t* entry =
ibuf_build_entry_from_ibuf_rec(
ibuf_rec, heap, &dummy_index);
volume = rec_get_converted_size(dummy_index, entry);
ibuf_dummy_index_free(dummy_index);
mem_heap_free(heap);
return(volume + page_dir_calc_reserved_space(1));
}
n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
new_format = TRUE;
n_fields = rec_get_n_fields(ibuf_rec) - 4;
types = rec_get_nth_field(ibuf_rec, 3, &len);
}
for (i = 0; i < n_fields; i++) {
if (new_format) {
data = rec_get_nth_field(ibuf_rec, i + 4, &len);
data = rec_get_nth_field_old(ibuf_rec, i + 4, &len);
dtype_new_read_for_order_and_null_size(&dtype,
types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
} else {
data = rec_get_nth_field(ibuf_rec, i + 2, &len);
data = rec_get_nth_field_old(ibuf_rec, i + 2, &len);
dtype_read_for_order_and_null_size(&dtype,
types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
}
if (len == UNIV_SQL_NULL) {
@ -1187,6 +1366,7 @@ ibuf_entry_build(
must be kept because we copy pointers to its
fields */
dtuple_t* entry, /* in: entry for a non-clustered index */
ibool comp, /* in: flag: TRUE=compact record format */
ulint space, /* in: space id */
ulint page_no,/* in: index page number where entry should
be inserted */
@ -1202,11 +1382,14 @@ ibuf_entry_build(
/* Starting from 4.1.x, we have to build a tuple whose
(1) first field is the space id,
(2) the second field a single marker byte to tell that this
(2) the second field a single marker byte (0) to tell that this
is a new format record,
(3) the third contains the page number, and
(4) the fourth contains the relevent type information of each data
field,
field; the length of this field % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE is
(a) 0 for b-trees in the old format, and
(b) 1 for b-trees in the compact format, the first byte of the field
being the marker (0);
(5) and the rest of the fields are copied from entry. All fields
in the tuple are ordered like the type binary in our insert buffer
tree. */
@ -1247,10 +1430,15 @@ ibuf_entry_build(
dfield_set_data(field, buf, 4);
ut_ad(comp == 0 || comp == 1);
/* Store the type info in buf2, and add the fields from entry to
tuple */
buf2 = mem_heap_alloc(heap, n_fields
* DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
* DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
+ comp);
if (comp) {
*buf2++ = 0; /* write the compact format indicator */
}
for (i = 0; i < n_fields; i++) {
/* We add 4 below because we have the 4 extra fields at the
start of an ibuf record */
@ -1268,8 +1456,13 @@ ibuf_entry_build(
field = dtuple_get_nth_field(tuple, 3);
if (comp) {
buf2--;
}
dfield_set_data(field, buf2, n_fields
* DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
* DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
+ comp);
/* Set all the types in the new tuple binary */
dtuple_set_types_binary(tuple, n_fields + 4);
@ -1277,88 +1470,6 @@ ibuf_entry_build(
return(tuple);
}
/*************************************************************************
Builds the entry to insert into a non-clustered index when we have the
corresponding record in an ibuf index. */
static
dtuple_t*
ibuf_build_entry_from_ibuf_rec(
/*===========================*/
/* out, own: entry to insert to
a non-clustered index; NOTE that
as we copy pointers to fields in
ibuf_rec, the caller must hold a
latch to the ibuf_rec page as long
as the entry is used! */
rec_t* ibuf_rec, /* in: record in an insert buffer */
mem_heap_t* heap) /* in: heap where built */
{
dtuple_t* tuple;
dfield_t* field;
ulint n_fields;
byte* types;
byte* data;
ulint len;
ulint i;
data = rec_get_nth_field(ibuf_rec, 1, &len);
if (len > 1) {
/* This a < 4.1.x format record */
ut_a(trx_doublewrite_must_reset_space_ids);
ut_a(!trx_sys_multiple_tablespace_format);
n_fields = rec_get_n_fields(ibuf_rec) - 2;
tuple = dtuple_create(heap, n_fields);
types = rec_get_nth_field(ibuf_rec, 1, &len);
ut_a(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
for (i = 0; i < n_fields; i++) {
field = dtuple_get_nth_field(tuple, i);
data = rec_get_nth_field(ibuf_rec, i + 2, &len);
dfield_set_data(field, data, len);
dtype_read_for_order_and_null_size(
dfield_get_type(field),
types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
}
return(tuple);
}
/* This a >= 4.1.x format record */
ut_a(trx_sys_multiple_tablespace_format);
ut_a(rec_get_n_fields(ibuf_rec) > 4);
n_fields = rec_get_n_fields(ibuf_rec) - 4;
tuple = dtuple_create(heap, n_fields);
types = rec_get_nth_field(ibuf_rec, 3, &len);
ut_a(len == n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
for (i = 0; i < n_fields; i++) {
field = dtuple_get_nth_field(tuple, i);
data = rec_get_nth_field(ibuf_rec, i + 4, &len);
dfield_set_data(field, data, len);
dtype_new_read_for_order_and_null_size(
dfield_get_type(field),
types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
}
return(tuple);
}
/*************************************************************************
Builds a search tuple used to search buffered inserts for an index page.
This is for < 4.1.x format records */
@ -2047,8 +2158,7 @@ loop:
mutex_exit(&ibuf_mutex);
sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur),
space_ids, space_versions, page_nos,
&n_stored);
space_ids, space_versions, page_nos, &n_stored);
#ifdef UNIV_IBUF_DEBUG
/* fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n",
sync, n_stored, sum_sizes); */
@ -2344,6 +2454,7 @@ ibuf_update_max_tablespace_id(void)
ibuf_data = fil_space_get_ibuf_data(0);
ibuf_index = ibuf_data->index;
ut_a(!ibuf_index->table->comp);
ibuf_enter();
@ -2360,7 +2471,7 @@ ibuf_update_max_tablespace_id(void)
} else {
rec = btr_pcur_get_rec(&pcur);
field = rec_get_nth_field(rec, 0, &len);
field = rec_get_nth_field_old(rec, 0, &len);
ut_a(len == 4);
@ -2479,7 +2590,7 @@ ibuf_insert_low(
ibuf_enter();
}
entry_size = rec_get_converted_size(entry);
entry_size = rec_get_converted_size(index, entry);
heap = mem_heap_create(512);
@ -2487,7 +2598,8 @@ ibuf_insert_low(
the first fields and the type information for other fields, and which
will be inserted to the insert buffer. */
ibuf_entry = ibuf_entry_build(entry, space, page_no, heap);
ibuf_entry = ibuf_entry_build(entry, index->table->comp,
space, page_no, heap);
/* Open a cursor to the insert buffer tree to calculate if we can add
the new entry to it without exceeding the free space limit for the
@ -2532,8 +2644,8 @@ ibuf_insert_low(
do_merge = TRUE;
ibuf_get_merge_page_nos(FALSE, btr_pcur_get_rec(&pcur),
space_ids, space_versions, page_nos,
&n_stored);
space_ids, space_versions,
page_nos, &n_stored);
goto function_exit;
}
@ -2656,8 +2768,8 @@ ibuf_insert(
ut_a(!(index->type & DICT_CLUSTERED));
if (rec_get_converted_size(entry)
>= page_get_free_space_of_empty() / 2) {
if (rec_get_converted_size(index, entry)
>= page_get_free_space_of_empty(index->table->comp) / 2) {
return(FALSE);
}
@ -2692,6 +2804,7 @@ ibuf_insert_to_index_page(
dtuple_t* entry, /* in: buffered entry to insert */
page_t* page, /* in: index page where the buffered entry
should be placed */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mtr */
{
page_cur_t page_cur;
@ -2699,17 +2812,28 @@ ibuf_insert_to_index_page(
rec_t* rec;
page_t* bitmap_page;
ulint old_bits;
mem_heap_t* heap;
ut_ad(ibuf_inside());
ut_ad(dtuple_check_typed(entry));
if (rec_get_n_fields(page_rec_get_next(page_get_infimum_rec(page)))
!= dtuple_get_n_fields(entry)) {
fprintf(stderr,
if (index->table->comp != page_is_comp(page)) {
fputs(
"InnoDB: Trying to insert a record from the insert buffer to an index page\n"
"InnoDB: but the number of fields does not match!\n");
"InnoDB: but the 'compact' flag does not match!\n", stderr);
goto dump;
}
heap = mem_heap_create(100);
rec = page_rec_get_next(page_get_infimum_rec(page));
if (rec_offs_n_fields(rec_get_offsets(rec, index, ULINT_UNDEFINED,
heap)) != dtuple_get_n_fields(entry)) {
mem_heap_free(heap);
fputs(
"InnoDB: Trying to insert a record from the insert buffer to an index page\n"
"InnoDB: but the number of fields does not match!\n", stderr);
dump:
buf_page_print(page);
dtuple_print(stderr, entry);
@ -2723,31 +2847,35 @@ ibuf_insert_to_index_page(
return;
}
low_match = page_cur_search(page, entry, PAGE_CUR_LE, &page_cur);
mem_heap_free(heap);
low_match = page_cur_search(page, index, entry,
PAGE_CUR_LE, &page_cur);
if (low_match == dtuple_get_n_fields(entry)) {
rec = page_cur_get_rec(&page_cur);
btr_cur_del_unmark_for_ibuf(rec, mtr);
btr_cur_del_unmark_for_ibuf(rec, index, mtr);
} else {
rec = page_cur_tuple_insert(&page_cur, entry, mtr);
rec = page_cur_tuple_insert(&page_cur, entry, index, mtr);
if (rec == NULL) {
/* If the record did not fit, reorganize */
btr_page_reorganize(page, mtr);
btr_page_reorganize(page, index, mtr);
page_cur_search(page, entry, PAGE_CUR_LE, &page_cur);
page_cur_search(page, index, entry,
PAGE_CUR_LE, &page_cur);
/* This time the record must fit */
if (!page_cur_tuple_insert(&page_cur, entry, mtr)) {
if (!page_cur_tuple_insert(&page_cur, entry,
index, mtr)) {
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Error: Insert buffer insert fails; page free %lu, dtuple size %lu\n",
(ulong) page_get_max_insert_size(page, 1),
(ulong) rec_get_converted_size(entry));
(ulong) rec_get_converted_size(index, entry));
fputs("InnoDB: Cannot insert index record ",
stderr);
dtuple_print(stderr, entry);
@ -2836,11 +2964,12 @@ ibuf_delete_rec(
"InnoDB: ibuf record inserted to page %lu\n", (ulong) page_no);
fflush(stderr);
rec_print(stderr, btr_pcur_get_rec(pcur));
rec_print(stderr, pcur->old_rec);
rec_print_old(stderr, btr_pcur_get_rec(pcur));
rec_print_old(stderr, pcur->old_rec);
dtuple_print(stderr, search_tuple);
rec_print(stderr, page_rec_get_next(btr_pcur_get_rec(pcur)));
rec_print_old(stderr,
page_rec_get_next(btr_pcur_get_rec(pcur)));
fflush(stderr);
btr_pcur_commit_specify_mtr(pcur, mtr);
@ -3075,7 +3204,7 @@ loop:
if (corruption_noticed) {
fputs("InnoDB: Discarding record\n ", stderr);
rec_print(stderr, ibuf_rec);
rec_print_old(stderr, ibuf_rec);
fputs("\n from the insert buffer!\n\n", stderr);
} else if (page) {
/* Now we have at pcur a record which should be
@ -3083,19 +3212,22 @@ loop:
copies pointers to fields in ibuf_rec, and we must
keep the latch to the ibuf_rec page until the
insertion is finished! */
dulint max_trx_id = page_get_max_trx_id(
dict_index_t* dummy_index;
dulint max_trx_id = page_get_max_trx_id(
buf_frame_align(ibuf_rec));
page_update_max_trx_id(page, max_trx_id);
entry = ibuf_build_entry_from_ibuf_rec(ibuf_rec, heap);
entry = ibuf_build_entry_from_ibuf_rec(ibuf_rec,
heap, &dummy_index);
#ifdef UNIV_IBUF_DEBUG
volume += rec_get_converted_size(entry)
volume += rec_get_converted_size(dummy_index, entry)
+ page_dir_calc_reserved_space(1);
ut_a(volume <= 4 * UNIV_PAGE_SIZE
/ IBUF_PAGE_SIZE_PER_FREE_SPACE);
#endif
ibuf_insert_to_index_page(entry, page, &mtr);
ibuf_insert_to_index_page(entry, page,
dummy_index, &mtr);
ibuf_dummy_index_free(dummy_index);
}
n_inserts++;

View File

@ -155,7 +155,8 @@ ulint
btr_node_ptr_get_child_page_no(
/*===========================*/
/* out: child node address */
rec_t* rec); /* in: node pointer record */
rec_t* rec, /* in: node pointer record */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/****************************************************************
Creates the root node for a new index tree. */
@ -167,6 +168,7 @@ btr_create(
ulint type, /* in: type of the index */
ulint space, /* in: space where created */
dulint index_id,/* in: index id */
ibool comp, /* in: TRUE=compact page format */
mtr_t* mtr); /* in: mini-transaction handle */
/****************************************************************
Frees a B-tree except the root page, which MUST be freed after this
@ -210,8 +212,9 @@ Reorganizes an index page. */
void
btr_page_reorganize(
/*================*/
page_t* page, /* in: page to be reorganized */
mtr_t* mtr); /* in: mtr */
page_t* page, /* in: page to be reorganized */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Decides if the page should be split at the convergence point of
inserts converging to left. */
@ -273,6 +276,7 @@ void
btr_set_min_rec_mark(
/*=================*/
rec_t* rec, /* in: record */
ibool comp, /* in: TRUE=compact page format */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes on the upper level the node pointer to a page. */
@ -332,6 +336,7 @@ btr_parse_set_min_rec_mark(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
ibool comp, /* in: TRUE=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
@ -340,11 +345,12 @@ Parses a redo log record of reorganizing a page. */
byte*
btr_parse_page_reorganize(
/*======================*/
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: record descriptor */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/******************************************************************
Gets the number of pages in a B-tree. */

View File

@ -183,17 +183,18 @@ ulint
btr_node_ptr_get_child_page_no(
/*===========================*/
/* out: child node address */
rec_t* rec) /* in: node pointer record */
rec_t* rec, /* in: node pointer record */
const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint n_fields;
byte* field;
ulint len;
ulint page_no;
n_fields = rec_get_n_fields(rec);
ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec));
/* The child address is in the last field */
field = rec_get_nth_field(rec, n_fields - 1, &len);
field = rec_get_nth_field(rec, offsets,
rec_offs_n_fields(offsets) - 1, &len);
ut_ad(len == 4);

View File

@ -34,7 +34,7 @@ page_cur_t*
btr_cur_get_page_cur(
/*=================*/
/* out: pointer to page cursor component */
btr_cur_t* cursor); /* in: tree cursor */
btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Returns the record pointer of a tree cursor. */
UNIV_INLINE
@ -42,14 +42,14 @@ rec_t*
btr_cur_get_rec(
/*============*/
/* out: pointer to record */
btr_cur_t* cursor); /* in: tree cursor */
btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Invalidates a tree cursor by setting record pointer to NULL. */
UNIV_INLINE
void
btr_cur_invalidate(
/*===============*/
btr_cur_t* cursor); /* in: tree cursor */
btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Returns the page of a tree cursor. */
UNIV_INLINE
@ -57,7 +57,7 @@ page_t*
btr_cur_get_page(
/*=============*/
/* out: pointer to page */
btr_cur_t* cursor); /* in: tree cursor */
btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Returns the tree of a cursor. */
UNIV_INLINE
@ -65,7 +65,7 @@ dict_tree_t*
btr_cur_get_tree(
/*=============*/
/* out: tree */
btr_cur_t* cursor); /* in: tree cursor */
btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Positions a tree cursor at a given record. */
UNIV_INLINE
@ -283,8 +283,9 @@ only used by the insert buffer insert merge mechanism. */
void
btr_cur_del_unmark_for_ibuf(
/*========================*/
rec_t* rec, /* in: record to delete unmark */
mtr_t* mtr); /* in: mtr */
rec_t* rec, /* in: record to delete unmark */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Tries to compress a page of the tree on the leaf level. It is assumed
that mtr holds an x-latch on the tree and on the cursor page. To avoid
@ -361,10 +362,11 @@ Parses a redo log record of updating a record in-place. */
byte*
btr_cur_parse_update_in_place(
/*==========================*/
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page); /* in: page or NULL */
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page, /* in: page or NULL */
dict_index_t* index); /* in: index corresponding to page */
/********************************************************************
Parses the redo log record for delete marking or unmarking of a clustered
index record. */
@ -372,10 +374,11 @@ index record. */
byte*
btr_cur_parse_del_mark_set_clust_rec(
/*=================================*/
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page); /* in: page or NULL */
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: index corresponding to page */
page_t* page); /* in: page or NULL */
/********************************************************************
Parses the redo log record for delete marking or unmarking of a secondary
index record. */
@ -383,10 +386,11 @@ index record. */
byte*
btr_cur_parse_del_mark_set_sec_rec(
/*===============================*/
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page); /* in: page or NULL */
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: index corresponding to page */
page_t* page); /* in: page or NULL */
/***********************************************************************
Estimates the number of rows in a given index range. */
@ -417,9 +421,10 @@ to free the field. */
void
btr_cur_mark_extern_inherited_fields(
/*=================================*/
rec_t* rec, /* in: record in a clustered index */
upd_t* update, /* in: update vector */
mtr_t* mtr); /* in: mtr */
rec_t* rec, /* in: record in a clustered index */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
upd_t* update, /* in: update vector */
mtr_t* mtr); /* in: mtr */
/***********************************************************************
The complement of the previous function: in an update entry may inherit
some externally stored fields from a record. We must mark them as inherited
@ -456,6 +461,7 @@ btr_store_big_rec_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree
MUST be X-latched */
rec_t* rec, /* in: record */
const ulint* offsets, /* in: rec_get_offsets(rec, index) */
big_rec_t* big_rec_vec, /* in: vector containing fields
to be stored externally */
mtr_t* local_mtr); /* in: mtr containing the latch to
@ -496,6 +502,7 @@ btr_rec_free_externally_stored_fields(
dict_index_t* index, /* in: index of the data, the index
tree MUST be X-latched */
rec_t* rec, /* in: record */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ibool do_not_free_inherited,/* in: TRUE if called in a
rollback and we do not want to free
inherited fields */
@ -510,6 +517,7 @@ btr_rec_copy_externally_stored_field(
/*=================================*/
/* out: the field copied to heap */
rec_t* rec, /* in: record */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint no, /* in: field number */
ulint* len, /* out: length of the field */
mem_heap_t* heap); /* in: mem heap */
@ -540,10 +548,10 @@ ulint
btr_push_update_extern_fields(
/*==========================*/
/* out: number of values stored in ext_vect */
ulint* ext_vect, /* in: array of ulints, must be preallocated
to have place for all fields in rec */
rec_t* rec, /* in: record */
upd_t* update); /* in: update vector */
ulint* ext_vect,/* in: array of ulints, must be preallocated
to have space for all fields in rec */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
upd_t* update);/* in: update vector or NULL */
/*######################################################################*/

View File

@ -134,17 +134,15 @@ btr_cur_can_delete_without_compress(
/* out: TRUE if can be deleted without
recommended compression */
btr_cur_t* cursor, /* in: btr cursor */
ulint rec_size,/* in: rec_get_size(btr_cur_get_rec(cursor))*/
mtr_t* mtr) /* in: mtr */
{
ulint rec_size;
page_t* page;
ut_ad(mtr_memo_contains(mtr, buf_block_align(
btr_cur_get_page(cursor)),
MTR_MEMO_PAGE_X_FIX));
rec_size = rec_get_size(btr_cur_get_rec(cursor));
page = btr_cur_get_page(cursor);
if ((page_get_data_size(page) - rec_size < BTR_CUR_PAGE_COMPRESS_LIMIT)

View File

@ -462,6 +462,7 @@ struct btr_pcur_struct{
contains an initial segment of the
latest record cursor was positioned
either on, before, or after */
ulint old_n_fields; /* number of fields in old_rec */
ulint rel_pos; /* BTR_PCUR_ON, BTR_PCUR_BEFORE, or
BTR_PCUR_AFTER, depending on whether
cursor was on, before, or after the

View File

@ -77,8 +77,10 @@ parameters as page (this often happens when a page is split). */
void
btr_search_move_or_delete_hash_entries(
/*===================================*/
page_t* new_page, /* in: records are copied to this page */
page_t* page); /* in: index page */
page_t* new_page, /* in: records are copied
to this page */
page_t* page, /* in: index page */
dict_index_t* index); /* in: record descriptor */
/************************************************************************
Drops a page hash index. */
@ -128,9 +130,10 @@ btr_search_update_hash_on_delete(
Validates the search system. */
ibool
btr_search_validate(void);
/*=====================*/
btr_search_validate(
/*================*/
/* out: TRUE if ok */
dict_index_t* index); /* in: record descriptor */
/* Search info directions */
#define BTR_SEA_NO_DIRECTION 1

View File

@ -149,8 +149,10 @@ dtype_new_store_for_order_and_null_size(
bytes where we store the info */
dtype_t* type) /* in: type struct */
{
ut_ad(6 == DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
#endif
buf[0] = (byte)(type->mtype & 0xFFUL);
if (type->prtype & DATA_BINARY_TYPE) {
@ -166,10 +168,12 @@ dtype_new_store_for_order_and_null_size(
mach_write_to_2(buf + 2, type->len & 0xFFFFUL);
ut_ad(dtype_get_charset_coll(type->prtype) < 256);
mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype));
/* Note that the second last byte is left unused, because the
charset-collation code is always < 256 */
if (type->prtype & DATA_NOT_NULL) {
buf[4] |= 128;
}
}
/**************************************************************************
@ -211,20 +215,26 @@ dtype_new_read_for_order_and_null_size(
{
ulint charset_coll;
ut_ad(6 == DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
#endif
type->mtype = buf[0] & 63;
type->prtype = buf[1];
if (buf[0] & 128) {
type->prtype = type->prtype | DATA_BINARY_TYPE;
type->prtype |= DATA_BINARY_TYPE;
}
if (buf[4] & 128) {
type->prtype |= DATA_NOT_NULL;
}
type->len = mach_read_from_2(buf + 2);
mach_read_from_2(buf + 4);
charset_coll = mach_read_from_2(buf + 4);
charset_coll = mach_read_from_2(buf + 4) & 0x7fff;
if (dtype_is_string_type(type->mtype)) {
ut_a(charset_coll < 256);
@ -257,6 +267,26 @@ dtype_get_fixed_size(
mtype = dtype_get_mtype(type);
switch (mtype) {
case DATA_SYS:
#ifdef UNIV_DEBUG
switch (type->prtype & DATA_MYSQL_TYPE_MASK) {
default:
ut_ad(0);
return(0);
case DATA_ROW_ID:
ut_ad(type->len == DATA_ROW_ID_LEN);
break;
case DATA_TRX_ID:
ut_ad(type->len == DATA_TRX_ID_LEN);
break;
case DATA_ROLL_PTR:
ut_ad(type->len == DATA_ROLL_PTR_LEN);
break;
case DATA_MIX_ID:
ut_ad(type->len == DATA_MIX_ID_LEN);
break;
}
#endif /* UNIV_DEBUG */
case DATA_CHAR:
case DATA_FIXBINARY:
case DATA_INT:
@ -264,16 +294,6 @@ dtype_get_fixed_size(
case DATA_DOUBLE:
case DATA_MYSQL:
return(dtype_get_len(type));
case DATA_SYS: if (type->prtype == DATA_ROW_ID) {
return(DATA_ROW_ID_LEN);
} else if (type->prtype == DATA_TRX_ID) {
return(DATA_TRX_ID_LEN);
} else if (type->prtype == DATA_ROLL_PTR) {
return(DATA_ROLL_PTR_LEN);
} else {
return(0);
}
case DATA_VARCHAR:
case DATA_BINARY:
case DATA_DECIMAL:

View File

@ -639,6 +639,16 @@ dict_index_get_sys_col_pos(
dict_index_t* index, /* in: index */
ulint type); /* in: DATA_ROW_ID, ... */
/***********************************************************************
Adds a column to index. */
void
dict_index_add_col(
/*===============*/
dict_index_t* index, /* in: index */
dict_col_t* col, /* in: column */
ulint order, /* in: order criterion */
ulint prefix_len); /* in: column prefix length */
/***********************************************************************
Copies types of fields contained in index to tuple. */
void
@ -657,6 +667,7 @@ dict_index_rec_get_sys_col(
/*=======================*/
/* out: system column value */
dict_index_t* index, /* in: clustered index describing the record */
const ulint* offsets,/* in: offsets returned by rec_get_offsets() */
ulint type, /* in: column type: DATA_ROLL_PTR, ... */
rec_t* rec); /* in: record */
/*************************************************************************
@ -770,6 +781,7 @@ dict_tree_copy_rec_order_prefix(
/* out: pointer to the prefix record */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to copy prefix */
ulint* n_fields,/* out: number of fields copied */
byte** buf, /* in/out: memory buffer for the copied prefix,
or NULL */
ulint* buf_size);/* in/out: buffer size */
@ -782,6 +794,7 @@ dict_tree_build_data_tuple(
/* out, own: data tuple */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to build data tuple */
ulint n_fields,/* in: number of data fields */
mem_heap_t* heap); /* in: memory heap where tuple created */
/*************************************************************************
Gets the space id of the root of the index tree. */

View File

@ -168,7 +168,7 @@ dict_table_get_sys_col(
col = dict_table_get_nth_col(table, table->n_cols
- DATA_N_SYS_COLS + sys);
ut_ad(col->type.mtype == DATA_SYS);
ut_ad(col->type.prtype == sys);
ut_ad(col->type.prtype == (sys | DATA_NOT_NULL));
return(col);
}
@ -322,6 +322,7 @@ dict_index_rec_get_sys_col(
/*=======================*/
/* out: system column value */
dict_index_t* index, /* in: clustered index describing the record */
const ulint* offsets,/* in: offsets returned by rec_get_offsets() */
ulint type, /* in: column type: DATA_ROLL_PTR, ... */
rec_t* rec) /* in: record */
{
@ -331,12 +332,13 @@ dict_index_rec_get_sys_col(
ut_ad(index);
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(rec_offs_validate(rec, index, offsets));
pos = dict_index_get_sys_col_pos(index, type);
ut_ad(pos != ULINT_UNDEFINED);
field = rec_get_nth_field(rec, pos, &len);
field = rec_get_nth_field(rec, offsets, pos, &len);
if (type == DATA_ROLL_PTR) {
ut_ad(len == 7);
@ -677,7 +679,10 @@ dict_is_mixed_table_rec(
byte* mix_id_field;
ulint len;
mix_id_field = rec_get_nth_field(rec, table->mix_len, &len);
ut_ad(!table->comp);
mix_id_field = rec_get_nth_field_old(rec,
table->mix_len, &len);
if ((len != table->mix_id_len)
|| (0 != ut_memcmp(table->mix_id_buf, mix_id_field, len))) {

View File

@ -54,7 +54,8 @@ dict_mem_table_create(
of the table is placed; this parameter
is ignored if the table is made
a member of a cluster */
ulint n_cols); /* in: number of columns */
ulint n_cols, /* in: number of columns */
ibool comp); /* in: TRUE=compact page format */
/**************************************************************************
Creates a cluster memory object. */
@ -171,6 +172,13 @@ struct dict_field_struct{
DICT_MAX_COL_PREFIX_LEN; NOTE that
in the UTF-8 charset, MySQL sets this
to 3 * the prefix len in UTF-8 chars */
ulint fixed_len; /* 0 or the fixed length of the
column if smaller than
DICT_MAX_COL_PREFIX_LEN */
ulint fixed_offs; /* offset to the field, or
ULINT_UNDEFINED if it is not fixed
within the record (due to preceding
variable-length fields) */
};
/* Data structure for an index tree */
@ -225,6 +233,7 @@ struct dict_index_struct{
ulint n_def; /* number of fields defined so far */
ulint n_fields;/* number of fields in the index */
dict_field_t* fields; /* array of field descriptions */
ulint n_nullable;/* number of nullable fields */
UT_LIST_NODE_T(dict_index_t)
indexes;/* list of indexes of the table */
dict_tree_t* tree; /* index tree struct */
@ -320,6 +329,7 @@ struct dict_table_struct{
ibool tablespace_discarded;/* this flag is set TRUE when the
user calls DISCARD TABLESPACE on this table,
and reset to FALSE in IMPORT TABLESPACE */
ibool comp; /* flag: TRUE=compact page format */
hash_node_t name_hash; /* hash chain node */
hash_node_t id_hash; /* hash chain node */
ulint n_def; /* number of columns defined so far */

View File

@ -47,7 +47,8 @@ lock_sec_rec_some_has_impl_off_kernel(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
dict_index_t* index); /* in: secondary index */
dict_index_t* index, /* in: secondary index */
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Checks if some transaction has an implicit x-lock on a record in a clustered
index. */
@ -58,7 +59,8 @@ lock_clust_rec_some_has_impl(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
dict_index_t* index); /* in: clustered index */
dict_index_t* index, /* in: clustered index */
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*****************************************************************
Resets the lock bits for a single record. Releases transactions
waiting for lock requests here. */
@ -275,6 +277,7 @@ lock_clust_rec_modify_check_and_lock(
does nothing */
rec_t* rec, /* in: record which should be modified */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
que_thr_t* thr); /* in: query thread */
/*************************************************************************
Checks if locks of other transactions prevent an immediate modify
@ -308,6 +311,7 @@ lock_sec_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: secondary index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@ -333,6 +337,7 @@ lock_clust_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@ -350,6 +355,7 @@ lock_clust_rec_cons_read_sees(
rec_t* rec, /* in: user record which should be read or
passed over by a read cursor */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
read_view_t* view); /* in: consistent read view */
/*************************************************************************
Checks that a non-clustered index record is seen in a consistent read. */
@ -499,6 +505,7 @@ lock_check_trx_id_sanity(
dulint trx_id, /* in: trx id */
rec_t* rec, /* in: user record */
dict_index_t* index, /* in: clustered index */
const ulint* offsets, /* in: rec_get_offsets(rec, index) */
ibool has_kernel_mutex);/* in: TRUE if the caller owns the
kernel mutex */
/*************************************************************************
@ -509,7 +516,8 @@ lock_rec_queue_validate(
/*====================*/
/* out: TRUE if ok */
rec_t* rec, /* in: record to look at */
dict_index_t* index); /* in: index, or NULL if not known */
dict_index_t* index, /* in: index, or NULL if not known */
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Prints info of a table lock. */

View File

@ -60,7 +60,8 @@ lock_clust_rec_some_has_impl(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
dict_index_t* index) /* in: clustered index */
dict_index_t* index, /* in: clustered index */
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
dulint trx_id;
@ -70,7 +71,7 @@ lock_clust_rec_some_has_impl(
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(page_rec_is_user_rec(rec));
trx_id = row_get_rec_trx_id(rec, index);
trx_id = row_get_rec_trx_id(rec, index, offsets);
if (trx_is_active(trx_id)) {
/* The modifying or inserting transaction is active */

View File

@ -11,6 +11,7 @@ Created 12/7/1995 Heikki Tuuri
#include "univ.i"
#include "mtr0mtr.h"
#include "dict0types.h"
/************************************************************
Writes 1 - 4 bytes to a file page buffered in the buffer pool.
@ -173,6 +174,38 @@ mlog_parse_string(
byte* page); /* in: page where to apply the log record, or NULL */
/************************************************************
Opens a buffer for mlog, writes the initial log record and,
if needed, the field lengths of an index. Reserves space
for further log entries. The log entry must be closed with
mtr_close(). */
byte*
mlog_open_and_write_index(
/*======================*/
/* out: buffer, NULL if log mode
MTR_LOG_NONE */
mtr_t* mtr, /* in: mtr */
byte* rec, /* in: index record or page */
dict_index_t* index, /* in: record descriptor */
byte type, /* in: log item type */
ulint size); /* in: requested buffer size in bytes
(if 0, calls mlog_close() and returns NULL) */
/************************************************************
Parses a log record written by mlog_open_and_write_index. */
byte*
mlog_parse_index(
/*=============*/
/* out: parsed record end,
NULL if not a complete record */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
/* out: new value of log_ptr */
ibool comp, /* in: TRUE=compact record format */
dict_index_t** index); /* out, own: dummy index */
/* Insert, update, and maybe other functions may use this value to define an
extra mlog buffer size for variable size data */
#define MLOG_BUF_MARGIN 256

View File

@ -102,7 +102,31 @@ flag value must give the length also! */
file rename */
#define MLOG_FILE_DELETE ((byte)35) /* log record about an .ibd
file deletion */
#define MLOG_BIGGEST_TYPE ((byte)35) /* biggest value (used in
#define MLOG_COMP_REC_MIN_MARK ((byte)36) /* mark a compact index record
as the predefined minimum
record */
#define MLOG_COMP_PAGE_CREATE ((byte)37) /* create a compact
index page */
#define MLOG_COMP_REC_INSERT ((byte)38) /* compact record insert */
#define MLOG_COMP_REC_CLUST_DELETE_MARK ((byte)39)
/* mark compact clustered index
record deleted */
#define MLOG_COMP_REC_SEC_DELETE_MARK ((byte)40)/* mark compact secondary index
record deleted */
#define MLOG_COMP_REC_UPDATE_IN_PLACE ((byte)41)/* update of a compact record,
preserves record field sizes */
#define MLOG_COMP_REC_DELETE ((byte)42) /* delete a compact record
from a page */
#define MLOG_COMP_LIST_END_DELETE ((byte)43) /* delete compact record list
end on index page */
#define MLOG_COMP_LIST_START_DELETE ((byte)44) /* delete compact record list
start on index page */
#define MLOG_COMP_LIST_END_COPY_CREATED ((byte)45)
/* copy compact record list end
to a new created index page */
#define MLOG_COMP_PAGE_REORGANIZE ((byte)46) /* reorganize an index page */
#define MLOG_BIGGEST_TYPE ((byte)46) /* biggest value (used in
asserts) */
/*******************************************************************

View File

@ -128,7 +128,8 @@ page_cur_tuple_insert(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
dtuple_t* tuple, /* in: pointer to a data tuple */
dtuple_t* tuple, /* in: pointer to a data tuple */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mini-transaction handle */
/***************************************************************
Inserts a record next to page cursor. Returns pointer to inserted record if
@ -142,6 +143,7 @@ page_cur_rec_insert(
otherwise */
page_cur_t* cursor, /* in: a page cursor */
rec_t* rec, /* in: record to insert */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mini-transaction handle */
/***************************************************************
Inserts a record next to page cursor. Returns pointer to inserted record if
@ -155,9 +157,9 @@ page_cur_insert_rec_low(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
ulint data_size,/* in: data size of tuple */
rec_t* rec, /* in: pointer to a physical record or NULL */
dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
dict_index_t* index, /* in: record descriptor */
rec_t* rec, /* in: pointer to a physical record or NULL */
mtr_t* mtr); /* in: mini-transaction handle */
/*****************************************************************
Copies records from page to a newly created page, from a given record onward,
@ -166,10 +168,11 @@ including that record. Infimum and supremum records are not copied. */
void
page_copy_rec_list_end_to_created_page(
/*===================================*/
page_t* new_page, /* in: index page to copy to */
page_t* page, /* in: index page */
rec_t* rec, /* in: first record to copy */
mtr_t* mtr); /* in: mtr */
page_t* new_page, /* in: index page to copy to */
page_t* page, /* in: index page */
rec_t* rec, /* in: first record to copy */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mtr */
/***************************************************************
Deletes a record at the page cursor. The cursor is moved to the
next record after the deleted one. */
@ -178,6 +181,7 @@ void
page_cur_delete_rec(
/*================*/
page_cur_t* cursor, /* in: a page cursor */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mini-transaction handle */
/********************************************************************
Searches the right position for a page cursor. */
@ -187,6 +191,7 @@ page_cur_search(
/*============*/
/* out: number of matched fields on the left */
page_t* page, /* in: index page */
dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@ -198,6 +203,7 @@ void
page_cur_search_with_match(
/*=======================*/
page_t* page, /* in: index page */
dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@ -229,34 +235,37 @@ Parses a log record of a record insert on a page. */
byte*
page_cur_parse_insert_rec(
/*======================*/
/* out: end of log record or NULL */
ibool is_short,/* in: TRUE if short inserts */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/* out: end of log record or NULL */
ibool is_short,/* in: TRUE if short inserts */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: record descriptor */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/**************************************************************
Parses a log record of copying a record list end to a new created page. */
byte*
page_parse_copy_rec_list_to_created_page(
/*=====================================*/
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: record descriptor */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
Parses log record of a record delete on a page. */
byte*
page_cur_parse_delete_rec(
/*======================*/
/* out: pointer to record end or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/* out: pointer to record end or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: record descriptor */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/* Index page cursor */

View File

@ -143,7 +143,7 @@ UNIV_INLINE
void
page_cur_move_to_prev(
/*==================*/
page_cur_t* cur) /* in: cursor; must not before first */
page_cur_t* cur) /* in: page cursor, not before first */
{
ut_ad(!page_cur_is_before_first(cur));
@ -158,6 +158,7 @@ page_cur_search(
/*============*/
/* out: number of matched fields on the left */
page_t* page, /* in: index page */
dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@ -170,7 +171,7 @@ page_cur_search(
ut_ad(dtuple_check_typed(tuple));
page_cur_search_with_match(page, tuple, mode,
page_cur_search_with_match(page, index, tuple, mode,
&up_matched_fields,
&up_matched_bytes,
&low_matched_fields,
@ -190,16 +191,11 @@ page_cur_tuple_insert(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
dtuple_t* tuple, /* in: pointer to a data tuple */
dtuple_t* tuple, /* in: pointer to a data tuple */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mini-transaction handle */
{
ulint data_size;
ut_ad(dtuple_check_typed(tuple));
data_size = dtuple_get_data_size(tuple);
return(page_cur_insert_rec_low(cursor, tuple, data_size, NULL, mtr));
return(page_cur_insert_rec_low(cursor, tuple, index, NULL, mtr));
}
/***************************************************************
@ -214,8 +210,9 @@ page_cur_rec_insert(
otherwise */
page_cur_t* cursor, /* in: a page cursor */
rec_t* rec, /* in: record to insert */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mini-transaction handle */
{
return(page_cur_insert_rec_low(cursor, NULL, 0, rec, mtr));
return(page_cur_insert_rec_low(cursor, NULL, index, rec, mtr));
}

View File

@ -37,7 +37,8 @@ typedef byte page_header_t;
/*-----------------------------*/
#define PAGE_N_DIR_SLOTS 0 /* number of slots in page directory */
#define PAGE_HEAP_TOP 2 /* pointer to record heap top */
#define PAGE_N_HEAP 4 /* number of records in the heap */
#define PAGE_N_HEAP 4 /* number of records in the heap,
bit 15=flag: new-style compact page format */
#define PAGE_FREE 6 /* pointer to start of page free record list */
#define PAGE_GARBAGE 8 /* number of bytes in deleted records */
#define PAGE_LAST_INSERT 10 /* pointer to the last inserted record, or
@ -79,15 +80,24 @@ typedef byte page_header_t;
#define PAGE_DATA (PAGE_HEADER + 36 + 2 * FSEG_HEADER_SIZE)
/* start of data on the page */
#define PAGE_INFIMUM (PAGE_DATA + 1 + REC_N_EXTRA_BYTES)
/* offset of the page infimum record on the
page */
#define PAGE_SUPREMUM (PAGE_DATA + 2 + 2 * REC_N_EXTRA_BYTES + 8)
/* offset of the page supremum record on the
page */
#define PAGE_SUPREMUM_END (PAGE_SUPREMUM + 9)
#define PAGE_OLD_INFIMUM (PAGE_DATA + 1 + REC_N_OLD_EXTRA_BYTES)
/* offset of the page infimum record on an
old-style page */
#define PAGE_OLD_SUPREMUM (PAGE_DATA + 2 + 2 * REC_N_OLD_EXTRA_BYTES + 8)
/* offset of the page supremum record on an
old-style page */
#define PAGE_OLD_SUPREMUM_END (PAGE_OLD_SUPREMUM + 9)
/* offset of the page supremum record end on
the page */
an old-style page */
#define PAGE_NEW_INFIMUM (PAGE_DATA + REC_N_NEW_EXTRA_BYTES)
/* offset of the page infimum record on a
new-style compact page */
#define PAGE_NEW_SUPREMUM (PAGE_DATA + 2 * REC_N_NEW_EXTRA_BYTES + 8)
/* offset of the page supremum record on a
new-style compact page */
#define PAGE_NEW_SUPREMUM_END (PAGE_NEW_SUPREMUM + 8)
/* offset of the page supremum record end on
a new-style compact page */
/*-----------------------------*/
/* Directions of cursor movement */
@ -233,6 +243,7 @@ page_cmp_dtuple_rec_with_match(
be page infimum or supremum, in which case
matched-parameter values below are not
affected */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns
contains the value for current comparison */
@ -259,6 +270,22 @@ page_rec_get_n_recs_before(
/* out: number of records */
rec_t* rec); /* in: the physical record */
/*****************************************************************
Gets the number of records in the heap. */
UNIV_INLINE
ulint
page_dir_get_n_heap(
/*================*/
/* out: number of user records */
page_t* page); /* in: index page */
/*****************************************************************
Sets the number of records in the heap. */
UNIV_INLINE
void
page_dir_set_n_heap(
/*================*/
page_t* page, /* in: index page */
ulint n_heap);/* in: number of records */
/*****************************************************************
Gets the number of dir slots in directory. */
UNIV_INLINE
ulint
@ -267,6 +294,15 @@ page_dir_get_n_slots(
/* out: number of slots */
page_t* page); /* in: index page */
/*****************************************************************
Sets the number of dir slots in directory. */
UNIV_INLINE
void
page_dir_set_n_slots(
/*=================*/
/* out: number of slots */
page_t* page, /* in: index page */
ulint n_slots);/* in: number of slots */
/*****************************************************************
Gets pointer to nth directory slot. */
UNIV_INLINE
page_dir_slot_t*
@ -333,7 +369,16 @@ ulint
page_dir_find_owner_slot(
/*=====================*/
/* out: the directory slot number */
rec_t* rec); /* in: the physical record */
rec_t* rec); /* in: the physical record */
/****************************************************************
Determine whether the page is in new-style compact format. */
UNIV_INLINE
ibool
page_is_comp(
/*=========*/
/* out: TRUE if the page is in compact format
FALSE if it is in old-style format */
page_t* page); /* in: index page */
/****************************************************************
Gets the pointer to the next record on the page. */
UNIV_INLINE
@ -359,9 +404,10 @@ UNIV_INLINE
rec_t*
page_rec_get_prev(
/*==============*/
/* out: pointer to previous record */
rec_t* rec); /* in: pointer to record, must not be page
infimum */
/* out: pointer to previous record */
rec_t* rec); /* in: pointer to record,
must not be page infimum */
/****************************************************************
TRUE if the record is a user record on the page. */
UNIV_INLINE
@ -446,9 +492,11 @@ page_get_max_insert_size_after_reorganize(
Calculates free space if a page is emptied. */
UNIV_INLINE
ulint
page_get_free_space_of_empty(void);
/*==============================*/
/* out: free space */
page_get_free_space_of_empty(
/*=========================*/
/* out: free space */
ibool comp) /* in: TRUE=compact page format */
__attribute__((const));
/****************************************************************
Returns the sum of the sizes of the records in the record list
excluding the infimum and supremum records. */
@ -464,20 +512,23 @@ Allocates a block of memory from an index page. */
byte*
page_mem_alloc(
/*===========*/
/* out: pointer to start of allocated
buffer, or NULL if allocation fails */
page_t* page, /* in: index page */
ulint need, /* in: number of bytes needed */
ulint* heap_no);/* out: this contains the heap number
of the allocated record if allocation succeeds */
/* out: pointer to start of allocated
buffer, or NULL if allocation fails */
page_t* page, /* in: index page */
ulint need, /* in: number of bytes needed */
dict_index_t* index, /* in: record descriptor */
ulint* heap_no);/* out: this contains the heap number
of the allocated record
if allocation succeeds */
/****************************************************************
Puts a record to free list. */
UNIV_INLINE
void
page_mem_free(
/*==========*/
page_t* page, /* in: index page */
rec_t* rec); /* in: pointer to the (origin of) record */
page_t* page, /* in: index page */
rec_t* rec, /* in: pointer to the (origin of) record */
dict_index_t* index); /* in: record descriptor */
/**************************************************************
The index page creation function. */
@ -487,7 +538,8 @@ page_create(
/* out: pointer to the page */
buf_frame_t* frame, /* in: a buffer frame where the page is
created */
mtr_t* mtr); /* in: mini-transaction handle */
mtr_t* mtr, /* in: mini-transaction handle */
ibool comp); /* in: TRUE=compact page format */
/*****************************************************************
Differs from page_copy_rec_list_end, because this function does not
touch the lock table and max trx id on page. */
@ -495,10 +547,11 @@ touch the lock table and max trx id on page. */
void
page_copy_rec_list_end_no_locks(
/*============================*/
page_t* new_page, /* in: index page to copy to */
page_t* page, /* in: index page */
rec_t* rec, /* in: record on page */
mtr_t* mtr); /* in: mtr */
page_t* new_page, /* in: index page to copy to */
page_t* page, /* in: index page */
rec_t* rec, /* in: record on page */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Copies records from page to new_page, from the given record onward,
including that record. Infimum and supremum records are not copied.
@ -507,10 +560,11 @@ The records are copied to the start of the record list on new_page. */
void
page_copy_rec_list_end(
/*===================*/
page_t* new_page, /* in: index page to copy to */
page_t* page, /* in: index page */
rec_t* rec, /* in: record on page */
mtr_t* mtr); /* in: mtr */
page_t* new_page, /* in: index page to copy to */
page_t* page, /* in: index page */
rec_t* rec, /* in: record on page */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Copies records from page to new_page, up to the given record, NOT
including that record. Infimum and supremum records are not copied.
@ -519,10 +573,11 @@ The records are copied to the end of the record list on new_page. */
void
page_copy_rec_list_start(
/*=====================*/
page_t* new_page, /* in: index page to copy to */
page_t* page, /* in: index page */
rec_t* rec, /* in: record on page */
mtr_t* mtr); /* in: mtr */
page_t* new_page, /* in: index page to copy to */
page_t* page, /* in: index page */
rec_t* rec, /* in: record on page */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes records from a page from a given record onward, including that record.
The infimum and supremum records are not deleted. */
@ -530,14 +585,15 @@ The infimum and supremum records are not deleted. */
void
page_delete_rec_list_end(
/*=====================*/
page_t* page, /* in: index page */
rec_t* rec, /* in: record on page */
ulint n_recs, /* in: number of records to delete, or ULINT_UNDEFINED
if not known */
ulint size, /* in: the sum of the sizes of the records in the end
of the chain to delete, or ULINT_UNDEFINED if not
known */
mtr_t* mtr); /* in: mtr */
page_t* page, /* in: index page */
rec_t* rec, /* in: record on page */
dict_index_t* index, /* in: record descriptor */
ulint n_recs, /* in: number of records to delete,
or ULINT_UNDEFINED if not known */
ulint size, /* in: the sum of the sizes of the
records in the end of the chain to
delete, or ULINT_UNDEFINED if not known */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes records from page, up to the given record, NOT including
that record. Infimum and supremum records are not deleted. */
@ -545,9 +601,10 @@ that record. Infimum and supremum records are not deleted. */
void
page_delete_rec_list_start(
/*=======================*/
page_t* page, /* in: index page */
rec_t* rec, /* in: record on page */
mtr_t* mtr); /* in: mtr */
page_t* page, /* in: index page */
rec_t* rec, /* in: record on page */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Moves record list end to another page. Moved records include
split_rec. */
@ -555,10 +612,11 @@ split_rec. */
void
page_move_rec_list_end(
/*===================*/
page_t* new_page, /* in: index page where to move */
page_t* page, /* in: index page */
rec_t* split_rec, /* in: first record to move */
mtr_t* mtr); /* in: mtr */
page_t* new_page, /* in: index page where to move */
page_t* page, /* in: index page */
rec_t* split_rec, /* in: first record to move */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Moves record list start to another page. Moved records do not include
split_rec. */
@ -566,10 +624,11 @@ split_rec. */
void
page_move_rec_list_start(
/*=====================*/
page_t* new_page, /* in: index page where to move */
page_t* page, /* in: index page */
rec_t* split_rec, /* in: first record not to move */
mtr_t* mtr); /* in: mtr */
page_t* new_page, /* in: index page where to move */
page_t* page, /* in: index page */
rec_t* split_rec, /* in: first record not to move */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mtr */
/********************************************************************
Splits a directory slot which owns too many records. */
@ -595,13 +654,16 @@ Parses a log record of a record list end or start deletion. */
byte*
page_parse_delete_rec_list(
/*=======================*/
/* out: end of log record or NULL */
byte type, /* in: MLOG_LIST_END_DELETE or
MLOG_LIST_START_DELETE */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/* out: end of log record or NULL */
byte type, /* in: MLOG_LIST_END_DELETE,
MLOG_LIST_START_DELETE,
MLOG_COMP_LIST_END_DELETE or
MLOG_COMP_LIST_START_DELETE */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: record descriptor */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
Parses a redo log record of creating a page. */
@ -611,6 +673,7 @@ page_parse_create(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
ibool comp, /* in: TRUE=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/****************************************************************
@ -620,7 +683,8 @@ the index page context. */
void
page_rec_print(
/*===========*/
rec_t* rec);
rec_t* rec, /* in: physical record */
const ulint* offsets);/* in: record descriptor */
/*******************************************************************
This is used to print the contents of the directory for
debugging purposes. */
@ -637,8 +701,9 @@ debugging purposes. */
void
page_print_list(
/*============*/
page_t* page, /* in: index page */
ulint pr_n); /* in: print n first and n last entries */
page_t* page, /* in: index page */
dict_index_t* index, /* in: dictionary index of the page */
ulint pr_n); /* in: print n first and n last entries */
/*******************************************************************
Prints the info in a page header. */
@ -653,9 +718,12 @@ debugging purposes. */
void
page_print(
/*======*/
page_t* page, /* in: index page */
ulint dn, /* in: print dn first and last entries in directory */
ulint rn); /* in: print rn first and last records on page */
page_t* page, /* in: index page */
dict_index_t* index, /* in: dictionary index of the page */
ulint dn, /* in: print dn first and last entries
in directory */
ulint rn); /* in: print rn first and last records
in directory */
/*******************************************************************
The following is used to validate a record on a page. This function
differs from rec_validate as it can also check the n_owned field and
@ -664,8 +732,9 @@ the heap_no field. */
ibool
page_rec_validate(
/*==============*/
/* out: TRUE if ok */
rec_t* rec); /* in: record on the page */
/* out: TRUE if ok */
rec_t* rec, /* in: physical record */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Checks that the first directory slot points to the infimum record and
the last to the supremum. This function is intended to track if the

View File

@ -73,7 +73,8 @@ page_header_set_field(
{
ut_ad(page);
ut_ad(field <= PAGE_N_RECS);
ut_ad(val < UNIV_PAGE_SIZE);
ut_ad(field == PAGE_N_HEAP || val < UNIV_PAGE_SIZE);
ut_ad(field != PAGE_N_HEAP || (val & 0x7fff) < UNIV_PAGE_SIZE);
mach_write_to_2(page + PAGE_HEADER + field, val);
}
@ -162,7 +163,11 @@ page_get_infimum_rec(
{
ut_ad(page);
return(page + PAGE_INFIMUM);
if (page_is_comp(page)) {
return(page + PAGE_NEW_INFIMUM);
} else {
return(page + PAGE_OLD_INFIMUM);
}
}
/****************************************************************
@ -176,7 +181,11 @@ page_get_supremum_rec(
{
ut_ad(page);
return(page + PAGE_SUPREMUM);
if (page_is_comp(page)) {
return(page + PAGE_NEW_SUPREMUM);
} else {
return(page + PAGE_OLD_SUPREMUM);
}
}
/****************************************************************
@ -309,6 +318,7 @@ page_cmp_dtuple_rec_with_match(
be page infimum or supremum, in which case
matched-parameter values below are not
affected */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns
contains the value for current comparison */
@ -320,6 +330,7 @@ page_cmp_dtuple_rec_with_match(
page_t* page;
ut_ad(dtuple_check_typed(dtuple));
ut_ad(rec_offs_validate(rec, NULL, offsets));
page = buf_frame_align(rec);
@ -328,7 +339,7 @@ page_cmp_dtuple_rec_with_match(
} else if (rec == page_get_supremum_rec(page)) {
return(-1);
} else {
return(cmp_dtuple_rec_with_match(dtuple, rec,
return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
matched_fields,
matched_bytes));
}
@ -358,6 +369,45 @@ page_dir_get_n_slots(
{
return(page_header_get_field(page, PAGE_N_DIR_SLOTS));
}
/*****************************************************************
Sets the number of dir slots in directory. */
UNIV_INLINE
void
page_dir_set_n_slots(
/*=================*/
/* out: number of slots */
page_t* page, /* in: index page */
ulint n_slots)/* in: number of slots */
{
page_header_set_field(page, PAGE_N_DIR_SLOTS, n_slots);
}
/*****************************************************************
Gets the number of records in the heap. */
UNIV_INLINE
ulint
page_dir_get_n_heap(
/*================*/
/* out: number of user records */
page_t* page) /* in: index page */
{
return(page_header_get_field(page, PAGE_N_HEAP) & 0x7fff);
}
/*****************************************************************
Sets the number of records in the heap. */
UNIV_INLINE
void
page_dir_set_n_heap(
/*================*/
page_t* page, /* in: index page */
ulint n_heap) /* in: number of records */
{
ut_ad(n_heap < 0x8000);
page_header_set_field(page, PAGE_N_HEAP, n_heap | (0x8000 &
page_header_get_field(page, PAGE_N_HEAP)));
}
/*****************************************************************
Gets pointer to nth directory slot. */
@ -369,7 +419,7 @@ page_dir_get_nth_slot(
page_t* page, /* in: index page */
ulint n) /* in: position */
{
ut_ad(page_header_get_field(page, PAGE_N_DIR_SLOTS) > n);
ut_ad(page_dir_get_n_slots(page) > n);
return(page + UNIV_PAGE_SIZE - PAGE_DIR
- (n + 1) * PAGE_DIR_SLOT_SIZE);
@ -431,7 +481,8 @@ page_dir_slot_get_n_owned(
/* out: number of records */
page_dir_slot_t* slot) /* in: page directory slot */
{
return(rec_get_n_owned(page_dir_slot_get_rec(slot)));
return(rec_get_n_owned(page_dir_slot_get_rec(slot),
page_is_comp(buf_frame_align(slot))));
}
/*******************************************************************
@ -444,7 +495,8 @@ page_dir_slot_set_n_owned(
ulint n) /* in: number of records owned
by the slot */
{
rec_set_n_owned(page_dir_slot_get_rec(slot), n);
rec_set_n_owned(page_dir_slot_get_rec(slot),
page_is_comp(buf_frame_align(slot)), n);
}
/****************************************************************
@ -461,6 +513,19 @@ page_dir_calc_reserved_space(
/ PAGE_DIR_SLOT_MIN_N_OWNED);
}
/****************************************************************
Determine whether the page is in new-style compact format. */
UNIV_INLINE
ibool
page_is_comp(
/*=========*/
/* out: TRUE if the page is in compact format
FALSE if it is in old-style format */
page_t* page) /* in: index page */
{
return(!!(page_header_get_field(page, PAGE_N_HEAP) & 0x8000));
}
/****************************************************************
Gets the pointer to the next record on the page. */
UNIV_INLINE
@ -477,7 +542,7 @@ page_rec_get_next(
page = buf_frame_align(rec);
offs = rec_get_next_offs(rec);
offs = rec_get_next_offs(rec, page_is_comp(page));
if (offs >= UNIV_PAGE_SIZE) {
fprintf(stderr,
@ -513,6 +578,7 @@ page_rec_set_next(
infimum */
{
page_t* page;
ulint offs;
ut_ad(page_rec_check(rec));
ut_a((next == NULL)
@ -523,11 +589,13 @@ page_rec_set_next(
ut_ad(rec != page_get_supremum_rec(page));
ut_ad(next != page_get_infimum_rec(page));
if (next == NULL) {
rec_set_next_offs(rec, 0);
if (next) {
offs = (ulint) (next - page);
} else {
rec_set_next_offs(rec, (ulint)(next - page));
offs = 0;
}
rec_set_next_offs(rec, page_is_comp(page), offs);
}
/****************************************************************
@ -545,6 +613,7 @@ page_rec_get_prev(
rec_t* rec2;
rec_t* prev_rec = NULL;
page_t* page;
ibool comp;
ut_ad(page_rec_check(rec));
@ -559,6 +628,7 @@ page_rec_get_prev(
slot = page_dir_get_nth_slot(page, slot_no - 1);
rec2 = page_dir_slot_get_rec(slot);
comp = page_is_comp(page);
while (rec != rec2) {
prev_rec = rec2;
@ -579,9 +649,12 @@ page_rec_find_owner_rec(
/* out: the owner record */
rec_t* rec) /* in: the physical record */
{
ut_ad(page_rec_check(rec));
ibool comp;
while (rec_get_n_owned(rec) == 0) {
ut_ad(page_rec_check(rec));
comp = page_is_comp(buf_frame_align(rec));
while (rec_get_n_owned(rec, comp) == 0) {
rec = page_rec_get_next(rec);
}
@ -601,7 +674,9 @@ page_get_data_size(
ulint ret;
ret = (ulint)(page_header_get_field(page, PAGE_HEAP_TOP)
- PAGE_SUPREMUM_END
- (page_is_comp(page)
? PAGE_NEW_SUPREMUM_END
: PAGE_OLD_SUPREMUM_END)
- page_header_get_field(page, PAGE_GARBAGE));
ut_ad(ret < UNIV_PAGE_SIZE);
@ -613,12 +688,13 @@ page_get_data_size(
Calculates free space if a page is emptied. */
UNIV_INLINE
ulint
page_get_free_space_of_empty(void)
/*==============================*/
page_get_free_space_of_empty(
/*=========================*/
/* out: free space */
ibool comp) /* in: TRUE=compact page layout */
{
return((ulint)(UNIV_PAGE_SIZE
- PAGE_SUPREMUM_END
- (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END)
- PAGE_DIR
- 2 * PAGE_DIR_SLOT_SIZE));
}
@ -640,13 +716,16 @@ page_get_max_insert_size(
{
ulint occupied;
ulint free_space;
ibool comp;
comp = page_is_comp(page);
occupied = page_header_get_field(page, PAGE_HEAP_TOP)
- PAGE_SUPREMUM_END
- (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END)
+ page_dir_calc_reserved_space(
n_recs + (page_header_get_field(page, PAGE_N_HEAP) - 2));
n_recs + page_dir_get_n_heap(page) - 2);
free_space = page_get_free_space_of_empty();
free_space = page_get_free_space_of_empty(comp);
/* Above the 'n_recs +' part reserves directory space for the new
inserted records; the '- 2' excludes page infimum and supremum
@ -673,11 +752,14 @@ page_get_max_insert_size_after_reorganize(
{
ulint occupied;
ulint free_space;
ibool comp;
comp = page_is_comp(page);
occupied = page_get_data_size(page)
+ page_dir_calc_reserved_space(n_recs + page_get_n_recs(page));
free_space = page_get_free_space_of_empty();
free_space = page_get_free_space_of_empty(comp);
if (occupied > free_space) {
@ -693,11 +775,12 @@ UNIV_INLINE
void
page_mem_free(
/*==========*/
page_t* page, /* in: index page */
rec_t* rec) /* in: pointer to the (origin of) record */
page_t* page, /* in: index page */
rec_t* rec, /* in: pointer to the (origin of) record */
dict_index_t* index) /* in: record descriptor */
{
rec_t* free;
ulint garbage;
rec_t* free;
ulint garbage;
free = page_header_get_ptr(page, PAGE_FREE);
@ -707,7 +790,7 @@ page_mem_free(
garbage = page_header_get_field(page, PAGE_GARBAGE);
page_header_set_field(page, PAGE_GARBAGE,
garbage + rec_get_size(rec));
garbage + rec_get_size(rec, index));
}
#ifdef UNIV_MATERIALIZE

View File

@ -90,6 +90,7 @@ cmp_dtuple_rec_with_match(
dtuple in some of the common fields, or which
has an equal number or more fields than
dtuple */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns,
contains the value for current comparison */
@ -107,7 +108,8 @@ cmp_dtuple_rec(
less than rec, respectively; see the comments
for cmp_dtuple_rec_with_match */
dtuple_t* dtuple, /* in: data tuple */
rec_t* rec); /* in: physical record */
rec_t* rec, /* in: physical record */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/******************************************************************
Checks if a dtuple is a prefix of a record. The last field in dtuple
is allowed to be a prefix of the corresponding field in the record. */
@ -116,23 +118,9 @@ ibool
cmp_dtuple_is_prefix_of_rec(
/*========================*/
/* out: TRUE if prefix */
dtuple_t* dtuple, /* in: data tuple */
rec_t* rec); /* in: physical record */
/******************************************************************
Compares a prefix of a data tuple to a prefix of a physical record for
equality. If there are less fields in rec than parameter n_fields, FALSE
is returned. NOTE that n_fields_cmp of dtuple does not affect this
comparison. */
ibool
cmp_dtuple_rec_prefix_equal(
/*========================*/
/* out: TRUE if equal */
dtuple_t* dtuple, /* in: data tuple */
rec_t* rec, /* in: physical record */
ulint n_fields); /* in: number of fields which should be
compared; must not exceed the number of
fields in dtuple */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*****************************************************************
This function is used to compare two physical records. Only the common
first fields are compared, and if an externally stored field is
@ -146,7 +134,13 @@ cmp_rec_rec_with_match(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
dict_index_t* index, /* in: data dictionary index */
ulint n, /* in: number of fields to compare,
or ULINT_UNDEFINED if both records
contain all fields, and all fields
should be compared */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when the function returns,
contains the value the for current
@ -167,6 +161,12 @@ cmp_rec_rec(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
ulint n, /* in: number of fields to compare,
or ULINT_UNDEFINED if both records
contain all fields, and all fields
should be compared */
dict_index_t* index); /* in: data dictionary index */

View File

@ -57,10 +57,14 @@ cmp_rec_rec(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
ulint n, /* in: number of fields to compare */
dict_index_t* index) /* in: data dictionary index */
{
ulint match_f = 0;
ulint match_b = 0;
return(cmp_rec_rec_with_match(rec1, rec2, index, &match_f, &match_b));
return(cmp_rec_rec_with_match(rec1, rec2, offsets1, offsets2, index, n,
&match_f, &match_b));
}

View File

@ -23,9 +23,18 @@ Created 5/30/1994 Heikki Tuuri
info bits of a record */
#define REC_INFO_MIN_REC_FLAG 0x10UL
/* Number of extra bytes in a record, in addition to the data and the
offsets */
#define REC_N_EXTRA_BYTES 6
/* Number of extra bytes in an old-style record,
in addition to the data and the offsets */
#define REC_N_OLD_EXTRA_BYTES 6
/* Number of extra bytes in a new-style record,
in addition to the data and the offsets */
#define REC_N_NEW_EXTRA_BYTES 5
/* Record status values */
#define REC_STATUS_ORDINARY 0
#define REC_STATUS_NODE_PTR 1
#define REC_STATUS_INFIMUM 2
#define REC_STATUS_SUPREMUM 3
/**********************************************************
The following function is used to get the offset of the
@ -36,7 +45,8 @@ rec_get_next_offs(
/*==============*/
/* out: the page offset of the next
chained record */
rec_t* rec); /* in: physical record */
rec_t* rec, /* in: physical record */
ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the next record offset field
of the record. */
@ -45,14 +55,15 @@ void
rec_set_next_offs(
/*==============*/
rec_t* rec, /* in: physical record */
ibool comp, /* in: TRUE=compact page format */
ulint next); /* in: offset of the next record */
/**********************************************************
The following function is used to get the number of fields
in the record. */
in an old-style record. */
UNIV_INLINE
ulint
rec_get_n_fields(
/*=============*/
rec_get_n_fields_old(
/*=================*/
/* out: number of data fields */
rec_t* rec); /* in: physical record */
/**********************************************************
@ -63,7 +74,8 @@ ulint
rec_get_n_owned(
/*============*/
/* out: number of owned records */
rec_t* rec); /* in: physical record */
rec_t* rec, /* in: physical record */
ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the number of owned
records. */
@ -72,6 +84,7 @@ void
rec_set_n_owned(
/*============*/
rec_t* rec, /* in: physical record */
ibool comp, /* in: TRUE=compact page format */
ulint n_owned); /* in: the number of owned */
/**********************************************************
The following function is used to retrieve the info bits of
@ -81,7 +94,8 @@ ulint
rec_get_info_bits(
/*==============*/
/* out: info bits */
rec_t* rec); /* in: physical record */
rec_t* rec, /* in: physical record */
ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the info bits of a record. */
UNIV_INLINE
@ -89,15 +103,26 @@ void
rec_set_info_bits(
/*==============*/
rec_t* rec, /* in: physical record */
ibool comp, /* in: TRUE=compact page format */
ulint bits); /* in: info bits */
/**********************************************************
Gets the value of the deleted falg in info bits. */
The following function retrieves the status bits of a new-style record. */
UNIV_INLINE
ibool
rec_info_bits_get_deleted_flag(
/*===========================*/
/* out: TRUE if deleted flag set */
ulint info_bits); /* in: info bits from a record */
ulint
rec_get_status(
/*===========*/
/* out: status bits */
rec_t* rec); /* in: physical record */
/**********************************************************
The following function is used to set the status bits of a new-style record. */
UNIV_INLINE
void
rec_set_status(
/*===========*/
rec_t* rec, /* in: physical record */
ulint bits); /* in: info bits */
/**********************************************************
The following function tells if record is delete marked. */
UNIV_INLINE
@ -105,7 +130,8 @@ ibool
rec_get_deleted_flag(
/*=================*/
/* out: TRUE if delete marked */
rec_t* rec); /* in: physical record */
rec_t* rec, /* in: physical record */
ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the deleted bit. */
UNIV_INLINE
@ -113,8 +139,25 @@ void
rec_set_deleted_flag(
/*=================*/
rec_t* rec, /* in: physical record */
ibool comp, /* in: TRUE=compact page format */
ibool flag); /* in: TRUE if delete marked */
/**********************************************************
The following function tells if a new-style record is a node pointer. */
UNIV_INLINE
ibool
rec_get_node_ptr_flag(
/*=================*/
/* out: TRUE if node pointer */
rec_t* rec); /* in: physical record */
/**********************************************************
The following function is used to flag a record as a node pointer. */
UNIV_INLINE
void
rec_set_node_ptr_flag(
/*=================*/
rec_t* rec, /* in: physical record */
ibool flag); /* in: TRUE if the record is a node pointer */
/**********************************************************
The following function is used to get the order number
of the record in the heap of the index page. */
UNIV_INLINE
@ -122,7 +165,8 @@ ulint
rec_get_heap_no(
/*=============*/
/* out: heap order number */
rec_t* rec); /* in: physical record */
rec_t* rec, /* in: physical record */
ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the heap number
field in the record. */
@ -131,6 +175,7 @@ void
rec_set_heap_no(
/*=============*/
rec_t* rec, /* in: physical record */
ibool comp, /* in: TRUE=compact page format */
ulint heap_no);/* in: the heap number */
/**********************************************************
The following function is used to test whether the data offsets
@ -141,31 +186,84 @@ rec_get_1byte_offs_flag(
/*====================*/
/* out: TRUE if 1-byte form */
rec_t* rec); /* in: physical record */
/**********************************************************
The following function determines the offsets to each field
in the record. The offsets are returned in an array of
ulint, with [0] being the number of fields (n), [1] being the
extra size (if REC_OFFS_COMPACT is set, the record is in the new
format), and [2]..[n+1] being the offsets past the end of
fields 0..n, or to the beginning of fields 1..n+1. When the
high-order bit of the offset at [n+1] is set (REC_OFFS_SQL_NULL),
the field n is NULL. When the second high-order bit of the offset
at [n+1] is set (REC_OFFS_EXTERNAL), the field n is being stored
externally. */
ulint*
rec_get_offsets(
/*============*/
/* out: the offsets */
rec_t* rec, /* in: physical record */
dict_index_t* index, /* in: record descriptor */
ulint n_fields,/* in: maximum number of initialized fields
(ULINT_UNDEFINED if all fields) */
mem_heap_t* heap); /* in: memory heap */
/**********************************************************
The following function determines the offsets to each field
in the record. It differs from rec_get_offsets() by trying to
reuse a previously returned array. */
ulint*
rec_reget_offsets(
/*==============*/
/* out: the new offsets */
rec_t* rec, /* in: physical record */
dict_index_t* index, /* in: record descriptor */
ulint* offsets,/* in: array of offsets
from rec_get_offsets()
or rec_reget_offsets(), or NULL */
ulint n_fields,/* in: maximum number of initialized fields
(ULINT_UNDEFINED if all fields) */
mem_heap_t* heap); /* in: memory heap */
/****************************************************************
Validates offsets returned by rec_get_offsets() or rec_reget_offsets(). */
UNIV_INLINE
ibool
rec_offs_validate(
/*==============*/
/* out: TRUE if valid */
rec_t* rec, /* in: record or NULL */
dict_index_t* index, /* in: record descriptor or NULL */
const ulint* offsets);/* in: array returned by rec_get_offsets()
or rec_reget_offsets() */
/****************************************************************
Updates debug data in offsets, in order to avoid bogus
rec_offs_validate() failures. */
UNIV_INLINE
void
rec_offs_make_valid(
/*================*/
const rec_t* rec, /* in: record */
const dict_index_t* index,/* in: record descriptor */
ulint* offsets);/* in: array returned by rec_get_offsets()
or rec_reget_offsets() */
/****************************************************************
The following function is used to get a pointer to the nth
data field in the record. */
data field in an old-style record. */
byte*
rec_get_nth_field(
/*==============*/
rec_get_nth_field_old(
/*==================*/
/* out: pointer to the field */
rec_t* rec, /* in: record */
ulint n, /* in: index of the field */
ulint* len); /* out: length of the field; UNIV_SQL_NULL
if SQL null */
/****************************************************************
Return field length or UNIV_SQL_NULL. */
UNIV_INLINE
ulint
rec_get_nth_field_len(
/*==================*/
/* out: length of the field; UNIV_SQL_NULL if SQL
null */
rec_t* rec, /* in: record */
ulint n); /* in: index of the field */
/****************************************************************
Gets the physical size of a field. Also an SQL null may have a field of
size > 0, if the data type is of a fixed size. */
Gets the physical size of an old-style field.
Also an SQL null may have a field of size > 0,
if the data type is of a fixed size. */
UNIV_INLINE
ulint
rec_get_nth_field_size(
@ -173,131 +271,194 @@ rec_get_nth_field_size(
/* out: field size in bytes */
rec_t* rec, /* in: record */
ulint n); /* in: index of the field */
/***************************************************************
Gets the value of the ith field extern storage bit. If it is TRUE
it means that the field is stored on another page. */
/****************************************************************
The following function is used to get a pointer to the nth
data field in an old-style record. */
UNIV_INLINE
byte*
rec_get_nth_field(
/*==============*/
/* out: pointer to the field */
rec_t* rec, /* in: record */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint n, /* in: index of the field */
ulint* len); /* out: length of the field; UNIV_SQL_NULL
if SQL null */
/**********************************************************
Determine if the offsets are for a record in the new
compact format. */
UNIV_INLINE
ibool
rec_get_nth_field_extern_bit(
/*=========================*/
/* in: TRUE or FALSE */
rec_t* rec, /* in: record */
ulint i); /* in: ith field */
rec_offs_comp(
/*==========*/
/* out: TRUE if compact format */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**********************************************************
Returns TRUE if the nth field of rec is SQL NULL. */
UNIV_INLINE
ibool
rec_offs_nth_null(
/*==============*/
/* out: TRUE if SQL NULL */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint n); /* in: nth field */
/**********************************************************
Returns TRUE if the extern bit is set in nth field of rec. */
UNIV_INLINE
ibool
rec_offs_nth_extern(
/*================*/
/* out: TRUE if externally stored */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint n); /* in: nth field */
/**********************************************************
Gets the physical size of a field. */
UNIV_INLINE
ulint
rec_offs_nth_size(
/*==============*/
/* out: length of field */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint n); /* in: nth field */
/**********************************************************
Returns TRUE if the extern bit is set in any of the fields
of rec. */
UNIV_INLINE
ibool
rec_contains_externally_stored_field(
/*=================================*/
/* out: TRUE if a field is stored externally */
rec_t* rec); /* in: record */
rec_offs_any_extern(
/*================*/
/* out: TRUE if a field is stored externally */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/***************************************************************
Sets the value of the ith field extern storage bit. */
UNIV_INLINE
void
rec_set_nth_field_extern_bit(
/*=========================*/
rec_t* rec, /* in: record */
ulint i, /* in: ith field */
ibool val, /* in: value to set */
mtr_t* mtr); /* in: mtr holding an X-latch to the page where
rec is, or NULL; in the NULL case we do not
write to log about the change */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: record descriptor */
ulint i, /* in: ith field */
ibool val, /* in: value to set */
mtr_t* mtr); /* in: mtr holding an X-latch to the page
where rec is, or NULL; in the NULL case
we do not write to log about the change */
/***************************************************************
Sets TRUE the extern storage bits of fields mentioned in an array. */
void
rec_set_field_extern_bits(
/*======================*/
rec_t* rec, /* in: record */
ulint* vec, /* in: array of field numbers */
ulint n_fields, /* in: number of fields numbers */
mtr_t* mtr); /* in: mtr holding an X-latch to the page
where rec is, or NULL; in the NULL case we
do not write to log about the change */
/****************************************************************
The following function is used to get a copy of the nth
data field in the record to a buffer. */
UNIV_INLINE
void
rec_copy_nth_field(
/*===============*/
void* buf, /* in: pointer to the buffer */
rec_t* rec, /* in: record */
ulint n, /* in: index of the field */
ulint* len); /* out: length of the field; UNIV_SQL_NULL if SQL
null */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: record descriptor */
const ulint* vec, /* in: array of field numbers */
ulint n_fields,/* in: number of fields numbers */
mtr_t* mtr); /* in: mtr holding an X-latch to the page
where rec is, or NULL; in the NULL case
we do not write to log about the change */
/***************************************************************
This is used to modify the value of an already existing field in
a physical record. The previous value must have exactly the same
size as the new value. If len is UNIV_SQL_NULL then the field is
treated as SQL null. */
This is used to modify the value of an already existing field in a record.
The previous value must have exactly the same size as the new value. If len
is UNIV_SQL_NULL then the field is treated as an SQL null for old-style
records. For new-style records, len must not be UNIV_SQL_NULL. */
UNIV_INLINE
void
rec_set_nth_field(
/*==============*/
rec_t* rec, /* in: record */
ulint n, /* in: index of the field */
void* data, /* in: pointer to the data if not SQL null */
ulint len); /* in: length of the data or UNIV_SQL_NULL.
If not SQL null, must have the same length as the
previous value. If SQL null, previous value must be
SQL null. */
rec_t* rec, /* in: record */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint n, /* in: index number of the field */
const void* data, /* in: pointer to the data if not SQL null */
ulint len); /* in: length of the data or UNIV_SQL_NULL.
If not SQL null, must have the same
length as the previous value.
If SQL null, previous value must be
SQL null. */
/**************************************************************
The following function returns the data size of an old-style physical
record, that is the sum of field lengths. SQL null fields
are counted as length 0 fields. The value returned by the function
is the distance from record origin to record end in bytes. */
UNIV_INLINE
ulint
rec_get_data_size_old(
/*==================*/
/* out: size */
rec_t* rec); /* in: physical record */
/**************************************************************
The following function returns the number of fields in a record. */
UNIV_INLINE
ulint
rec_offs_n_fields(
/*===============*/
/* out: number of fields */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**************************************************************
The following function returns the data size of a physical
record, that is the sum of field lengths. SQL null fields
are counted as length 0 fields. The value returned by the function
is the distance from record origin to record end in bytes. */
UNIV_INLINE
ulint
rec_get_data_size(
/*==============*/
/* out: size */
rec_t* rec); /* in: physical record */
/**************************************************************
rec_offs_data_size(
/*===============*/
/* out: size */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**************************************************************
Returns the total size of record minus data size of record.
The value returned by the function is the distance from record
start to record origin in bytes. */
UNIV_INLINE
ulint
rec_get_extra_size(
/*===============*/
/* out: size */
rec_t* rec); /* in: physical record */
/**************************************************************
rec_offs_extra_size(
/*================*/
/* out: size */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**************************************************************
Returns the total size of a physical record. */
UNIV_INLINE
ulint
rec_offs_size(
/*==========*/
/* out: size */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**************************************************************
Returns the total size of a physical record. */
ulint
rec_get_size(
/*=========*/
/* out: size */
rec_t* rec); /* in: physical record */
/* out: size */
rec_t* rec, /* in: physical record */
dict_index_t* index); /* in: record descriptor */
/**************************************************************
Returns a pointer to the start of the record. */
UNIV_INLINE
byte*
rec_get_start(
/*==========*/
/* out: pointer to start */
rec_t* rec); /* in: pointer to record */
/* out: pointer to start */
rec_t* rec, /* in: pointer to record */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**************************************************************
Returns a pointer to the end of the record. */
UNIV_INLINE
byte*
rec_get_end(
/*========*/
/* out: pointer to end */
rec_t* rec); /* in: pointer to record */
/* out: pointer to end */
rec_t* rec, /* in: pointer to record */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Copies a physical record to a buffer. */
UNIV_INLINE
rec_t*
rec_copy(
/*=====*/
/* out: pointer to the origin of the copied record */
void* buf, /* in: buffer */
rec_t* rec); /* in: physical record */
/* out: pointer to the origin of the copy */
void* buf, /* in: buffer */
const rec_t* rec, /* in: physical record */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/******************************************************************
Copies the first n fields of a physical record to a new physical record in
a buffer. */
@ -305,49 +466,43 @@ a buffer. */
rec_t*
rec_copy_prefix_to_buf(
/*===================*/
/* out, own: copied record */
rec_t* rec, /* in: physical record */
ulint n_fields, /* in: number of fields to copy */
byte** buf, /* in/out: memory buffer for the copied prefix,
or NULL */
ulint* buf_size); /* in/out: buffer size */
/* out, own: copied record */
rec_t* rec, /* in: physical record */
dict_index_t* index, /* in: record descriptor */
ulint n_fields, /* in: number of fields to copy */
byte** buf, /* in/out: memory buffer
for the copied prefix, or NULL */
ulint* buf_size); /* in/out: buffer size */
/****************************************************************
Folds a prefix of a physical record to a ulint. */
UNIV_INLINE
ulint
rec_fold(
/*=====*/
/* out: the folded value */
rec_t* rec, /* in: the physical record */
ulint n_fields, /* in: number of complete fields to fold */
ulint n_bytes, /* in: number of bytes to fold in an
incomplete last field */
dulint tree_id); /* in: index tree id */
/*************************************************************
Builds a physical record out of a data tuple and stores it beginning from
address destination. */
UNIV_INLINE
rec_t*
rec_convert_dtuple_to_rec(
/*======================*/
/* out: pointer to the origin of physical
record */
byte* destination, /* in: start address of the physical record */
dtuple_t* dtuple); /* in: data tuple */
/* out: the folded value */
rec_t* rec, /* in: the physical record */
const ulint* offsets, /* in: array returned by
rec_get_offsets() */
ulint n_fields, /* in: number of complete
fields to fold */
ulint n_bytes, /* in: number of bytes to fold
in an incomplete last field */
dulint tree_id); /* in: index tree id */
/*************************************************************
Builds a physical record out of a data tuple and stores it beginning from
address destination. */
rec_t*
rec_convert_dtuple_to_rec_low(
/*==========================*/
/* out: pointer to the origin of physical
record */
byte* destination, /* in: start address of the physical record */
dtuple_t* dtuple, /* in: data tuple */
ulint data_size); /* in: data size of dtuple */
rec_convert_dtuple_to_rec(
/*======================*/
/* out: pointer to the origin
of physical record */
byte* buf, /* in: start address of the
physical record */
dict_index_t* index, /* in: record descriptor */
dtuple_t* dtuple);/* in: data tuple */
/**************************************************************
Returns the extra size of a physical record if we know its
Returns the extra size of an old-style physical record if we know its
data size and number of fields. */
UNIV_INLINE
ulint
@ -355,7 +510,8 @@ rec_get_converted_extra_size(
/*=========================*/
/* out: extra size */
ulint data_size, /* in: data size */
ulint n_fields); /* in: number of fields */
ulint n_fields) /* in: number of fields */
__attribute__((const));
/**************************************************************
The following function returns the size of a data tuple when converted to
a physical record. */
@ -364,6 +520,7 @@ ulint
rec_get_converted_size(
/*===================*/
/* out: size */
dict_index_t* index, /* in: record descriptor */
dtuple_t* dtuple);/* in: data tuple */
/******************************************************************
Copies the first n fields of a physical record to a data tuple.
@ -374,6 +531,7 @@ rec_copy_prefix_to_dtuple(
/*======================*/
dtuple_t* tuple, /* in: data tuple */
rec_t* rec, /* in: physical record */
dict_index_t* index, /* in: record descriptor */
ulint n_fields, /* in: number of fields to copy */
mem_heap_t* heap); /* in: memory heap */
/*******************************************************************
@ -382,16 +540,27 @@ Validates the consistency of a physical record. */
ibool
rec_validate(
/*=========*/
/* out: TRUE if ok */
rec_t* rec); /* in: physical record */
/* out: TRUE if ok */
rec_t* rec, /* in: physical record */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Prints an old-style physical record. */
void
rec_print_old(
/*==========*/
FILE* file, /* in: file where to print */
rec_t* rec); /* in: physical record */
/*******************************************************************
Prints a physical record. */
void
rec_print(
/*======*/
FILE* file, /* in: file where to print */
rec_t* rec); /* in: physical record */
FILE* file, /* in: file where to print */
rec_t* rec, /* in: physical record */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
#define REC_INFO_BITS 6 /* This is single byte bit-field */

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,8 @@ row_get_rec_trx_id(
/*===============*/
/* out: value of the field */
rec_t* rec, /* in: record */
dict_index_t* index); /* in: clustered index */
dict_index_t* index, /* in: clustered index */
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Reads the roll pointer field from a clustered index record. */
UNIV_INLINE
@ -36,7 +37,8 @@ row_get_rec_roll_ptr(
/*=================*/
/* out: value of the field */
rec_t* rec, /* in: record */
dict_index_t* index); /* in: clustered index */
dict_index_t* index, /* in: clustered index */
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Writes the trx id field to a clustered index record. */
UNIV_INLINE
@ -45,7 +47,8 @@ row_set_rec_trx_id(
/*===============*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
dulint trx_id); /* in: value of the field */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint trx_id);/* in: value of the field */
/*************************************************************************
Sets the roll pointer field in a clustered index record. */
UNIV_INLINE
@ -54,6 +57,7 @@ row_set_rec_roll_ptr(
/*=================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint roll_ptr);/* in: value of the field */
/*********************************************************************
When an insert to a table is performed, this function builds the entry which
@ -90,6 +94,9 @@ row_build(
the buffer page of this record must be
at least s-latched and the latch held
as long as the row dtuple is used! */
const ulint* offsets,/* in: rec_get_offsets(rec, index)
or NULL, in which case this function
will invoke rec_get_offsets() */
mem_heap_t* heap); /* in: memory heap from which the memory
needed is allocated */
/***********************************************************************
@ -175,14 +182,15 @@ UNIV_INLINE
void
row_build_row_ref_fast(
/*===================*/
dtuple_t* ref, /* in: typed data tuple where the reference
is built */
ulint* map, /* in: array of field numbers in rec telling
how ref should be built from the fields of
rec */
rec_t* rec); /* in: record in the index; must be preserved
while ref is used, as we do not copy field
values to heap */
dtuple_t* ref, /* in: typed data tuple where the
reference is built */
const ulint* map, /* in: array of field numbers in rec
telling how ref should be built from
the fields of rec */
rec_t* rec, /* in: record in the index; must be
preserved while ref is used, as we do
not copy field values to heap */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Searches the clustered index record for a row, if we have the row
reference. */

View File

@ -20,7 +20,8 @@ row_get_rec_sys_field(
/* out: value of the field */
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
dict_index_t* index); /* in: clustered index */
dict_index_t* index, /* in: clustered index */
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Sets the trx id or roll ptr field in a clustered index record: this function
is slower than the specialized inline functions. */
@ -32,6 +33,7 @@ row_set_rec_sys_field(
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint val); /* in: value to set */
/*************************************************************************
@ -42,18 +44,21 @@ row_get_rec_trx_id(
/*===============*/
/* out: value of the field */
rec_t* rec, /* in: record */
dict_index_t* index) /* in: clustered index */
dict_index_t* index, /* in: clustered index */
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
return(trx_read_trx_id(rec + offset));
} else {
return(row_get_rec_sys_field(DATA_TRX_ID, rec, index));
return(row_get_rec_sys_field(DATA_TRX_ID,
rec, index, offsets));
}
}
@ -65,18 +70,21 @@ row_get_rec_roll_ptr(
/*=================*/
/* out: value of the field */
rec_t* rec, /* in: record */
dict_index_t* index) /* in: clustered index */
dict_index_t* index, /* in: clustered index */
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
return(trx_read_roll_ptr(rec + offset + DATA_TRX_ID_LEN));
} else {
return(row_get_rec_sys_field(DATA_ROLL_PTR, rec, index));
return(row_get_rec_sys_field(DATA_ROLL_PTR,
rec, index, offsets));
}
}
@ -88,18 +96,21 @@ row_set_rec_trx_id(
/*===============*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint trx_id) /* in: value of the field */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
trx_write_trx_id(rec + offset, trx_id);
} else {
row_set_rec_sys_field(DATA_TRX_ID, rec, index, trx_id);
row_set_rec_sys_field(DATA_TRX_ID,
rec, index, offsets, trx_id);
}
}
@ -111,18 +122,21 @@ row_set_rec_roll_ptr(
/*=================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint roll_ptr)/* in: value of the field */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
trx_write_roll_ptr(rec + offset + DATA_TRX_ID_LEN, roll_ptr);
} else {
row_set_rec_sys_field(DATA_ROLL_PTR, rec, index, roll_ptr);
row_set_rec_sys_field(DATA_ROLL_PTR,
rec, index, offsets, roll_ptr);
}
}
@ -133,14 +147,15 @@ UNIV_INLINE
void
row_build_row_ref_fast(
/*===================*/
dtuple_t* ref, /* in: typed data tuple where the reference
is built */
ulint* map, /* in: array of field numbers in rec telling
how ref should be built from the fields of
rec */
rec_t* rec) /* in: record in the index; must be preserved
while ref is used, as we do not copy field
values to heap */
dtuple_t* ref, /* in: typed data tuple where the
reference is built */
const ulint* map, /* in: array of field numbers in rec
telling how ref should be built from
the fields of rec */
rec_t* rec, /* in: record in the index; must be
preserved while ref is used, as we do
not copy field values to heap */
const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
dfield_t* dfield;
byte* field;
@ -149,6 +164,7 @@ row_build_row_ref_fast(
ulint field_no;
ulint i;
ut_ad(rec_offs_validate(rec, NULL, offsets));
ref_len = dtuple_get_n_fields(ref);
for (i = 0; i < ref_len; i++) {
@ -158,7 +174,8 @@ row_build_row_ref_fast(
if (field_no != ULINT_UNDEFINED) {
field = rec_get_nth_field(rec, field_no, &len);
field = rec_get_nth_field(rec, offsets,
field_no, &len);
dfield_set_data(dfield, field, len);
}
}

View File

@ -80,6 +80,7 @@ row_upd_rec_sys_fields(
/*===================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
trx_t* trx, /* in: transaction */
dulint roll_ptr);/* in: roll ptr of the undo log record */
/*************************************************************************
@ -124,8 +125,8 @@ row_upd_changes_field_size_or_external(
/* out: TRUE if the update changes the size of
some field in index or the field is external
in rec or update */
rec_t* rec, /* in: record in index */
dict_index_t* index, /* in: index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
upd_t* update);/* in: update vector */
/***************************************************************
Replaces the new column values stored in the update vector to the record
@ -135,8 +136,9 @@ a clustered index */
void
row_upd_rec_in_place(
/*=================*/
rec_t* rec, /* in/out: record where replaced */
upd_t* update);/* in: update vector */
rec_t* rec, /* in/out: record where replaced */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
upd_t* update);/* in: update vector */
/*******************************************************************
Builds an update vector from those fields which in a secondary index entry
differ from a record that has the equal ordering fields. NOTE: we compare
@ -274,10 +276,11 @@ recovery. */
void
row_upd_rec_sys_fields_in_recovery(
/*===============================*/
rec_t* rec, /* in: record */
ulint pos, /* in: TRX_ID position in rec */
dulint trx_id, /* in: transaction id */
dulint roll_ptr);/* in: roll ptr of the undo log record */
rec_t* rec, /* in: record */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint pos, /* in: TRX_ID position in rec */
dulint trx_id, /* in: transaction id */
dulint roll_ptr);/* in: roll ptr of the undo log record */
/*************************************************************************
Parses the log data written by row_upd_index_write_log. */

View File

@ -106,15 +106,17 @@ row_upd_rec_sys_fields(
/*===================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
trx_t* trx, /* in: transaction */
dulint roll_ptr)/* in: roll ptr of the undo log record */
{
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(rec_offs_validate(rec, index, offsets));
#ifdef UNIV_SYNC_DEBUG
ut_ad(!buf_block_align(rec)->is_hashed
|| rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
row_set_rec_trx_id(rec, index, trx->id);
row_set_rec_roll_ptr(rec, index, roll_ptr);
row_set_rec_trx_id(rec, index, offsets, trx->id);
row_set_rec_roll_ptr(rec, index, offsets, roll_ptr);
}

View File

@ -30,7 +30,8 @@ row_vers_impl_x_locked_off_kernel(
transaction; NOTE that the kernel mutex is
temporarily released! */
rec_t* rec, /* in: record in a secondary index */
dict_index_t* index); /* in: the secondary index */
dict_index_t* index, /* in: the secondary index */
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*********************************************************************
Finds out if we must preserve a delete marked earlier version of a clustered
index record, because it is >= the purge view. */

View File

@ -11,73 +11,3 @@ Created 2/6/1997 Heikki Tuuri
#include "read0read.h"
#include "page0page.h"
#include "log0recv.h"
/*************************************************************************
Fetches the trx id of a clustered index record or version. */
UNIV_INLINE
dulint
row_vers_get_trx_id(
/*================*/
/* out: trx id or ut_dulint_zero if the
clustered index record not found */
rec_t* rec, /* in: clustered index record, or an old
version of it */
dict_table_t* table) /* in: table */
{
return(row_get_rec_trx_id(rec, dict_table_get_first_index(table)));
}
/*************************************************************************
Checks if a consistent read can be performed immediately on the index
record, or if an older version is needed. */
UNIV_INLINE
ibool
row_vers_clust_rec_sees_older(
/*==========================*/
/* out: FALSE if can read immediately */
rec_t* rec, /* in: record which should be read or passed
over by a read cursor */
dict_index_t* index, /* in: clustered index */
read_view_t* view) /* in: read view */
{
ut_ad(index->type & DICT_CLUSTERED);
if (read_view_sees_trx_id(view, row_get_rec_trx_id(rec, index))) {
return(FALSE);
}
return(TRUE);
}
/*************************************************************************
Checks if a secondary index record can be read immediately by a consistent
read, or if an older version may be needed. To be sure, we will have to
look in the clustered index. */
UNIV_INLINE
ibool
row_vers_sec_rec_may_see_older(
/*===========================*/
/* out: FALSE if can be read immediately */
rec_t* rec, /* in: record which should be read or passed */
dict_index_t* index __attribute__((unused)),/* in: secondary index */
read_view_t* view) /* in: read view */
{
page_t* page;
ut_ad(!(index->type & DICT_CLUSTERED));
page = buf_frame_align(rec);
if ((ut_dulint_cmp(page_get_max_trx_id(page), view->up_limit_id) >= 0)
|| recv_recovery_is_on()) {
/* It may be that the record was inserted or modified by a
transaction the view should not see: we have to look in the
clustered index */
return(TRUE);
}
return(FALSE);
}

View File

@ -538,6 +538,10 @@ struct srv_sys_struct{
srv_table_t* threads; /* server thread table */
UT_LIST_BASE_NODE_T(que_thr_t)
tasks; /* task queue */
dict_index_t* dummy_ind1; /* dummy index for old-style
supremum and infimum records */
dict_index_t* dummy_ind2; /* dummy index for new-style
supremum and infimum records */
};
extern ulint srv_n_threads_active[];

View File

@ -246,6 +246,7 @@ trx_undo_prev_version_build(
index_rec page and purge_view */
rec_t* rec, /* in: version of a clustered index record */
dict_index_t* index, /* in: clustered index */
ulint* offsets,/* in: rec_get_offsets(rec, index) */
mem_heap_t* heap, /* in: memory heap from which the memory
needed is allocated */
rec_t** old_vers);/* out, own: previous version, or NULL if

View File

@ -208,7 +208,20 @@ ut_align_down(
/*==========*/
/* out: aligned pointer */
void* ptr, /* in: pointer */
ulint align_no); /* in: align by this number */
ulint align_no) /* in: align by this number */
__attribute__((const));
/*************************************************************
The following function computes the offset of a pointer from the nearest
aligned address. */
UNIV_INLINE
ulint
ut_align_offset(
/*==========*/
/* out: distance from aligned
pointer */
const void* ptr, /* in: pointer */
ulint align_no) /* in: align by this number */
__attribute__((const));
/*********************************************************************
Gets the nth bit of a ulint. */
UNIV_INLINE

View File

@ -335,6 +335,27 @@ ut_align_down(
return((void*)((((ulint)ptr)) & ~(align_no - 1)));
}
/*************************************************************
The following function computes the offset of a pointer from the nearest
aligned address. */
UNIV_INLINE
ulint
ut_align_offset(
/*============*/
/* out: distance from
aligned pointer */
const void* ptr, /* in: pointer */
ulint align_no) /* in: align by this number */
{
ut_ad(align_no > 0);
ut_ad(((align_no - 1) & align_no) == 0);
ut_ad(ptr);
ut_ad(sizeof(void*) == sizeof(ulint));
return(((ulint)ptr) & (align_no - 1));
}
/*********************************************************************
Gets the nth bit of a ulint. */
UNIV_INLINE

View File

@ -425,11 +425,14 @@ lock_check_trx_id_sanity(
dulint trx_id, /* in: trx id */
rec_t* rec, /* in: user record */
dict_index_t* index, /* in: clustered index */
const ulint* offsets, /* in: rec_get_offsets(rec, index) */
ibool has_kernel_mutex)/* in: TRUE if the caller owns the
kernel mutex */
{
ibool is_ok = TRUE;
ut_ad(rec_offs_validate(rec, index, offsets));
if (!has_kernel_mutex) {
mutex_enter(&kernel_mutex);
}
@ -442,7 +445,7 @@ lock_check_trx_id_sanity(
fputs(" InnoDB: Error: transaction id associated"
" with record\n",
stderr);
rec_print(stderr, rec);
rec_print(stderr, rec, offsets);
fputs("InnoDB: in ", stderr);
dict_index_name_print(stderr, NULL, index);
fprintf(stderr, "\n"
@ -474,18 +477,20 @@ lock_clust_rec_cons_read_sees(
rec_t* rec, /* in: user record which should be read or
passed over by a read cursor */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
read_view_t* view) /* in: consistent read view */
{
dulint trx_id;
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(page_rec_is_user_rec(rec));
ut_ad(rec_offs_validate(rec, index, offsets));
/* NOTE that we call this function while holding the search
system latch. To obey the latching order we must NOT reserve the
kernel mutex here! */
trx_id = row_get_rec_trx_id(rec, index);
trx_id = row_get_rec_trx_id(rec, index, offsets);
if (read_view_sees_trx_id(view, trx_id)) {
@ -1256,6 +1261,7 @@ lock_rec_get_next(
/*==============*/
/* out: next lock, NULL if none exists */
rec_t* rec, /* in: record on a page */
ibool comp, /* in: TRUE=compact page format */
lock_t* lock) /* in: lock */
{
#ifdef UNIV_SYNC_DEBUG
@ -1271,7 +1277,7 @@ lock_rec_get_next(
return(NULL);
}
if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec))) {
if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec, comp))) {
return(lock);
}
@ -1288,15 +1294,17 @@ lock_rec_get_first(
rec_t* rec) /* in: record on a page */
{
lock_t* lock;
ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first_on_page(rec);
comp = page_is_comp(buf_frame_align(rec));
while (lock) {
if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec))) {
if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec, comp))) {
break;
}
@ -1463,6 +1471,7 @@ lock_rec_has_expl(
for a supremum record we regard this always a gap
type request */
rec_t* rec, /* in: record */
ibool comp, /* in: TRUE=compact page format */
trx_t* trx) /* in: transaction */
{
lock_t* lock;
@ -1492,7 +1501,7 @@ lock_rec_has_expl(
return(lock);
}
lock = lock_rec_get_next(rec, lock);
lock = lock_rec_get_next(rec, comp, lock);
}
return(NULL);
@ -1511,6 +1520,7 @@ lock_rec_other_has_expl_req(
ulint wait, /* in: LOCK_WAIT if also waiting locks are
taken into account, or 0 if not */
rec_t* rec, /* in: record to look at */
ibool comp, /* in: TRUE=compact record format */
trx_t* trx) /* in: transaction, or NULL if requests by all
transactions are taken into account */
{
@ -1535,7 +1545,7 @@ lock_rec_other_has_expl_req(
return(lock);
}
lock = lock_rec_get_next(rec, lock);
lock = lock_rec_get_next(rec, comp, lock);
}
return(NULL);
@ -1556,12 +1566,13 @@ lock_rec_other_has_conflicting(
trx_t* trx) /* in: our transaction */
{
lock_t* lock;
ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first(rec);
comp = page_is_comp(buf_frame_align(rec));
while (lock) {
if (lock_rec_has_to_wait(trx, mode, lock,
@ -1570,7 +1581,7 @@ lock_rec_other_has_conflicting(
return(lock);
}
lock = lock_rec_get_next(rec, lock);
lock = lock_rec_get_next(rec, comp, lock);
}
return(NULL);
@ -1596,8 +1607,7 @@ lock_rec_find_similar_on_page(
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
heap_no = rec_get_heap_no(rec);
heap_no = rec_get_heap_no(rec, page_is_comp(buf_frame_align(rec)));
lock = lock_rec_get_first_on_page(rec);
while (lock != NULL) {
@ -1624,7 +1634,8 @@ lock_sec_rec_some_has_impl_off_kernel(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
dict_index_t* index) /* in: secondary index */
dict_index_t* index, /* in: secondary index */
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
page_t* page;
@ -1633,6 +1644,7 @@ lock_sec_rec_some_has_impl_off_kernel(
#endif /* UNIV_SYNC_DEBUG */
ut_ad(!(index->type & DICT_CLUSTERED));
ut_ad(page_rec_is_user_rec(rec));
ut_ad(rec_offs_validate(rec, index, offsets));
page = buf_frame_align(rec);
@ -1652,8 +1664,8 @@ lock_sec_rec_some_has_impl_off_kernel(
/* Ok, in this case it is possible that some transaction has an
implicit x-lock. We have to look in the clustered index. */
if (!lock_check_trx_id_sanity(page_get_max_trx_id(page), rec, index,
TRUE)) {
if (!lock_check_trx_id_sanity(page_get_max_trx_id(page),
rec, index, offsets, TRUE)) {
buf_page_print(page);
/* The page is corrupt: try to avoid a crash by returning
@ -1661,7 +1673,7 @@ lock_sec_rec_some_has_impl_off_kernel(
return(NULL);
}
return(row_vers_impl_x_locked_off_kernel(rec, index));
return(row_vers_impl_x_locked_off_kernel(rec, index, offsets));
}
/*============== RECORD LOCK CREATION AND QUEUE MANAGEMENT =============*/
@ -1695,7 +1707,7 @@ lock_rec_create(
page = buf_frame_align(rec);
space = buf_frame_get_space_id(page);
page_no = buf_frame_get_page_no(page);
heap_no = rec_get_heap_no(rec);
heap_no = rec_get_heap_no(rec, page_is_comp(page));
/* If rec is the supremum record, then we reset the gap and
LOCK_REC_NOT_GAP bits, as all locks on the supremum are
@ -1708,8 +1720,7 @@ lock_rec_create(
}
/* Make lock bitmap bigger by a safety margin */
n_bits = page_header_get_field(page, PAGE_N_HEAP)
+ LOCK_PAGE_BITMAP_MARGIN;
n_bits = page_dir_get_n_heap(page) + LOCK_PAGE_BITMAP_MARGIN;
n_bytes = 1 + n_bits / 8;
lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes);
@ -1814,7 +1825,8 @@ lock_rec_enqueue_waiting(
if (lock_deadlock_occurs(lock, trx)) {
lock_reset_lock_and_trx_wait(lock);
lock_rec_reset_nth_bit(lock, rec_get_heap_no(rec));
lock_rec_reset_nth_bit(lock, rec_get_heap_no(rec,
page_is_comp(buf_frame_align(rec))));
return(DB_DEADLOCK);
}
@ -1864,7 +1876,7 @@ lock_rec_add_to_queue(
lock_t* lock;
lock_t* similar_lock = NULL;
ulint heap_no;
page_t* page;
page_t* page = buf_frame_align(rec);
ibool somebody_waits = FALSE;
#ifdef UNIV_SYNC_DEBUG
@ -1872,15 +1884,15 @@ lock_rec_add_to_queue(
#endif /* UNIV_SYNC_DEBUG */
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|| ((type_mode & LOCK_MODE_MASK) != LOCK_S)
|| !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT, rec, trx));
|| !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT,
rec, page_is_comp(page), trx));
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|| ((type_mode & LOCK_MODE_MASK) != LOCK_X)
|| !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT, rec, trx));
|| !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
rec, page_is_comp(page), trx));
type_mode = type_mode | LOCK_REC;
page = buf_frame_align(rec);
/* If rec is the supremum record, then we can reset the gap bit, as
all locks on the supremum are automatically of the gap type, and we
try to avoid unnecessary memory consumption of a new record lock
@ -1897,7 +1909,7 @@ lock_rec_add_to_queue(
/* Look for a waiting lock request on the same record or on a gap */
heap_no = rec_get_heap_no(rec);
heap_no = rec_get_heap_no(rec, page_is_comp(page));
lock = lock_rec_get_first_on_page(rec);
while (lock != NULL) {
@ -1972,7 +1984,7 @@ lock_rec_lock_fast(
|| mode - (LOCK_MODE_MASK & mode) == 0
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
heap_no = rec_get_heap_no(rec);
heap_no = rec_get_heap_no(rec, page_is_comp(buf_frame_align(rec)));
lock = lock_rec_get_first_on_page(rec);
@ -2053,7 +2065,8 @@ lock_rec_lock_slow(
trx = thr_get_trx(thr);
if (lock_rec_has_expl(mode, rec, trx)) {
if (lock_rec_has_expl(mode, rec,
page_is_comp(buf_frame_align(rec)), trx)) {
/* The trx already has a strong enough lock on rec: do
nothing */
@ -2369,12 +2382,14 @@ lock_rec_reset_and_release_wait(
{
lock_t* lock;
ulint heap_no;
ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
heap_no = rec_get_heap_no(rec);
comp = page_is_comp(buf_frame_align(rec));
heap_no = rec_get_heap_no(rec, comp);
lock = lock_rec_get_first(rec);
@ -2385,7 +2400,7 @@ lock_rec_reset_and_release_wait(
lock_rec_reset_nth_bit(lock, heap_no);
}
lock = lock_rec_get_next(rec, lock);
lock = lock_rec_get_next(rec, comp, lock);
}
}
@ -2403,12 +2418,13 @@ lock_rec_inherit_to_gap(
the locks on this record */
{
lock_t* lock;
ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first(rec);
comp = page_is_comp(buf_frame_align(rec));
while (lock != NULL) {
if (!lock_rec_get_insert_intention(lock)) {
@ -2418,7 +2434,7 @@ lock_rec_inherit_to_gap(
heir, lock->index, lock->trx);
}
lock = lock_rec_get_next(rec, lock);
lock = lock_rec_get_next(rec, comp, lock);
}
}
@ -2435,12 +2451,13 @@ lock_rec_inherit_to_gap_if_gap_lock(
the locks on this record */
{
lock_t* lock;
ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first(rec);
comp = page_is_comp(buf_frame_align(rec));
while (lock != NULL) {
if (!lock_rec_get_insert_intention(lock)
@ -2452,7 +2469,7 @@ lock_rec_inherit_to_gap_if_gap_lock(
heir, lock->index, lock->trx);
}
lock = lock_rec_get_next(rec, lock);
lock = lock_rec_get_next(rec, comp, lock);
}
}
@ -2465,7 +2482,8 @@ lock_rec_move(
/*==========*/
rec_t* receiver, /* in: record which gets locks; this record
must have no lock requests on it! */
rec_t* donator) /* in: record which gives locks */
rec_t* donator, /* in: record which gives locks */
ibool comp) /* in: TRUE=compact page format */
{
lock_t* lock;
ulint heap_no;
@ -2475,7 +2493,7 @@ lock_rec_move(
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
heap_no = rec_get_heap_no(donator);
heap_no = rec_get_heap_no(donator, comp);
lock = lock_rec_get_first(donator);
@ -2495,7 +2513,7 @@ lock_rec_move(
lock_rec_add_to_queue(type_mode, receiver, lock->index,
lock->trx);
lock = lock_rec_get_next(donator, lock);
lock = lock_rec_get_next(donator, comp, lock);
}
ut_ad(lock_rec_get_first(donator) == NULL);
@ -2521,6 +2539,7 @@ lock_move_reorganize_page(
UT_LIST_BASE_NODE_T(lock_t) old_locks;
mem_heap_t* heap = NULL;
rec_t* sup;
ibool comp;
lock_mutex_enter_kernel();
@ -2561,6 +2580,9 @@ lock_move_reorganize_page(
lock = UT_LIST_GET_FIRST(old_locks);
comp = page_is_comp(page);
ut_ad(comp == page_is_comp(old_page));
while (lock) {
/* NOTE: we copy also the locks set on the infimum and
supremum of the page; the infimum may carry locks if an
@ -2572,12 +2594,12 @@ lock_move_reorganize_page(
/* Set locks according to old locks */
for (;;) {
ut_ad(0 == ut_memcmp(page_cur_get_rec(&cur1),
ut_ad(comp || 0 == ut_memcmp(page_cur_get_rec(&cur1),
page_cur_get_rec(&cur2),
rec_get_data_size(
rec_get_data_size_old(
page_cur_get_rec(&cur2))));
old_heap_no = rec_get_heap_no(page_cur_get_rec(&cur2));
old_heap_no = rec_get_heap_no(page_cur_get_rec(&cur2),
comp);
if (lock_rec_get_nth_bit(lock, old_heap_no)) {
@ -2636,6 +2658,7 @@ lock_move_rec_list_end(
ulint heap_no;
rec_t* sup;
ulint type_mode;
ibool comp;
lock_mutex_enter_kernel();
@ -2649,6 +2672,8 @@ lock_move_rec_list_end(
lock = lock_rec_get_first_on_page(page);
comp = page_is_comp(page);
while (lock != NULL) {
page_cur_position(rec, &cur1);
@ -2664,13 +2689,12 @@ lock_move_rec_list_end(
reset the lock bits on the old */
while (page_cur_get_rec(&cur1) != sup) {
ut_ad(0 == ut_memcmp(page_cur_get_rec(&cur1),
ut_ad(comp || 0 == ut_memcmp(page_cur_get_rec(&cur1),
page_cur_get_rec(&cur2),
rec_get_data_size(
rec_get_data_size_old(
page_cur_get_rec(&cur2))));
heap_no = rec_get_heap_no(page_cur_get_rec(&cur1));
heap_no = rec_get_heap_no(page_cur_get_rec(&cur1),
comp);
if (lock_rec_get_nth_bit(lock, heap_no)) {
type_mode = lock->type_mode;
@ -2720,12 +2744,15 @@ lock_move_rec_list_start(
page_cur_t cur2;
ulint heap_no;
ulint type_mode;
ibool comp;
ut_a(new_page);
lock_mutex_enter_kernel();
lock = lock_rec_get_first_on_page(page);
comp = page_is_comp(page);
ut_ad(comp == page_is_comp(new_page));
while (lock != NULL) {
@ -2739,13 +2766,12 @@ lock_move_rec_list_start(
reset the lock bits on the old */
while (page_cur_get_rec(&cur1) != rec) {
ut_ad(0 == ut_memcmp(page_cur_get_rec(&cur1),
ut_ad(comp || 0 == ut_memcmp(page_cur_get_rec(&cur1),
page_cur_get_rec(&cur2),
rec_get_data_size(
rec_get_data_size_old(
page_cur_get_rec(&cur2))));
heap_no = rec_get_heap_no(page_cur_get_rec(&cur1));
heap_no = rec_get_heap_no(page_cur_get_rec(&cur1),
comp);
if (lock_rec_get_nth_bit(lock, heap_no)) {
type_mode = lock->type_mode;
@ -2785,13 +2811,16 @@ lock_update_split_right(
page_t* right_page, /* in: right page */
page_t* left_page) /* in: left page */
{
ibool comp;
lock_mutex_enter_kernel();
comp = page_is_comp(left_page);
ut_ad(comp == page_is_comp(right_page));
/* Move the locks on the supremum of the left page to the supremum
of the right page */
lock_rec_move(page_get_supremum_rec(right_page),
page_get_supremum_rec(left_page));
page_get_supremum_rec(left_page), comp);
/* Inherit the locks to the supremum of left page from the successor
of the infimum on right page */
@ -2845,13 +2874,16 @@ lock_update_root_raise(
page_t* new_page, /* in: index page to which copied */
page_t* root) /* in: root page */
{
ibool comp;
lock_mutex_enter_kernel();
comp = page_is_comp(root);
ut_ad(comp == page_is_comp(new_page));
/* Move the locks on the supremum of the root to the supremum
of new_page */
lock_rec_move(page_get_supremum_rec(new_page),
page_get_supremum_rec(root));
page_get_supremum_rec(root), comp);
lock_mutex_exit_kernel();
}
@ -2865,13 +2897,16 @@ lock_update_copy_and_discard(
page_t* new_page, /* in: index page to which copied */
page_t* page) /* in: index page; NOT the root! */
{
ibool comp;
lock_mutex_enter_kernel();
comp = page_is_comp(page);
ut_ad(comp == page_is_comp(new_page));
/* Move the locks on the supremum of the old page to the supremum
of new_page */
lock_rec_move(page_get_supremum_rec(new_page),
page_get_supremum_rec(page));
page_get_supremum_rec(page), comp);
lock_rec_free_all_from_discard_page(page);
lock_mutex_exit_kernel();
@ -2909,8 +2944,11 @@ lock_update_merge_left(
page_t* right_page) /* in: merged index page which will be
discarded */
{
ibool comp;
lock_mutex_enter_kernel();
comp = page_is_comp(left_page);
ut_ad(comp == page_is_comp(right_page));
if (page_rec_get_next(orig_pred) != page_get_supremum_rec(left_page)) {
/* Inherit the locks on the supremum of the left page to the
@ -2930,7 +2968,7 @@ lock_update_merge_left(
of the left page */
lock_rec_move(page_get_supremum_rec(left_page),
page_get_supremum_rec(right_page));
page_get_supremum_rec(right_page), comp);
lock_rec_free_all_from_discard_page(right_page);
@ -3057,12 +3095,14 @@ lock_rec_store_on_page_infimum(
bits are reset on the record */
{
page_t* page;
ibool comp;
page = buf_frame_align(rec);
comp = page_is_comp(page);
lock_mutex_enter_kernel();
lock_rec_move(page_get_infimum_rec(page), rec);
lock_rec_move(page_get_infimum_rec(page), rec, comp);
lock_mutex_exit_kernel();
}
@ -3079,9 +3119,12 @@ lock_rec_restore_from_page_infimum(
whose infimum stored the lock state; lock bits are
reset on the infimum */
{
ibool comp;
lock_mutex_enter_kernel();
lock_rec_move(rec, page_get_infimum_rec(page));
comp = page_is_comp(page);
ut_ad(comp == page_is_comp(buf_frame_align(rec)));
lock_rec_move(rec, page_get_infimum_rec(page), comp);
lock_mutex_exit_kernel();
}
@ -4025,11 +4068,15 @@ lock_rec_print(
FILE* file, /* in: file where to print */
lock_t* lock) /* in: record type lock */
{
page_t* page;
ulint space;
ulint page_no;
ulint i;
mtr_t mtr;
page_t* page;
ulint space;
ulint page_no;
ulint i;
mtr_t mtr;
mem_heap_t* heap;
ulint* offsets = NULL;
heap = mem_heap_create(100);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@ -4108,8 +4155,11 @@ lock_rec_print(
fprintf(file, "Record lock, heap no %lu ", (ulong) i);
if (page) {
rec_print(file,
page_find_rec_with_heap_no(page, i));
rec_t* rec
= page_find_rec_with_heap_no(page, i);
offsets = rec_reget_offsets(rec, lock->index,
offsets, ULINT_UNDEFINED, heap);
rec_print(file, rec, offsets);
}
putc('\n', file);
@ -4117,6 +4167,7 @@ lock_rec_print(
}
mtr_commit(&mtr);
mem_heap_free(heap);
}
/*************************************************************************
@ -4394,12 +4445,16 @@ lock_rec_queue_validate(
/*====================*/
/* out: TRUE if ok */
rec_t* rec, /* in: record to look at */
dict_index_t* index) /* in: index, or NULL if not known */
dict_index_t* index, /* in: index, or NULL if not known */
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
trx_t* impl_trx;
lock_t* lock;
ibool comp;
ut_a(rec);
ut_ad(rec_offs_validate(rec, index, offsets));
comp = page_is_comp(buf_frame_align(rec));
lock_mutex_enter_kernel();
@ -4422,7 +4477,7 @@ lock_rec_queue_validate(
ut_a(lock->index == index);
}
lock = lock_rec_get_next(rec, lock);
lock = lock_rec_get_next(rec, comp, lock);
}
lock_mutex_exit_kernel();
@ -4432,13 +4487,13 @@ lock_rec_queue_validate(
if (index && (index->type & DICT_CLUSTERED)) {
impl_trx = lock_clust_rec_some_has_impl(rec, index);
impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
LOCK_WAIT, rec, impl_trx)) {
LOCK_WAIT, rec, comp, impl_trx)) {
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
impl_trx));
comp, impl_trx));
}
}
@ -4448,13 +4503,14 @@ lock_rec_queue_validate(
next function call: we have to release lock table mutex
to obey the latching order */
impl_trx = lock_sec_rec_some_has_impl_off_kernel(rec, index);
impl_trx = lock_sec_rec_some_has_impl_off_kernel(
rec, index, offsets);
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
LOCK_WAIT, rec, impl_trx)) {
LOCK_WAIT, rec, comp, impl_trx)) {
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
impl_trx));
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
rec, comp, impl_trx));
}
}
@ -4473,10 +4529,10 @@ lock_rec_queue_validate(
if (lock_get_mode(lock) == LOCK_S) {
ut_a(!lock_rec_other_has_expl_req(LOCK_X,
0, 0, rec, lock->trx));
0, 0, rec, comp, lock->trx));
} else {
ut_a(!lock_rec_other_has_expl_req(LOCK_S,
0, 0, rec, lock->trx));
0, 0, rec, comp, lock->trx));
}
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {
@ -4484,7 +4540,7 @@ lock_rec_queue_validate(
ut_a(lock_rec_has_to_wait_in_queue(lock));
}
lock = lock_rec_get_next(rec, lock);
lock = lock_rec_get_next(rec, comp, lock);
}
lock_mutex_exit_kernel();
@ -4510,6 +4566,8 @@ lock_rec_validate_page(
ulint nth_bit = 0;
ulint i;
mtr_t mtr;
mem_heap_t* heap = mem_heap_create(100);
ulint* offsets = NULL;
#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
@ -4549,13 +4607,15 @@ loop:
index = lock->index;
rec = page_find_rec_with_heap_no(page, i);
offsets = rec_reget_offsets(rec, index,
offsets, ULINT_UNDEFINED, heap);
fprintf(stderr,
"Validating %lu %lu\n", (ulong) space, (ulong) page_no);
lock_mutex_exit_kernel();
lock_rec_queue_validate(rec, index);
lock_rec_queue_validate(rec, index, offsets);
lock_mutex_enter_kernel();
@ -4575,6 +4635,7 @@ function_exit:
mtr_commit(&mtr);
mem_heap_free(heap);
return(TRUE);
}
@ -4747,8 +4808,16 @@ lock_rec_insert_check_and_lock(
page_update_max_trx_id(buf_frame_align(rec),
thr_get_trx(thr)->id);
}
ut_ad(lock_rec_queue_validate(next_rec, index));
#ifdef UNIV_DEBUG
{
mem_heap_t* heap = mem_heap_create(100);
const ulint* offsets = rec_get_offsets(next_rec, index,
ULINT_UNDEFINED, heap);
ut_ad(lock_rec_queue_validate(next_rec, index, offsets));
mem_heap_free(heap);
}
#endif /* UNIV_DEBUG */
return(err);
}
@ -4762,7 +4831,8 @@ void
lock_rec_convert_impl_to_expl(
/*==========================*/
rec_t* rec, /* in: user record on page */
dict_index_t* index) /* in: index of record */
dict_index_t* index, /* in: index of record */
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
trx_t* impl_trx;
@ -4770,11 +4840,14 @@ lock_rec_convert_impl_to_expl(
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(page_rec_is_user_rec(rec));
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(page_is_comp(buf_frame_align(rec)) == index->table->comp);
if (index->type & DICT_CLUSTERED) {
impl_trx = lock_clust_rec_some_has_impl(rec, index);
impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
} else {
impl_trx = lock_sec_rec_some_has_impl_off_kernel(rec, index);
impl_trx = lock_sec_rec_some_has_impl_off_kernel(
rec, index, offsets);
}
if (impl_trx) {
@ -4782,7 +4855,7 @@ lock_rec_convert_impl_to_expl(
record, set one for it */
if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
impl_trx)) {
index->table->comp, impl_trx)) {
lock_rec_add_to_queue(LOCK_REC | LOCK_X
| LOCK_REC_NOT_GAP, rec, index,
@ -4808,17 +4881,19 @@ lock_clust_rec_modify_check_and_lock(
does nothing */
rec_t* rec, /* in: record which should be modified */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
que_thr_t* thr) /* in: query thread */
{
ulint err;
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(index->type & DICT_CLUSTERED);
if (flags & BTR_NO_LOCKING_FLAG) {
return(DB_SUCCESS);
}
ut_ad(index->type & DICT_CLUSTERED);
lock_mutex_enter_kernel();
ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
@ -4826,13 +4901,13 @@ lock_clust_rec_modify_check_and_lock(
/* If a transaction has no explicit x-lock set on the record, set one
for it */
lock_rec_convert_impl_to_expl(rec, index);
lock_rec_convert_impl_to_expl(rec, index, offsets);
err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr);
lock_mutex_exit_kernel();
ut_ad(lock_rec_queue_validate(rec, index));
ut_ad(lock_rec_queue_validate(rec, index, offsets));
return(err);
}
@ -4876,8 +4951,16 @@ lock_sec_rec_modify_check_and_lock(
err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr);
lock_mutex_exit_kernel();
ut_ad(lock_rec_queue_validate(rec, index));
#ifdef UNIV_DEBUG
{
mem_heap_t* heap = mem_heap_create(100);
const ulint* offsets = rec_get_offsets(rec, index,
ULINT_UNDEFINED, heap);
ut_ad(lock_rec_queue_validate(rec, index, offsets));
mem_heap_free(heap);
}
#endif /* UNIV_DEBUG */
if (err == DB_SUCCESS) {
/* Update the page max trx id field */
@ -4904,6 +4987,7 @@ lock_sec_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: secondary index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@ -4915,6 +4999,7 @@ lock_sec_rec_read_check_and_lock(
ut_ad(!(index->type & DICT_CLUSTERED));
ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
ut_ad(rec_offs_validate(rec, index, offsets));
if (flags & BTR_NO_LOCKING_FLAG) {
@ -4937,14 +5022,14 @@ lock_sec_rec_read_check_and_lock(
|| recv_recovery_is_on())
&& !page_rec_is_supremum(rec)) {
lock_rec_convert_impl_to_expl(rec, index);
lock_rec_convert_impl_to_expl(rec, index, offsets);
}
err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
lock_mutex_exit_kernel();
ut_ad(lock_rec_queue_validate(rec, index));
ut_ad(lock_rec_queue_validate(rec, index, offsets));
return(err);
}
@ -4968,6 +5053,7 @@ lock_clust_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@ -4981,6 +5067,9 @@ lock_clust_rec_read_check_and_lock(
ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
ut_ad(gap_mode == LOCK_ORDINARY || gap_mode == LOCK_GAP
|| gap_mode == LOCK_REC_NOT_GAP);
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(rec_offs_validate(rec, index, offsets));
if (flags & BTR_NO_LOCKING_FLAG) {
return(DB_SUCCESS);
@ -4995,14 +5084,14 @@ lock_clust_rec_read_check_and_lock(
if (!page_rec_is_supremum(rec)) {
lock_rec_convert_impl_to_expl(rec, index);
lock_rec_convert_impl_to_expl(rec, index, offsets);
}
err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
lock_mutex_exit_kernel();
ut_ad(lock_rec_queue_validate(rec, index));
ut_ad(lock_rec_queue_validate(rec, index, offsets));
return(err);
}

View File

@ -756,81 +756,124 @@ recv_parse_or_apply_log_rec_body(
mtr_t* mtr) /* in: mtr or NULL; should be non-NULL if and only if
page is non-NULL */
{
byte* new_ptr;
dict_index_t* index = NULL;
if (type <= MLOG_8BYTES) {
new_ptr = mlog_parse_nbytes(type, ptr, end_ptr, page);
} else if (type == MLOG_REC_INSERT) {
new_ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr, page,
mtr);
} else if (type == MLOG_REC_CLUST_DELETE_MARK) {
new_ptr = btr_cur_parse_del_mark_set_clust_rec(ptr, end_ptr,
page);
} else if (type == MLOG_REC_SEC_DELETE_MARK) {
new_ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr,
page);
} else if (type == MLOG_REC_UPDATE_IN_PLACE) {
new_ptr = btr_cur_parse_update_in_place(ptr, end_ptr, page);
} else if ((type == MLOG_LIST_END_DELETE)
|| (type == MLOG_LIST_START_DELETE)) {
new_ptr = page_parse_delete_rec_list(type, ptr, end_ptr, page,
mtr);
} else if (type == MLOG_LIST_END_COPY_CREATED) {
new_ptr = page_parse_copy_rec_list_to_created_page(ptr,
end_ptr, page, mtr);
} else if (type == MLOG_PAGE_REORGANIZE) {
new_ptr = btr_parse_page_reorganize(ptr, end_ptr, page, mtr);
} else if (type == MLOG_PAGE_CREATE) {
new_ptr = page_parse_create(ptr, end_ptr, page, mtr);
} else if (type == MLOG_UNDO_INSERT) {
new_ptr = trx_undo_parse_add_undo_rec(ptr, end_ptr, page);
} else if (type == MLOG_UNDO_ERASE_END) {
new_ptr = trx_undo_parse_erase_page_end(ptr, end_ptr, page,
mtr);
} else if (type == MLOG_UNDO_INIT) {
new_ptr = trx_undo_parse_page_init(ptr, end_ptr, page, mtr);
} else if (type == MLOG_UNDO_HDR_DISCARD) {
new_ptr = trx_undo_parse_discard_latest(ptr, end_ptr, page,
mtr);
} else if ((type == MLOG_UNDO_HDR_CREATE)
|| (type == MLOG_UNDO_HDR_REUSE)) {
new_ptr = trx_undo_parse_page_header(type, ptr, end_ptr, page,
mtr);
} else if (type == MLOG_REC_MIN_MARK) {
new_ptr = btr_parse_set_min_rec_mark(ptr, end_ptr, page, mtr);
} else if (type == MLOG_REC_DELETE) {
new_ptr = page_cur_parse_delete_rec(ptr, end_ptr, page, mtr);
} else if (type == MLOG_IBUF_BITMAP_INIT) {
new_ptr = ibuf_parse_bitmap_init(ptr, end_ptr, page, mtr);
} else if (type == MLOG_INIT_FILE_PAGE) {
new_ptr = fsp_parse_init_file_page(ptr, end_ptr, page);
} else if (type == MLOG_WRITE_STRING) {
new_ptr = mlog_parse_string(ptr, end_ptr, page);
} else if (type == MLOG_FILE_CREATE
|| type == MLOG_FILE_RENAME
|| type == MLOG_FILE_DELETE) {
new_ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, FALSE,
switch (type) {
case MLOG_1BYTE: case MLOG_2BYTES: case MLOG_4BYTES: case MLOG_8BYTES:
ptr = mlog_parse_nbytes(type, ptr, end_ptr, page);
break;
case MLOG_REC_INSERT: case MLOG_COMP_REC_INSERT:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_REC_INSERT, &index))) {
ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr,
index, page, mtr);
}
break;
case MLOG_REC_CLUST_DELETE_MARK: case MLOG_COMP_REC_CLUST_DELETE_MARK:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_REC_CLUST_DELETE_MARK, &index))) {
ptr = btr_cur_parse_del_mark_set_clust_rec(ptr,
end_ptr, index, page);
}
break;
case MLOG_REC_SEC_DELETE_MARK: case MLOG_COMP_REC_SEC_DELETE_MARK:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_REC_SEC_DELETE_MARK, &index))) {
ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr,
index, page);
}
break;
case MLOG_REC_UPDATE_IN_PLACE: case MLOG_COMP_REC_UPDATE_IN_PLACE:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_REC_UPDATE_IN_PLACE, &index))) {
ptr = btr_cur_parse_update_in_place(ptr, end_ptr,
page, index);
}
break;
case MLOG_LIST_END_DELETE: case MLOG_COMP_LIST_END_DELETE:
case MLOG_LIST_START_DELETE: case MLOG_COMP_LIST_START_DELETE:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_LIST_END_DELETE
|| type == MLOG_COMP_LIST_START_DELETE, &index))) {
ptr = page_parse_delete_rec_list(type, ptr, end_ptr,
index, page, mtr);
}
break;
case MLOG_LIST_END_COPY_CREATED: case MLOG_COMP_LIST_END_COPY_CREATED:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_LIST_END_COPY_CREATED, &index))) {
ptr = page_parse_copy_rec_list_to_created_page(ptr,
end_ptr, index, page, mtr);
}
break;
case MLOG_PAGE_REORGANIZE: case MLOG_COMP_PAGE_REORGANIZE:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_PAGE_REORGANIZE, &index))) {
ptr = btr_parse_page_reorganize(ptr, end_ptr, index,
page, mtr);
}
break;
case MLOG_PAGE_CREATE: case MLOG_COMP_PAGE_CREATE:
ptr = page_parse_create(ptr, end_ptr,
type == MLOG_COMP_PAGE_CREATE, page, mtr);
break;
case MLOG_UNDO_INSERT:
ptr = trx_undo_parse_add_undo_rec(ptr, end_ptr, page);
break;
case MLOG_UNDO_ERASE_END:
ptr = trx_undo_parse_erase_page_end(ptr, end_ptr, page, mtr);
break;
case MLOG_UNDO_INIT:
ptr = trx_undo_parse_page_init(ptr, end_ptr, page, mtr);
break;
case MLOG_UNDO_HDR_DISCARD:
ptr = trx_undo_parse_discard_latest(ptr, end_ptr, page, mtr);
break;
case MLOG_UNDO_HDR_CREATE:
case MLOG_UNDO_HDR_REUSE:
ptr = trx_undo_parse_page_header(type, ptr, end_ptr,
page, mtr);
break;
case MLOG_REC_MIN_MARK: case MLOG_COMP_REC_MIN_MARK:
ptr = btr_parse_set_min_rec_mark(ptr, end_ptr,
type == MLOG_COMP_REC_MIN_MARK, page, mtr);
break;
case MLOG_REC_DELETE: case MLOG_COMP_REC_DELETE:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_REC_DELETE, &index))) {
ptr = page_cur_parse_delete_rec(ptr, end_ptr,
index, page, mtr);
}
break;
case MLOG_IBUF_BITMAP_INIT:
ptr = ibuf_parse_bitmap_init(ptr, end_ptr, page, mtr);
break;
case MLOG_INIT_FILE_PAGE:
ptr = fsp_parse_init_file_page(ptr, end_ptr, page);
break;
case MLOG_WRITE_STRING:
ptr = mlog_parse_string(ptr, end_ptr, page);
break;
case MLOG_FILE_CREATE:
case MLOG_FILE_RENAME:
case MLOG_FILE_DELETE:
ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, FALSE,
ULINT_UNDEFINED);
} else {
new_ptr = NULL;
break;
default:
ptr = NULL;
recv_sys->found_corrupt_log = TRUE;
}
ut_ad(!page || new_ptr);
ut_ad(!page || ptr);
if (index) {
dict_table_t* table = index->table;
mem_heap_free(index->heap);
mutex_free(&(table->autoinc_mutex));
mem_heap_free(table->heap);
}
return(new_ptr);
return(ptr);
}
/*************************************************************************

View File

@ -384,3 +384,160 @@ mlog_parse_string(
return(ptr + len);
}
/************************************************************
Opens a buffer for mlog, writes the initial log record and,
if needed, the field lengths of an index. */
byte*
mlog_open_and_write_index(
/*======================*/
/* out: buffer, NULL if log mode
MTR_LOG_NONE */
mtr_t* mtr, /* in: mtr */
byte* rec, /* in: index record or page */
dict_index_t* index, /* in: record descriptor */
byte type, /* in: log item type */
ulint size) /* in: requested buffer size in bytes
(if 0, calls mlog_close() and returns NULL) */
{
byte* log_ptr;
const byte* log_start;
const byte* log_end;
if (!index->table->comp) {
log_start = log_ptr = mlog_open(mtr, 11 + size);
if (!log_ptr) {
return(NULL); /* logging is disabled */
}
log_ptr = mlog_write_initial_log_record_fast(rec, type,
log_ptr, mtr);
log_end = log_ptr + 11 + size;
} else {
ulint i;
ulint n = dict_index_get_n_fields(index);
/* total size needed */
ulint total = 11 + size + (n + 2) * 2;
ulint alloc = total;
/* allocate at most DYN_ARRAY_DATA_SIZE at a time */
if (alloc > DYN_ARRAY_DATA_SIZE) {
alloc = DYN_ARRAY_DATA_SIZE;
}
log_start = log_ptr = mlog_open(mtr, alloc);
if (!log_ptr) {
return(NULL); /* logging is disabled */
}
log_end = log_ptr + alloc;
log_ptr = mlog_write_initial_log_record_fast(rec, type,
log_ptr, mtr);
mach_write_to_2(log_ptr, n);
log_ptr += 2;
mach_write_to_2(log_ptr,
dict_index_get_n_unique_in_tree(index));
log_ptr += 2;
for (i = 0; i < n; i++) {
dict_field_t* field;
dtype_t* type;
ulint len;
field = dict_index_get_nth_field(index, i);
type = dict_col_get_type(dict_field_get_col(field));
len = field->fixed_len;
ut_ad(len < 0x7fff);
if (len == 0 && dtype_get_len(type) > 255) {
/* variable-length field
with maximum length > 255 */
len = 0x7fff;
}
if (dtype_get_prtype(type) & DATA_NOT_NULL) {
len |= 0x8000;
}
if (log_ptr + 2 > log_end) {
mlog_close(mtr, log_ptr);
ut_a(total > (ulint) (log_ptr - log_start));
total -= log_ptr - log_start;
alloc = total;
if (alloc > DYN_ARRAY_DATA_SIZE) {
alloc = DYN_ARRAY_DATA_SIZE;
}
log_start = log_ptr = mlog_open(mtr, alloc);
if (!log_ptr) {
return(NULL); /* logging is disabled */
}
log_end = log_ptr + alloc;
}
mach_write_to_2(log_ptr, len);
log_ptr += 2;
}
}
if (size == 0) {
mlog_close(mtr, log_ptr);
log_ptr = NULL;
} else if (log_ptr + size > log_end) {
mlog_close(mtr, log_ptr);
log_ptr = mlog_open(mtr, size);
}
return(log_ptr);
}
/************************************************************
Parses a log record written by mlog_open_and_write_index. */
byte*
mlog_parse_index(
/*=============*/
/* out: parsed record end,
NULL if not a complete record */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
/* out: new value of log_ptr */
ibool comp, /* in: TRUE=compact record format */
dict_index_t** index) /* out, own: dummy index */
{
ulint i, n, n_uniq;
dict_table_t* table;
dict_index_t* ind;
if (comp) {
if (end_ptr < ptr + 4) {
return(NULL);
}
n = mach_read_from_2(ptr);
ptr += 2;
n_uniq = mach_read_from_2(ptr);
ut_ad(n_uniq <= n);
if (end_ptr < ptr + (n + 1) * 2) {
return(NULL);
}
} else {
n = n_uniq = 1;
}
table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n, comp);
ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY",
DICT_HDR_SPACE, 0, n);
ind->table = table;
ind->n_uniq = n_uniq;
if (n_uniq != n) {
ind->type = DICT_CLUSTERED;
}
/* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
ind->cached = TRUE;
if (comp) {
for (i = 0; i < n; i++) {
ulint len = mach_read_from_2(ptr += 2);
/* The high-order bit of len is the NOT NULL flag;
the rest is 0 or 0x7fff for variable-length fields,
and 1..0x7ffe for fixed-length fields. */
dict_mem_table_add_col(table, "DUMMY",
((len + 1) & 0x7fff) <= 1
? DATA_BINARY
: DATA_FIXBINARY,
len & 0x8000 ? DATA_NOT_NULL : 0,
len & 0x7fff, 0);
dict_index_add_col(ind,
dict_table_get_nth_col(table, i), 0, 0);
}
ptr += 2;
}
*index = ind;
return(ptr);
}

View File

@ -30,6 +30,7 @@ ibool
page_cur_try_search_shortcut(
/*=========================*/
page_t* page, /* in: index page */
dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint* iup_matched_fields,
/* in/out: already matched fields in upper
@ -55,9 +56,14 @@ page_cur_try_search_shortcut(
#ifdef UNIV_SEARCH_DEBUG
page_cur_t cursor2;
#endif
mem_heap_t* heap;
ulint* offsets;
ut_ad(dtuple_check_typed(tuple));
rec = page_header_get_ptr(page, PAGE_LAST_INSERT);
heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, index,
dtuple_get_n_fields(tuple), heap);
ut_ad(rec);
ut_ad(page_rec_is_user_rec(rec));
@ -69,26 +75,30 @@ page_cur_try_search_shortcut(
up_match = low_match;
up_bytes = low_bytes;
cmp = page_cmp_dtuple_rec_with_match(tuple, rec, &low_match,
cmp = page_cmp_dtuple_rec_with_match(tuple, rec, offsets, &low_match,
&low_bytes);
if (cmp == -1) {
mem_heap_free(heap);
return(FALSE);
}
next_rec = page_rec_get_next(rec);
offsets = rec_reget_offsets(next_rec, index, offsets,
dtuple_get_n_fields(tuple), heap);
cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec, &up_match,
&up_bytes);
cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec, offsets,
&up_match, &up_bytes);
if (cmp != -1) {
mem_heap_free(heap);
return(FALSE);
}
cursor->rec = rec;
#ifdef UNIV_SEARCH_DEBUG
page_cur_search_with_match(page, tuple, PAGE_CUR_DBG,
page_cur_search_with_match(page, index, tuple, PAGE_CUR_DBG,
iup_matched_fields,
iup_matched_bytes,
ilow_matched_fields,
@ -117,6 +127,7 @@ page_cur_try_search_shortcut(
#ifdef UNIV_SEARCH_PERF_STAT
page_cur_short_succ++;
#endif
mem_heap_free(heap);
return(TRUE);
}
@ -130,22 +141,24 @@ static
ibool
page_cur_rec_field_extends(
/*=======================*/
/* out: TRUE if rec field extends tuple
field */
dtuple_t* tuple, /* in: data tuple */
rec_t* rec, /* in: record */
ulint n) /* in: compare nth field */
/* out: TRUE if rec field
extends tuple field */
dtuple_t* tuple, /* in: data tuple */
rec_t* rec, /* in: record */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint n) /* in: compare nth field */
{
dtype_t* type;
dfield_t* dfield;
byte* rec_f;
ulint rec_f_len;
ut_ad(rec_offs_validate(rec, NULL, offsets));
dfield = dtuple_get_nth_field(tuple, n);
type = dfield_get_type(dfield);
rec_f = rec_get_nth_field(rec, n, &rec_f_len);
rec_f = rec_get_nth_field(rec, offsets, n, &rec_f_len);
if (type->mtype == DATA_VARCHAR
|| type->mtype == DATA_CHAR
@ -176,6 +189,7 @@ void
page_cur_search_with_match(
/*=======================*/
page_t* page, /* in: index page */
dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@ -212,6 +226,9 @@ page_cur_search_with_match(
ulint dbg_matched_fields;
ulint dbg_matched_bytes;
#endif
mem_heap_t* heap;
ulint* offsets = NULL;
ut_ad(page && tuple && iup_matched_fields && iup_matched_bytes
&& ilow_matched_fields && ilow_matched_bytes && cursor);
ut_ad(dtuple_validate(tuple));
@ -229,7 +246,7 @@ page_cur_search_with_match(
&& (page_header_get_ptr(page, PAGE_LAST_INSERT))
&& (page_header_get_field(page, PAGE_DIRECTION) == PAGE_RIGHT)) {
if (page_cur_try_search_shortcut(page, tuple,
if (page_cur_try_search_shortcut(page, index, tuple,
iup_matched_fields,
iup_matched_bytes,
ilow_matched_fields,
@ -245,6 +262,8 @@ page_cur_search_with_match(
/*#endif */
#endif
heap = mem_heap_create(100);
/* The following flag does not work for non-latin1 char sets because
cmp_full_field does not tell how many bytes matched */
ut_a(mode != PAGE_CUR_LE_OR_EXTENDS);
@ -279,7 +298,10 @@ page_cur_search_with_match(
low_matched_fields, low_matched_bytes,
up_matched_fields, up_matched_bytes);
cmp = cmp_dtuple_rec_with_match(tuple, mid_rec,
offsets = rec_reget_offsets(mid_rec, index, offsets,
dtuple_get_n_fields_cmp(tuple), heap);
cmp = cmp_dtuple_rec_with_match(tuple, mid_rec, offsets,
&cur_matched_fields,
&cur_matched_bytes);
if (cmp == 1) {
@ -288,10 +310,12 @@ page_cur_search_with_match(
low_matched_bytes = cur_matched_bytes;
} else if (cmp == -1) {
offsets = rec_reget_offsets(mid_rec, index,
offsets, dtuple_get_n_fields_cmp(tuple), heap);
if (mode == PAGE_CUR_LE_OR_EXTENDS
&& page_cur_rec_field_extends(tuple, mid_rec,
cur_matched_fields)) {
offsets, cur_matched_fields)) {
low = mid;
low_matched_fields = cur_matched_fields;
low_matched_bytes = cur_matched_bytes;
@ -329,7 +353,10 @@ page_cur_search_with_match(
low_matched_fields, low_matched_bytes,
up_matched_fields, up_matched_bytes);
cmp = cmp_dtuple_rec_with_match(tuple, mid_rec,
offsets = rec_reget_offsets(mid_rec, index,
offsets, dtuple_get_n_fields_cmp(tuple), heap);
cmp = cmp_dtuple_rec_with_match(tuple, mid_rec, offsets,
&cur_matched_fields,
&cur_matched_bytes);
if (cmp == 1) {
@ -338,9 +365,12 @@ page_cur_search_with_match(
low_matched_bytes = cur_matched_bytes;
} else if (cmp == -1) {
offsets = rec_reget_offsets(mid_rec, index,
offsets, dtuple_get_n_fields_cmp(tuple), heap);
if (mode == PAGE_CUR_LE_OR_EXTENDS
&& page_cur_rec_field_extends(tuple, mid_rec,
cur_matched_fields)) {
offsets, cur_matched_fields)) {
low_rec = mid_rec;
low_matched_fields = cur_matched_fields;
low_matched_bytes = cur_matched_bytes;
@ -368,7 +398,9 @@ page_cur_search_with_match(
dbg_matched_fields = 0;
dbg_matched_bytes = 0;
dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, low_rec,
offsets = rec_reget_offsets(low_rec, index,
offsets, ULINT_UNDEFINED, heap);
dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, low_rec, offsets,
&dbg_matched_fields,
&dbg_matched_bytes);
if (mode == PAGE_CUR_G) {
@ -390,7 +422,9 @@ page_cur_search_with_match(
dbg_matched_fields = 0;
dbg_matched_bytes = 0;
dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, up_rec,
offsets = rec_reget_offsets(up_rec, index,
offsets, ULINT_UNDEFINED, heap);
dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, up_rec, offsets,
&dbg_matched_fields,
&dbg_matched_bytes);
if (mode == PAGE_CUR_G) {
@ -419,6 +453,7 @@ page_cur_search_with_match(
*iup_matched_bytes = up_matched_bytes;
*ilow_matched_fields = low_matched_fields;
*ilow_matched_bytes = low_matched_bytes;
mem_heap_free(heap);
}
/***************************************************************
@ -463,10 +498,12 @@ static
void
page_cur_insert_rec_write_log(
/*==========================*/
rec_t* insert_rec, /* in: inserted physical record */
ulint rec_size, /* in: insert_rec size */
rec_t* cursor_rec, /* in: record the cursor is pointing to */
mtr_t* mtr) /* in: mini-transaction handle */
rec_t* insert_rec, /* in: inserted physical record */
ulint rec_size, /* in: insert_rec size */
rec_t* cursor_rec, /* in: record the
cursor is pointing to */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mini-transaction handle */
{
ulint cur_rec_size;
ulint extra_size;
@ -476,23 +513,30 @@ page_cur_insert_rec_write_log(
byte* cur_ptr;
ulint extra_info_yes;
byte* log_ptr;
byte* log_end;
ulint i;
ut_a(rec_size < UNIV_PAGE_SIZE);
ut_ad(rec_size == rec_get_size(insert_rec));
log_ptr = mlog_open(mtr, 30 + MLOG_BUF_MARGIN);
{
mem_heap_t* heap;
ulint* cur_offs;
ulint* ins_offs;
if (log_ptr == NULL) {
heap = mem_heap_create(100);
cur_offs = rec_get_offsets(cursor_rec, index,
ULINT_UNDEFINED, heap);
ins_offs = rec_get_offsets(insert_rec, index,
ULINT_UNDEFINED, heap);
return;
extra_size = rec_offs_extra_size(ins_offs);
cur_extra_size = rec_offs_extra_size(cur_offs);
ut_ad(rec_size == rec_offs_size(ins_offs));
cur_rec_size = rec_offs_size(cur_offs);
mem_heap_free(heap);
}
extra_size = rec_get_extra_size(insert_rec);
cur_extra_size = rec_get_extra_size(cursor_rec);
cur_rec_size = rec_get_size(cursor_rec);
ins_ptr = insert_rec - extra_size;
i = 0;
@ -514,7 +558,9 @@ page_cur_insert_rec_write_log(
ins_ptr++;
cur_ptr++;
} else if ((i < extra_size)
&& (i >= extra_size - REC_N_EXTRA_BYTES)) {
&& (i >= extra_size - (index->table->comp
? REC_N_NEW_EXTRA_BYTES
: REC_N_OLD_EXTRA_BYTES))) {
i = extra_size;
ins_ptr = insert_rec;
cur_ptr = cursor_rec;
@ -525,16 +571,35 @@ page_cur_insert_rec_write_log(
}
if (mtr_get_log_mode(mtr) != MTR_LOG_SHORT_INSERTS) {
log_ptr = mlog_write_initial_log_record_fast(insert_rec,
MLOG_REC_INSERT, log_ptr, mtr);
log_ptr = mlog_open_and_write_index(mtr, insert_rec, index,
index->table->comp
? MLOG_COMP_REC_INSERT : MLOG_REC_INSERT,
2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN);
if (!log_ptr) {
/* Logging in mtr is switched off during crash
recovery: in that case mlog_open returns NULL */
return;
}
log_end = &log_ptr[2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
/* Write the cursor rec offset as a 2-byte ulint */
mach_write_to_2(log_ptr, cursor_rec
- buf_frame_align(cursor_rec));
log_ptr += 2;
} else {
log_ptr = mlog_open(mtr, 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN);
if (!log_ptr) {
/* Logging in mtr is switched off during crash
recovery: in that case mlog_open returns NULL */
return;
}
log_end = &log_ptr[5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
}
if ((rec_get_info_bits(insert_rec) != rec_get_info_bits(cursor_rec))
if ((rec_get_info_bits(insert_rec, index->table->comp) !=
rec_get_info_bits(cursor_rec, index->table->comp))
|| (extra_size != cur_extra_size)
|| (rec_size != cur_rec_size)) {
@ -549,7 +614,8 @@ page_cur_insert_rec_write_log(
+ extra_info_yes);
if (extra_info_yes) {
/* Write the info bits */
mach_write_to_1(log_ptr, rec_get_info_bits(insert_rec));
mach_write_to_1(log_ptr,
rec_get_info_bits(insert_rec, index->table->comp));
log_ptr++;
/* Write the record origin offset */
@ -565,17 +631,15 @@ page_cur_insert_rec_write_log(
/* Write to the log the inserted index record end segment which
differs from the cursor record */
if (rec_size - i < MLOG_BUF_MARGIN) {
ut_memcpy(log_ptr, ins_ptr, rec_size - i);
log_ptr += rec_size - i;
}
rec_size -= i;
mlog_close(mtr, log_ptr);
ut_a(rec_size - i < UNIV_PAGE_SIZE);
if (rec_size - i >= MLOG_BUF_MARGIN) {
mlog_catenate_string(mtr, ins_ptr, rec_size - i);
if (log_ptr + rec_size <= log_end) {
memcpy(log_ptr, ins_ptr, rec_size);
mlog_close(mtr, log_ptr + rec_size);
} else {
mlog_close(mtr, log_ptr);
ut_a(rec_size < UNIV_PAGE_SIZE);
mlog_catenate_string(mtr, ins_ptr, rec_size);
}
}
@ -585,12 +649,13 @@ Parses a log record of a record insert on a page. */
byte*
page_cur_parse_insert_rec(
/*======================*/
/* out: end of log record or NULL */
ibool is_short,/* in: TRUE if short inserts */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
/* out: end of log record or NULL */
ibool is_short,/* in: TRUE if short inserts */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: record descriptor */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
ulint extra_info_yes;
ulint offset = 0; /* remove warning */
@ -603,6 +668,8 @@ page_cur_parse_insert_rec(
byte* ptr2 = ptr;
ulint info_bits = 0; /* remove warning */
page_cur_t cursor;
mem_heap_t* heap;
ulint* offsets;
if (!is_short) {
/* Read the cursor rec offset as a 2-byte ulint */
@ -689,11 +756,14 @@ page_cur_parse_insert_rec(
cursor_rec = page + offset;
}
heap = mem_heap_create(100);
offsets = rec_get_offsets(cursor_rec, index, ULINT_UNDEFINED, heap);
if (extra_info_yes == 0) {
info_bits = rec_get_info_bits(cursor_rec);
origin_offset = rec_get_extra_size(cursor_rec);
mismatch_index = rec_get_size(cursor_rec) - end_seg_len;
}
info_bits = rec_get_info_bits(cursor_rec, index->table->comp);
origin_offset = rec_offs_extra_size(offsets);
mismatch_index = rec_offs_size(offsets) - end_seg_len;
}
if (mismatch_index + end_seg_len < sizeof buf1) {
buf = buf1;
@ -722,14 +792,24 @@ page_cur_parse_insert_rec(
ut_error;
}
ut_memcpy(buf, rec_get_start(cursor_rec), mismatch_index);
ut_memcpy(buf, rec_get_start(cursor_rec, offsets), mismatch_index);
ut_memcpy(buf + mismatch_index, ptr, end_seg_len);
rec_set_info_bits(buf + origin_offset, info_bits);
rec_set_info_bits(buf + origin_offset, index->table->comp, info_bits);
/* Set the status bits for new-style records. */
if (index->table->comp) {
/* Leaf pages (level 0) contain ordinary records;
non-leaf pages contain node pointer records. */
ulint level = page_header_get_field(
buf_frame_align(cursor_rec), PAGE_LEVEL);
rec_set_status(buf + origin_offset,
level ? REC_STATUS_NODE_PTR : REC_STATUS_ORDINARY);
}
page_cur_position(cursor_rec, &cursor);
page_cur_rec_insert(&cursor, buf + origin_offset, mtr);
page_cur_rec_insert(&cursor, buf + origin_offset, index, mtr);
if (buf != buf1) {
@ -751,68 +831,80 @@ page_cur_insert_rec_low(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
ulint data_size,/* in: data size of tuple */
rec_t* rec, /* in: pointer to a physical record or NULL */
dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
dict_index_t* index, /* in: record descriptor */
rec_t* rec, /* in: pointer to a physical record or NULL */
mtr_t* mtr) /* in: mini-transaction handle */
{
byte* insert_buf = NULL;
ulint rec_size;
byte* page; /* the relevant page */
rec_t* last_insert; /* cursor position at previous insert */
rec_t* insert_rec; /* inserted record */
ulint heap_no; /* heap number of the inserted record */
rec_t* current_rec; /* current record after which the
new record is inserted */
rec_t* next_rec; /* next record after current before
the insertion */
ulint owner_slot; /* the slot which owns the inserted record */
rec_t* owner_rec;
ulint n_owned;
byte* insert_buf = NULL;
ulint rec_size;
byte* page; /* the relevant page */
rec_t* last_insert; /* cursor position at previous insert */
rec_t* insert_rec; /* inserted record */
ulint heap_no; /* heap number of the inserted record */
rec_t* current_rec; /* current record after which the
new record is inserted */
rec_t* next_rec; /* next record after current before
the insertion */
ulint owner_slot; /* the slot which owns the
inserted record */
rec_t* owner_rec;
ulint n_owned;
mem_heap_t* heap;
ulint* offsets;
ibool comp = index->table->comp;
ut_ad(cursor && mtr);
ut_ad(tuple || rec);
ut_ad(!(tuple && rec));
ut_ad(rec || dtuple_check_typed(tuple));
ut_ad(rec || (dtuple_get_data_size(tuple) == data_size));
page = page_cur_get_page(cursor);
ut_ad(page_is_comp(page) == comp);
ut_ad(cursor->rec != page_get_supremum_rec(page));
heap = mem_heap_create(100);
/* 1. Get the size of the physical record in the page */
if (tuple != NULL) {
rec_size = data_size + rec_get_converted_extra_size(
data_size,
dtuple_get_n_fields(tuple));
offsets = NULL;
rec_size = rec_get_converted_size(index, tuple);
} else {
rec_size = rec_get_size(rec);
offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
rec_size = rec_offs_size(offsets);
}
/* 2. Try to find suitable space from page memory management */
insert_buf = page_mem_alloc(page, rec_size, &heap_no);
insert_buf = page_mem_alloc(page, rec_size, index, &heap_no);
if (insert_buf == NULL) {
mem_heap_free(heap);
return(NULL);
}
/* 3. Create the record */
if (tuple != NULL) {
insert_rec = rec_convert_dtuple_to_rec_low(insert_buf, tuple,
data_size);
insert_rec = rec_convert_dtuple_to_rec(insert_buf,
index, tuple);
} else {
insert_rec = rec_copy(insert_buf, rec);
insert_rec = rec_copy(insert_buf, rec, offsets);
}
ut_ad(insert_rec);
ut_ad(rec_size == rec_get_size(insert_rec));
offsets = rec_reget_offsets(insert_rec, index,
offsets, ULINT_UNDEFINED, heap);
ut_ad(rec_size == rec_offs_size(offsets));
/* 4. Insert the record in the linked list of records */
current_rec = cursor->rec;
ut_ad(!comp || rec_get_status(current_rec) <= REC_STATUS_INFIMUM);
ut_ad(!comp || rec_get_status(insert_rec) < REC_STATUS_INFIMUM);
next_rec = page_rec_get_next(current_rec);
ut_ad(!comp || rec_get_status(next_rec) != REC_STATUS_INFIMUM);
page_rec_set_next(insert_rec, next_rec);
page_rec_set_next(current_rec, insert_rec);
@ -821,12 +913,15 @@ page_cur_insert_rec_low(
/* 5. Set the n_owned field in the inserted record to zero,
and set the heap_no field */
rec_set_n_owned(insert_rec, 0);
rec_set_heap_no(insert_rec, heap_no);
rec_set_n_owned(insert_rec, comp, 0);
rec_set_heap_no(insert_rec, comp, heap_no);
/* 6. Update the last insertion info in page header */
last_insert = page_header_get_ptr(page, PAGE_LAST_INSERT);
ut_ad(!last_insert || !comp
|| rec_get_node_ptr_flag(last_insert)
== rec_get_node_ptr_flag(insert_rec));
if (last_insert == NULL) {
page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION);
@ -855,8 +950,8 @@ page_cur_insert_rec_low(
/* 7. It remains to update the owner record. */
owner_rec = page_rec_find_owner_rec(insert_rec);
n_owned = rec_get_n_owned(owner_rec);
rec_set_n_owned(owner_rec, n_owned + 1);
n_owned = rec_get_n_owned(owner_rec, comp);
rec_set_n_owned(owner_rec, comp, n_owned + 1);
/* 8. Now we have incremented the n_owned field of the owner
record. If the number exceeds PAGE_DIR_SLOT_MAX_N_OWNED,
@ -868,8 +963,10 @@ page_cur_insert_rec_low(
}
/* 9. Write log record of the insert */
page_cur_insert_rec_write_log(insert_rec, rec_size, current_rec, mtr);
page_cur_insert_rec_write_log(insert_rec, rec_size, current_rec,
index, mtr);
mem_heap_free(heap);
return(insert_rec);
}
@ -879,17 +976,19 @@ UNIV_INLINE
byte*
page_copy_rec_list_to_created_page_write_log(
/*=========================================*/
/* out: 4-byte field where to write the log data
length */
page_t* page, /* in: index page */
mtr_t* mtr) /* in: mtr */
/* out: 4-byte field where to
write the log data length */
page_t* page, /* in: index page */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
mlog_write_initial_log_record(page, MLOG_LIST_END_COPY_CREATED, mtr);
log_ptr = mlog_open(mtr, 4);
log_ptr = mlog_open_and_write_index(mtr, page, index,
index->table->comp
? MLOG_COMP_LIST_END_COPY_CREATED
: MLOG_LIST_END_COPY_CREATED, 4);
ut_a(log_ptr);
mlog_close(mtr, log_ptr + 4);
return(log_ptr);
@ -901,11 +1000,12 @@ Parses a log record of copying a record list end to a new created page. */
byte*
page_parse_copy_rec_list_to_created_page(
/*=====================================*/
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: record descriptor */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
byte* rec_end;
ulint log_data_len;
@ -931,7 +1031,8 @@ page_parse_copy_rec_list_to_created_page(
}
while (ptr < rec_end) {
ptr = page_cur_parse_insert_rec(TRUE, ptr, end_ptr, page, mtr);
ptr = page_cur_parse_insert_rec(TRUE, ptr, end_ptr,
index, page, mtr);
}
ut_a(ptr == rec_end);
@ -950,10 +1051,11 @@ including that record. Infimum and supremum records are not copied. */
void
page_copy_rec_list_end_to_created_page(
/*===================================*/
page_t* new_page, /* in: index page to copy to */
page_t* page, /* in: index page */
rec_t* rec, /* in: first record to copy */
mtr_t* mtr) /* in: mtr */
page_t* new_page, /* in: index page to copy to */
page_t* page, /* in: index page */
rec_t* rec, /* in: first record to copy */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mtr */
{
page_dir_slot_t* slot = 0; /* remove warning */
byte* heap_top;
@ -966,9 +1068,13 @@ page_copy_rec_list_end_to_created_page(
ulint log_mode;
byte* log_ptr;
ulint log_data_len;
ibool comp = page_is_comp(page);
mem_heap_t* heap;
ulint* offsets = NULL;
ut_ad(page_header_get_field(new_page, PAGE_N_HEAP) == 2);
ut_ad(page_dir_get_n_heap(new_page) == 2);
ut_ad(page != new_page);
ut_ad(comp == page_is_comp(new_page));
if (rec == page_get_infimum_rec(page)) {
@ -983,12 +1089,13 @@ page_copy_rec_list_end_to_created_page(
#ifdef UNIV_DEBUG
/* To pass the debug tests we have to set these dummy values
in the debug version */
page_header_set_field(new_page, PAGE_N_DIR_SLOTS, UNIV_PAGE_SIZE / 2);
page_dir_set_n_slots(new_page, UNIV_PAGE_SIZE / 2);
page_header_set_ptr(new_page, PAGE_HEAP_TOP,
new_page + UNIV_PAGE_SIZE - 1);
#endif
log_ptr = page_copy_rec_list_to_created_page_write_log(new_page, mtr);
log_ptr = page_copy_rec_list_to_created_page_write_log(new_page,
index, mtr);
log_data_len = dyn_array_get_data_size(&(mtr->log));
@ -997,22 +1104,29 @@ page_copy_rec_list_end_to_created_page(
log_mode = mtr_set_log_mode(mtr, MTR_LOG_SHORT_INSERTS);
prev_rec = page_get_infimum_rec(new_page);
heap_top = new_page + PAGE_SUPREMUM_END;
if (comp) {
heap_top = new_page + PAGE_NEW_SUPREMUM_END;
} else {
heap_top = new_page + PAGE_OLD_SUPREMUM_END;
}
count = 0;
slot_index = 0;
n_recs = 0;
heap = mem_heap_create(100);
/* should be do ... until, comment by Jani */
while (rec != page_get_supremum_rec(page)) {
insert_rec = rec_copy(heap_top, rec);
offsets = rec_reget_offsets(rec, index,
offsets, ULINT_UNDEFINED, heap);
insert_rec = rec_copy(heap_top, rec, offsets);
rec_set_next_offs(prev_rec, insert_rec - new_page);
rec_set_next_offs(prev_rec, comp, insert_rec - new_page);
rec_set_n_owned(insert_rec, 0);
rec_set_heap_no(insert_rec, 2 + n_recs);
rec_set_n_owned(insert_rec, comp, 0);
rec_set_heap_no(insert_rec, comp, 2 + n_recs);
rec_size = rec_get_size(insert_rec);
rec_size = rec_offs_size(offsets);
heap_top = heap_top + rec_size;
@ -1034,7 +1148,7 @@ page_copy_rec_list_end_to_created_page(
}
page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec,
mtr);
index, mtr);
prev_rec = insert_rec;
rec = page_rec_get_next(rec);
}
@ -1056,22 +1170,25 @@ page_copy_rec_list_end_to_created_page(
slot_index--;
}
mem_heap_free(heap);
log_data_len = dyn_array_get_data_size(&(mtr->log)) - log_data_len;
ut_a(log_data_len < 100 * UNIV_PAGE_SIZE);
mach_write_to_4(log_ptr, log_data_len);
rec_set_next_offs(insert_rec, PAGE_SUPREMUM);
rec_set_next_offs(insert_rec, comp,
comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM);
slot = page_dir_get_nth_slot(new_page, 1 + slot_index);
page_dir_slot_set_rec(slot, page_get_supremum_rec(new_page));
page_dir_slot_set_n_owned(slot, count + 1);
page_header_set_field(new_page, PAGE_N_DIR_SLOTS, 2 + slot_index);
page_dir_set_n_slots(new_page, 2 + slot_index);
page_header_set_ptr(new_page, PAGE_HEAP_TOP, heap_top);
page_header_set_field(new_page, PAGE_N_HEAP, 2 + n_recs);
page_dir_set_n_heap(new_page, 2 + n_recs);
page_header_set_field(new_page, PAGE_N_RECS, n_recs);
page_header_set_ptr(new_page, PAGE_LAST_INSERT, NULL);
@ -1089,14 +1206,27 @@ UNIV_INLINE
void
page_cur_delete_rec_write_log(
/*==========================*/
rec_t* cursor_rec, /* in: record to be deleted */
mtr_t* mtr) /* in: mini-transaction handle */
rec_t* rec, /* in: record to be deleted */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mini-transaction handle */
{
mlog_write_initial_log_record(cursor_rec, MLOG_REC_DELETE, mtr);
byte* log_ptr;
log_ptr = mlog_open_and_write_index(mtr, rec, index,
index->table->comp
? MLOG_COMP_REC_DELETE
: MLOG_REC_DELETE, 2);
if (!log_ptr) {
/* Logging in mtr is switched off during crash recovery:
in that case mlog_open returns NULL */
return;
}
/* Write the cursor rec offset as a 2-byte ulint */
mlog_catenate_ulint(mtr, cursor_rec - buf_frame_align(cursor_rec),
MLOG_2BYTES);
mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
mlog_close(mtr, log_ptr + 2);
}
/***************************************************************
@ -1105,11 +1235,12 @@ Parses log record of a record delete on a page. */
byte*
page_cur_parse_delete_rec(
/*======================*/
/* out: pointer to record end or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
/* out: pointer to record end or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: record descriptor */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
ulint offset;
page_cur_t cursor;
@ -1128,7 +1259,7 @@ page_cur_parse_delete_rec(
if (page) {
page_cur_position(page + offset, &cursor);
page_cur_delete_rec(&cursor, mtr);
page_cur_delete_rec(&cursor, index, mtr);
}
return(ptr);
@ -1142,6 +1273,7 @@ void
page_cur_delete_rec(
/*================*/
page_cur_t* cursor, /* in: a page cursor */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mini-transaction handle */
{
page_dir_slot_t* cur_dir_slot;
@ -1169,7 +1301,7 @@ page_cur_delete_rec(
cur_n_owned = page_dir_slot_get_n_owned(cur_dir_slot);
/* 0. Write the log record */
page_cur_delete_rec_write_log(current_rec, mtr);
page_cur_delete_rec_write_log(current_rec, index, mtr);
/* 1. Reset the last insert info in the page header and increment
the modify clock for the frame */
@ -1223,7 +1355,7 @@ page_cur_delete_rec(
page_dir_slot_set_n_owned(cur_dir_slot, cur_n_owned - 1);
/* 6. Free the memory occupied by the record */
page_mem_free(page, current_rec);
page_mem_free(page, current_rec, index);
/* 7. Now we have decremented the number of owned records of the slot.
If the number drops below PAGE_DIR_SLOT_MIN_N_OWNED, we balance the

File diff suppressed because it is too large Load Diff

View File

@ -1514,8 +1514,11 @@ pars_create_table(
n_cols = que_node_list_get_len(column_defs);
table = dict_mem_table_create(table_sym->name, 0, n_cols);
/* As the InnoDB SQL parser is for internal use only,
for creating some system tables, this function will only
create tables in the old (not compact) record format. */
table = dict_mem_table_create(table_sym->name, 0, n_cols, FALSE);
if (not_fit_in_memory != NULL) {
table->does_not_fit_in_memory = TRUE;
}

View File

@ -51,6 +51,7 @@ cmp_debug_dtuple_rec_with_match(
dtuple in some of the common fields, or which
has an equal number or more fields than
dtuple */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields);/* in/out: number of already
completely matched fields; when function
returns, contains the value for current
@ -426,6 +427,7 @@ cmp_dtuple_rec_with_match(
dtuple in some of the common fields, or which
has an equal number or more fields than
dtuple */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns,
contains the value for current comparison */
@ -455,12 +457,13 @@ cmp_dtuple_rec_with_match(
ut_ad(dtuple && rec && matched_fields && matched_bytes);
ut_ad(dtuple_check_typed(dtuple));
ut_ad(rec_offs_validate(rec, NULL, offsets));
cur_field = *matched_fields;
cur_bytes = *matched_bytes;
ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple));
ut_ad(cur_field <= rec_get_n_fields(rec));
ut_ad(cur_field <= rec_offs_n_fields(offsets));
/* Match fields in a loop; stop if we run out of fields in dtuple
or find an externally stored field */
@ -472,7 +475,8 @@ cmp_dtuple_rec_with_match(
dtuple_f_len = dfield_get_len(dtuple_field);
rec_b_ptr = rec_get_nth_field(rec, cur_field, &rec_f_len);
rec_b_ptr = rec_get_nth_field(rec, offsets,
cur_field, &rec_f_len);
/* If we have matched yet 0 bytes, it may be that one or
both the fields are SQL null, or the record or dtuple may be
@ -482,7 +486,8 @@ cmp_dtuple_rec_with_match(
if (cur_bytes == 0) {
if (cur_field == 0) {
if (rec_get_info_bits(rec)
if (rec_get_info_bits(rec,
rec_offs_comp(offsets))
& REC_INFO_MIN_REC_FLAG) {
if (dtuple_get_info_bits(dtuple)
@ -504,7 +509,7 @@ cmp_dtuple_rec_with_match(
}
}
if (rec_get_nth_field_extern_bit(rec, cur_field)) {
if (rec_offs_nth_extern(offsets, cur_field)) {
/* We do not compare to an externally
stored field */
@ -635,7 +640,7 @@ cmp_dtuple_rec_with_match(
up to the common fields */
order_resolved:
ut_ad((ret >= - 1) && (ret <= 1));
ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec,
ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec, offsets,
matched_fields));
ut_ad(*matched_fields == cur_field); /* In the debug version, the
above cmp_debug_... sets
@ -656,13 +661,15 @@ cmp_dtuple_rec(
less than rec, respectively; see the comments
for cmp_dtuple_rec_with_match */
dtuple_t* dtuple, /* in: data tuple */
rec_t* rec) /* in: physical record */
rec_t* rec, /* in: physical record */
const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint matched_fields = 0;
ulint matched_bytes = 0;
return(cmp_dtuple_rec_with_match(dtuple, rec, &matched_fields,
&matched_bytes));
ut_ad(rec_offs_validate(rec, NULL, offsets));
return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
&matched_fields, &matched_bytes));
}
/******************************************************************
@ -673,22 +680,24 @@ ibool
cmp_dtuple_is_prefix_of_rec(
/*========================*/
/* out: TRUE if prefix */
dtuple_t* dtuple, /* in: data tuple */
rec_t* rec) /* in: physical record */
dtuple_t* dtuple, /* in: data tuple */
rec_t* rec, /* in: physical record */
const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint n_fields;
ulint matched_fields = 0;
ulint matched_bytes = 0;
ut_ad(rec_offs_validate(rec, NULL, offsets));
n_fields = dtuple_get_n_fields(dtuple);
if (n_fields > rec_get_n_fields(rec)) {
if (n_fields > rec_offs_n_fields(offsets)) {
return(FALSE);
}
cmp_dtuple_rec_with_match(dtuple, rec, &matched_fields,
&matched_bytes);
cmp_dtuple_rec_with_match(dtuple, rec, offsets,
&matched_fields, &matched_bytes);
if (matched_fields == n_fields) {
return(TRUE);
@ -703,42 +712,6 @@ cmp_dtuple_is_prefix_of_rec(
return(FALSE);
}
/******************************************************************
Compares a prefix of a data tuple to a prefix of a physical record for
equality. If there are less fields in rec than parameter n_fields, FALSE
is returned. NOTE that n_fields_cmp of dtuple does not affect this
comparison. */
ibool
cmp_dtuple_rec_prefix_equal(
/*========================*/
/* out: TRUE if equal */
dtuple_t* dtuple, /* in: data tuple */
rec_t* rec, /* in: physical record */
ulint n_fields) /* in: number of fields which should be
compared; must not exceed the number of
fields in dtuple */
{
ulint matched_fields = 0;
ulint matched_bytes = 0;
ut_ad(n_fields <= dtuple_get_n_fields(dtuple));
if (rec_get_n_fields(rec) < n_fields) {
return(FALSE);
}
cmp_dtuple_rec_with_match(dtuple, rec, &matched_fields,
&matched_bytes);
if (matched_fields >= n_fields) {
return(TRUE);
}
return(FALSE);
}
/*****************************************************************
This function is used to compare two physical records. Only the common
first fields are compared, and if an externally stored field is
@ -752,7 +725,13 @@ cmp_rec_rec_with_match(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
dict_index_t* index, /* in: data dictionary index */
ulint n, /* in: number of fields to compare,
or ULINT_UNDEFINED if both records
contain all fields, and all fields
should be compared */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when the function returns,
contains the value the for current
@ -778,17 +757,27 @@ cmp_rec_rec_with_match(
ulint cur_bytes; /* number of already matched bytes in current
field */
int ret = 3333; /* return value */
ibool comp;
ut_ad(rec1 && rec2 && index);
ut_ad(rec_offs_validate(rec1, index, offsets1));
ut_ad(rec_offs_validate(rec2, index, offsets2));
ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2));
rec1_n_fields = rec_get_n_fields(rec1);
rec2_n_fields = rec_get_n_fields(rec2);
comp = rec_offs_comp(offsets1);
if (n == ULINT_UNDEFINED) {
rec1_n_fields = rec_offs_n_fields(offsets1);
rec2_n_fields = rec_offs_n_fields(offsets2);
} else {
ut_ad(n <= rec_offs_n_fields(offsets1));
ut_ad(n <= rec_offs_n_fields(offsets2));
rec1_n_fields = rec2_n_fields = n;
}
cur_field = *matched_fields;
cur_bytes = *matched_bytes;
/* Match fields in a loop; stop if we run out of fields in either
record */
/* Match fields in a loop */
while ((cur_field < rec1_n_fields) && (cur_field < rec2_n_fields)) {
@ -800,17 +789,19 @@ cmp_rec_rec_with_match(
dict_index_get_nth_field(index, cur_field)));
}
rec1_b_ptr = rec_get_nth_field(rec1, cur_field, &rec1_f_len);
rec2_b_ptr = rec_get_nth_field(rec2, cur_field, &rec2_f_len);
rec1_b_ptr = rec_get_nth_field(rec1, offsets1,
cur_field, &rec1_f_len);
rec2_b_ptr = rec_get_nth_field(rec2, offsets2,
cur_field, &rec2_f_len);
if (cur_bytes == 0) {
if (cur_field == 0) {
/* Test if rec is the predefined minimum
record */
if (rec_get_info_bits(rec1)
if (rec_get_info_bits(rec1, comp)
& REC_INFO_MIN_REC_FLAG) {
if (rec_get_info_bits(rec2)
if (rec_get_info_bits(rec2, comp)
& REC_INFO_MIN_REC_FLAG) {
ret = 0;
} else {
@ -819,7 +810,7 @@ cmp_rec_rec_with_match(
goto order_resolved;
} else if (rec_get_info_bits(rec2)
} else if (rec_get_info_bits(rec2, comp)
& REC_INFO_MIN_REC_FLAG) {
ret = 1;
@ -828,8 +819,8 @@ cmp_rec_rec_with_match(
}
}
if (rec_get_nth_field_extern_bit(rec1, cur_field)
|| rec_get_nth_field_extern_bit(rec2, cur_field)) {
if (rec_offs_nth_extern(offsets1, cur_field)
|| rec_offs_nth_extern(offsets2, cur_field)) {
/* We do not compare to an externally
stored field */
@ -984,6 +975,7 @@ cmp_debug_dtuple_rec_with_match(
dtuple in some of the common fields, or which
has an equal number or more fields than
dtuple */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields) /* in/out: number of already
completely matched fields; when function
returns, contains the value for current
@ -1003,14 +995,16 @@ cmp_debug_dtuple_rec_with_match(
ut_ad(dtuple && rec && matched_fields);
ut_ad(dtuple_check_typed(dtuple));
ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple));
ut_ad(*matched_fields <= rec_get_n_fields(rec));
ut_ad(*matched_fields <= rec_offs_n_fields(offsets));
cur_field = *matched_fields;
if (cur_field == 0) {
if (rec_get_info_bits(rec) & REC_INFO_MIN_REC_FLAG) {
if (rec_get_info_bits(rec, rec_offs_comp(offsets))
& REC_INFO_MIN_REC_FLAG) {
if (dtuple_get_info_bits(dtuple)
& REC_INFO_MIN_REC_FLAG) {
@ -1040,9 +1034,10 @@ cmp_debug_dtuple_rec_with_match(
dtuple_f_data = dfield_get_data(dtuple_field);
dtuple_f_len = dfield_get_len(dtuple_field);
rec_f_data = rec_get_nth_field(rec, cur_field, &rec_f_len);
rec_f_data = rec_get_nth_field(rec, offsets,
cur_field, &rec_f_len);
if (rec_get_nth_field_extern_bit(rec, cur_field)) {
if (rec_offs_nth_extern(offsets, cur_field)) {
/* We do not compare to an externally stored field */
ret = 0;

File diff suppressed because it is too large Load Diff

View File

@ -251,7 +251,7 @@ row_ins_sec_index_entry_by_modify(
rec = btr_cur_get_rec(cursor);
ut_ad((cursor->index->type & DICT_CLUSTERED) == 0);
ut_ad(rec_get_deleted_flag(rec));
ut_ad(rec_get_deleted_flag(rec, cursor->index->table->comp));
/* We know that in the alphabetical ordering, entry and rec are
identified. But in their binary form there may be differences if
@ -316,7 +316,7 @@ row_ins_clust_index_entry_by_modify(
rec = btr_cur_get_rec(cursor);
ut_ad(rec_get_deleted_flag(rec));
ut_ad(rec_get_deleted_flag(rec, cursor->index->table->comp));
heap = mem_heap_create(1024);
@ -588,8 +588,16 @@ row_ins_foreign_report_err(
fputs(", in index ", ef);
ut_print_name(ef, trx, foreign->foreign_index->name);
if (rec) {
mem_heap_t* heap;
ulint* offsets;
heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, foreign->foreign_index,
ULINT_UNDEFINED, heap);
fputs(", there is a record:\n", ef);
rec_print(ef, rec);
rec_print(ef, rec, offsets);
mem_heap_free(heap);
} else {
fputs(", the record is not available\n", ef);
}
@ -644,7 +652,16 @@ row_ins_foreign_report_add_err(
}
if (rec) {
rec_print(ef, rec);
mem_heap_t* heap;
ulint* offsets;
heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, foreign->foreign_index,
ULINT_UNDEFINED, heap);
rec_print(ef, rec, offsets);
mem_heap_free(heap);
}
putc('\n', ef);
@ -706,7 +723,6 @@ row_ins_foreign_check_on_constraint(
dict_index_t* index;
dict_index_t* clust_index;
dtuple_t* ref;
mem_heap_t* tmp_heap;
mem_heap_t* upd_vec_heap = NULL;
rec_t* rec;
rec_t* clust_rec;
@ -715,8 +731,9 @@ row_ins_foreign_check_on_constraint(
ulint err;
ulint i;
trx_t* trx;
mem_heap_t* tmp_heap = NULL;
ulint* offsets;
ut_a(thr && foreign && pcur && mtr);
trx = thr_get_trx(thr);
@ -816,7 +833,7 @@ row_ins_foreign_check_on_constraint(
err = DB_ROW_IS_REFERENCED;
row_ins_foreign_report_err(
(char*)"Trying a too deep cascaded delete or update\n",
"Trying a too deep cascaded delete or update\n",
thr, foreign, btr_pcur_get_rec(pcur), entry);
goto nonstandard_exit_func;
@ -848,8 +865,6 @@ row_ins_foreign_check_on_constraint(
PAGE_CUR_LE, BTR_SEARCH_LEAF,
cascade->pcur, 0, mtr);
mem_heap_free(tmp_heap);
clust_rec = btr_pcur_get_rec(cascade->pcur);
if (!page_rec_is_user_rec(clust_rec)
@ -863,10 +878,14 @@ row_ins_foreign_check_on_constraint(
fputs("\n"
"InnoDB: record ", stderr);
rec_print(stderr, rec);
offsets = rec_get_offsets(rec, index,
ULINT_UNDEFINED, tmp_heap);
rec_print(stderr, rec, offsets);
fputs("\n"
"InnoDB: clustered record ", stderr);
rec_print(stderr, clust_rec);
offsets = rec_reget_offsets(clust_rec, clust_index,
offsets, ULINT_UNDEFINED, tmp_heap);
rec_print(stderr, clust_rec, offsets);
fputs("\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr);
@ -884,9 +903,14 @@ row_ins_foreign_check_on_constraint(
/* Here it suffices to use a LOCK_REC_NOT_GAP type lock;
we already have a normal shared lock on the appropriate
gap if the search criterion was not unique */
if (!tmp_heap) {
tmp_heap = mem_heap_create(256);
}
offsets = rec_get_offsets(clust_rec, clust_index,
ULINT_UNDEFINED, tmp_heap);
err = lock_clust_rec_read_check_and_lock(0, clust_rec,
clust_index, LOCK_X, LOCK_REC_NOT_GAP, thr);
clust_index, offsets, LOCK_X, LOCK_REC_NOT_GAP, thr);
}
if (err != DB_SUCCESS) {
@ -894,7 +918,7 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func;
}
if (rec_get_deleted_flag(clust_rec)) {
if (rec_get_deleted_flag(clust_rec, table->comp)) {
/* This can happen if there is a circular reference of
rows such that cascading delete comes to delete a row
already in the process of being delete marked */
@ -1003,6 +1027,10 @@ row_ins_foreign_check_on_constraint(
btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
if (tmp_heap) {
mem_heap_free(tmp_heap);
}
if (upd_vec_heap) {
mem_heap_free(upd_vec_heap);
}
@ -1010,6 +1038,9 @@ row_ins_foreign_check_on_constraint(
return(err);
nonstandard_exit_func:
if (tmp_heap) {
mem_heap_free(tmp_heap);
}
if (upd_vec_heap) {
mem_heap_free(upd_vec_heap);
@ -1037,16 +1068,19 @@ row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP type lock */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
que_thr_t* thr) /* in: query thread */
{
ulint err;
ut_ad(rec_offs_validate(rec, index, offsets));
if (index->type & DICT_CLUSTERED) {
err = lock_clust_rec_read_check_and_lock(0, rec, index, LOCK_S,
type, thr);
err = lock_clust_rec_read_check_and_lock(0,
rec, index, offsets, LOCK_S, type, thr);
} else {
err = lock_sec_rec_read_check_and_lock(0, rec, index, LOCK_S,
type, thr);
err = lock_sec_rec_read_check_and_lock(0,
rec, index, offsets, LOCK_S, type, thr);
}
return(err);
@ -1064,16 +1098,19 @@ row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP type lock */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
que_thr_t* thr) /* in: query thread */
{
ulint err;
ut_ad(rec_offs_validate(rec, index, offsets));
if (index->type & DICT_CLUSTERED) {
err = lock_clust_rec_read_check_and_lock(0, rec, index, LOCK_X,
type, thr);
err = lock_clust_rec_read_check_and_lock(0,
rec, index, offsets, LOCK_X, type, thr);
} else {
err = lock_sec_rec_read_check_and_lock(0, rec, index, LOCK_X,
type, thr);
err = lock_sec_rec_read_check_and_lock(0,
rec, index, offsets, LOCK_X, type, thr);
}
return(err);
@ -1114,6 +1151,10 @@ row_ins_check_foreign_constraint(
ulint i;
mtr_t mtr;
trx_t* trx = thr_get_trx(thr);
mem_heap_t* heap;
ulint* offsets = NULL;
heap = mem_heap_create(100);
run_again:
#ifdef UNIV_SYNC_DEBUG
@ -1125,7 +1166,7 @@ run_again:
if (trx->check_foreigns == FALSE) {
/* The user has suppressed foreign key checks currently for
this session */
mem_heap_free(heap);
return(DB_SUCCESS);
}
@ -1137,6 +1178,7 @@ run_again:
if (UNIV_SQL_NULL == dfield_get_len(
dtuple_get_nth_field(entry, i))) {
mem_heap_free(heap);
return(DB_SUCCESS);
}
}
@ -1160,7 +1202,8 @@ run_again:
with each foreign key constraint, one after
another, and the user has problems predicting in
which order they are performed. */
mem_heap_free(heap);
return(DB_SUCCESS);
}
}
@ -1174,6 +1217,8 @@ run_again:
}
if (check_table == NULL) {
mem_heap_free(heap);
if (check_ref) {
FILE* ef = dict_foreign_err_file;
mutex_enter(&dict_foreign_err_mutex);
@ -1244,10 +1289,13 @@ run_again:
goto next_rec;
}
offsets = rec_reget_offsets(rec, check_index,
offsets, ULINT_UNDEFINED, heap);
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec,
check_index, thr);
check_index, offsets, thr);
if (err != DB_SUCCESS) {
break;
@ -1256,29 +1304,30 @@ run_again:
goto next_rec;
}
cmp = cmp_dtuple_rec(entry, rec);
cmp = cmp_dtuple_rec(entry, rec, offsets);
if (cmp == 0) {
if (rec_get_deleted_flag(rec)) {
if (rec_get_deleted_flag(rec,
rec_offs_comp(offsets))) {
err = row_ins_set_shared_rec_lock(
LOCK_ORDINARY,
rec, check_index, thr);
LOCK_ORDINARY, rec,
check_index, offsets, thr);
if (err != DB_SUCCESS) {
break;
}
} else {
/* Found a matching record */
ulint lock_type;
if (unique_search) {
err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP,
rec, check_index, thr);
lock_type = LOCK_REC_NOT_GAP;
} else {
err = row_ins_set_shared_rec_lock(
LOCK_ORDINARY,
rec, check_index, thr);
lock_type = LOCK_ORDINARY;
}
err = row_ins_set_shared_rec_lock(lock_type,
rec, check_index, offsets, thr);
if (err != DB_SUCCESS) {
@ -1315,7 +1364,7 @@ run_again:
if (cmp < 0) {
err = row_ins_set_shared_rec_lock(LOCK_GAP,
rec, check_index, thr);
rec, check_index, offsets, thr);
if (err != DB_SUCCESS) {
break;
@ -1373,6 +1422,7 @@ do_possible_lock_wait:
err = trx->error_state;
}
mem_heap_free(heap);
return(err);
}
@ -1444,19 +1494,23 @@ row_ins_dupl_error_with_rec(
that the caller already has a record lock on
the record! */
dtuple_t* entry, /* in: entry to insert */
dict_index_t* index) /* in: index */
dict_index_t* index, /* in: index */
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
ulint matched_fields;
ulint matched_bytes;
ulint n_unique;
ulint i;
ut_ad(rec_offs_validate(rec, index, offsets));
n_unique = dict_index_get_n_unique(index);
matched_fields = 0;
matched_bytes = 0;
cmp_dtuple_rec_with_match(entry, rec, &matched_fields, &matched_bytes);
cmp_dtuple_rec_with_match(entry, rec, offsets,
&matched_fields, &matched_bytes);
if (matched_fields < n_unique) {
@ -1477,7 +1531,7 @@ row_ins_dupl_error_with_rec(
}
}
if (!rec_get_deleted_flag(rec)) {
if (!rec_get_deleted_flag(rec, index->table->comp)) {
return(TRUE);
}
@ -1509,7 +1563,9 @@ row_ins_scan_sec_index_for_duplicate(
ibool moved;
mtr_t mtr;
trx_t* trx;
mem_heap_t* heap;
ulint* offsets = NULL;
n_unique = dict_index_get_n_unique(index);
/* If the secondary index is unique, but one of the fields in the
@ -1524,6 +1580,7 @@ row_ins_scan_sec_index_for_duplicate(
}
}
heap = mem_heap_create(100);
mtr_start(&mtr);
/* Store old value on n_fields_cmp */
@ -1549,6 +1606,9 @@ row_ins_scan_sec_index_for_duplicate(
trx = thr_get_trx(thr);
ut_ad(trx);
offsets = rec_reget_offsets(rec, index,
offsets, ULINT_UNDEFINED, heap);
if (innobase_query_is_replace()) {
/* The manual defines the REPLACE semantics that it
@ -1556,12 +1616,12 @@ row_ins_scan_sec_index_for_duplicate(
+ INSERT. Therefore, we should take X-lock for
duplicates */
err = row_ins_set_exclusive_rec_lock(
LOCK_ORDINARY,rec,index,thr);
err = row_ins_set_exclusive_rec_lock(LOCK_ORDINARY,
rec, index, offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_ORDINARY, rec, index,thr);
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY,
rec, index, offsets, thr);
}
if (err != DB_SUCCESS) {
@ -1574,10 +1634,11 @@ row_ins_scan_sec_index_for_duplicate(
goto next_rec;
}
cmp = cmp_dtuple_rec(entry, rec);
cmp = cmp_dtuple_rec(entry, rec, offsets);
if (cmp == 0) {
if (row_ins_dupl_error_with_rec(rec, entry, index)) {
if (row_ins_dupl_error_with_rec(rec, entry,
index, offsets)) {
err = DB_DUPLICATE_KEY;
thr_get_trx(thr)->error_info = index;
@ -1599,6 +1660,7 @@ next_rec:
}
}
mem_heap_free(heap);
mtr_commit(&mtr);
/* Restore old value */
@ -1656,6 +1718,12 @@ row_ins_duplicate_error_in_clust(
page = buf_frame_align(rec);
if (rec != page_get_infimum_rec(page)) {
mem_heap_t* heap;
ulint* offsets;
heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, cursor->index,
ULINT_UNDEFINED, heap);
/* We set a lock on the possible duplicate: this
is needed in logical logging of MySQL to make
@ -1671,24 +1739,26 @@ row_ins_duplicate_error_in_clust(
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,rec,cursor->index,
thr);
offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP,rec, cursor->index,
thr);
offsets, thr);
}
if (err != DB_SUCCESS) {
mem_heap_free(heap);
return(err);
}
if (row_ins_dupl_error_with_rec(rec, entry,
cursor->index)) {
cursor->index, offsets)) {
trx->error_info = cursor->index;
mem_heap_free(heap);
return(DB_DUPLICATE_KEY);
}
mem_heap_free(heap);
}
}
@ -1698,7 +1768,12 @@ row_ins_duplicate_error_in_clust(
page = buf_frame_align(rec);
if (rec != page_get_supremum_rec(page)) {
mem_heap_t* heap;
ulint* offsets;
heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, cursor->index,
ULINT_UNDEFINED, heap);
/* The manual defines the REPLACE semantics that it
is either an INSERT or DELETE(s) for duplicate key
@ -1708,25 +1783,27 @@ row_ins_duplicate_error_in_clust(
if (innobase_query_is_replace()) {
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,
rec,cursor->index,thr);
LOCK_REC_NOT_GAP, rec,
cursor->index, offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP,rec,
cursor->index, thr);
LOCK_REC_NOT_GAP, rec,
cursor->index, offsets, thr);
}
if (err != DB_SUCCESS) {
mem_heap_free(heap);
return(err);
}
if (row_ins_dupl_error_with_rec(rec, entry,
cursor->index)) {
cursor->index, offsets)) {
trx->error_info = cursor->index;
mem_heap_free(heap);
return(DB_DUPLICATE_KEY);
}
mem_heap_free(heap);
}
ut_a(!(cursor->index->type & DICT_CLUSTERED));
@ -1815,6 +1892,8 @@ row_ins_index_entry_low(
ulint n_unique;
big_rec_t* big_rec = NULL;
mtr_t mtr;
mem_heap_t* heap = mem_heap_create(100);
ulint* offsets = NULL;
log_free_check();
@ -1847,8 +1926,9 @@ row_ins_index_entry_low(
buf_frame_align(btr_cur_get_rec(&cursor))));
if (!page_rec_is_supremum(first_rec)) {
ut_a((rec_get_n_fields(first_rec))
== dtuple_get_n_fields(entry));
offsets = rec_get_offsets(first_rec, index,
ULINT_UNDEFINED, heap);
ut_a(rec_offs_n_fields(offsets) == dtuple_get_n_fields(entry));
}
n_unique = dict_index_get_n_unique(index);
@ -1926,7 +2006,7 @@ row_ins_index_entry_low(
if (err == DB_SUCCESS) {
if (ext_vec) {
rec_set_field_extern_bits(insert_rec,
rec_set_field_extern_bits(insert_rec, index,
ext_vec, n_ext_vec, &mtr);
}
}
@ -1936,14 +2016,18 @@ function_exit:
mtr_commit(&mtr);
if (big_rec) {
rec_t* rec;
mtr_start(&mtr);
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, 0, &mtr);
rec = btr_cur_get_rec(&cursor);
offsets = rec_reget_offsets(rec, index,
offsets, ULINT_UNDEFINED, heap);
err = btr_store_big_rec_extern_fields(index, rec,
offsets, big_rec, &mtr);
err = btr_store_big_rec_extern_fields(index,
btr_cur_get_rec(&cursor),
big_rec, &mtr);
if (modify) {
dtuple_big_rec_free(big_rec);
} else {
@ -1953,6 +2037,7 @@ function_exit:
mtr_commit(&mtr);
}
mem_heap_free(heap);
return(err);
}

View File

@ -3226,7 +3226,8 @@ row_scan_and_check_index(
int cmp;
ibool contains_null;
ulint i;
ulint* offsets = NULL;
*n_rows = 0;
buf = mem_alloc(UNIV_PAGE_SIZE);
@ -3266,8 +3267,10 @@ loop:
if (prev_entry != NULL) {
matched_fields = 0;
matched_bytes = 0;
cmp = cmp_dtuple_rec_with_match(prev_entry, rec,
offsets = rec_reget_offsets(rec, index,
offsets, ULINT_UNDEFINED, heap);
cmp = cmp_dtuple_rec_with_match(prev_entry, rec, offsets,
&matched_fields,
&matched_bytes);
contains_null = FALSE;
@ -3296,7 +3299,7 @@ loop:
dtuple_print(stderr, prev_entry);
fputs("\n"
"InnoDB: record ", stderr);
rec_print(stderr, rec);
rec_print(stderr, rec, offsets);
putc('\n', stderr);
is_ok = FALSE;
} else if ((index->type & DICT_UNIQUE)
@ -3310,6 +3313,7 @@ loop:
}
mem_heap_empty(heap);
offsets = NULL;
prev_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
@ -3394,7 +3398,7 @@ row_check_table_for_mysql(
/* We validate also the whole adaptive hash index for all tables
at every CHECK TABLE */
if (!btr_search_validate()) {
if (!btr_search_validate(index)) {
ret = DB_ERROR;
}

View File

@ -99,6 +99,8 @@ row_purge_remove_clust_if_poss_low(
ibool success;
ulint err;
mtr_t mtr;
rec_t* rec;
mem_heap_t* heap;
index = dict_table_get_first_index(node->table);
@ -117,15 +119,21 @@ row_purge_remove_clust_if_poss_low(
return(TRUE);
}
rec = btr_pcur_get_rec(pcur);
heap = mem_heap_create(100);
if (0 != ut_dulint_cmp(node->roll_ptr,
row_get_rec_roll_ptr(btr_pcur_get_rec(pcur), index))) {
row_get_rec_roll_ptr(rec, index, rec_get_offsets(
rec, index, ULINT_UNDEFINED, heap)))) {
mem_heap_free(heap);
/* Someone else has modified the record later: do not remove */
btr_pcur_commit_specify_mtr(pcur, &mtr);
return(TRUE);
}
mem_heap_free(heap);
if (mode == BTR_MODIFY_LEAF) {
success = btr_cur_optimistic_delete(btr_cur, &mtr);
} else {

View File

@ -37,17 +37,18 @@ row_get_rec_sys_field(
/* out: value of the field */
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
dict_index_t* index) /* in: clustered index */
dict_index_t* index, /* in: clustered index */
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
ulint pos;
byte* field;
ulint len;
ulint pos;
byte* field;
ulint len;
ut_ad(index->type & DICT_CLUSTERED);
pos = dict_index_get_sys_col_pos(index, type);
field = rec_get_nth_field(rec, pos, &len);
field = rec_get_nth_field(rec, offsets, pos, &len);
if (type == DATA_TRX_ID) {
@ -70,6 +71,7 @@ row_set_rec_sys_field(
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint val) /* in: value to set */
{
ulint pos;
@ -77,10 +79,11 @@ row_set_rec_sys_field(
ulint len;
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(rec_offs_validate(rec, index, offsets));
pos = dict_index_get_sys_col_pos(index, type);
field = rec_get_nth_field(rec, pos, &len);
field = rec_get_nth_field(rec, offsets, pos, &len);
if (type == DATA_TRX_ID) {
@ -182,6 +185,9 @@ row_build(
the buffer page of this record must be
at least s-latched and the latch held
as long as the row dtuple is used! */
const ulint* offsets,/* in: rec_get_offsets(rec, index)
or NULL, in which case this function
will invoke rec_get_offsets() */
mem_heap_t* heap) /* in: memory heap from which the memory
needed is allocated */
{
@ -196,14 +202,26 @@ row_build(
ulint row_len;
byte* buf;
ulint i;
mem_heap_t* tmp_heap;
ut_ad(index && rec && heap);
ut_ad(index->type & DICT_CLUSTERED);
if (!offsets) {
tmp_heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, index,
ULINT_UNDEFINED, tmp_heap);
} else {
tmp_heap = NULL;
ut_ad(rec_offs_validate(rec, index, offsets));
}
if (type != ROW_COPY_POINTERS) {
/* Take a copy of rec to heap */
buf = mem_heap_alloc(heap, rec_get_size(rec));
rec = rec_copy(buf, rec);
buf = mem_heap_alloc(heap, rec_offs_size(offsets));
rec = rec_copy(buf, rec, offsets);
/* Avoid a debug assertion in rec_offs_validate(). */
rec_offs_make_valid(rec, index, (ulint*) offsets);
}
table = index->table;
@ -211,11 +229,9 @@ row_build(
row = dtuple_create(heap, row_len);
dtuple_set_info_bits(row, rec_get_info_bits(rec));
n_fields = dict_index_get_n_fields(index);
dtuple_set_info_bits(row, rec_get_info_bits(rec, table->comp));
ut_ad(n_fields == rec_get_n_fields(rec));
n_fields = rec_offs_n_fields(offsets);
dict_table_copy_types(row, table);
@ -227,13 +243,13 @@ row_build(
col = dict_field_get_col(ind_field);
dfield = dtuple_get_nth_field(row,
dict_col_get_no(col));
field = rec_get_nth_field(rec, i, &len);
field = rec_get_nth_field(rec, offsets, i, &len);
if (type == ROW_COPY_ALSO_EXTERNALS
&& rec_get_nth_field_extern_bit(rec, i)) {
&& rec_offs_nth_extern(offsets, i)) {
field = btr_rec_copy_externally_stored_field(
rec, i, &len, heap);
rec, offsets, i, &len, heap);
}
dfield_set_data(dfield, field, len);
@ -242,6 +258,10 @@ row_build(
ut_ad(dtuple_check_typed(row));
if (tmp_heap) {
mem_heap_free(tmp_heap);
}
return(row);
}
@ -276,16 +296,23 @@ row_rec_to_index_entry(
ulint len;
ulint rec_len;
byte* buf;
mem_heap_t* tmp_heap;
ulint* offsets;
ut_ad(rec && heap && index);
tmp_heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, tmp_heap);
if (type == ROW_COPY_DATA) {
/* Take a copy of rec to heap */
buf = mem_heap_alloc(heap, rec_get_size(rec));
rec = rec_copy(buf, rec);
buf = mem_heap_alloc(heap, rec_offs_size(offsets));
rec = rec_copy(buf, rec, offsets);
/* Avoid a debug assertion in rec_offs_validate(). */
rec_offs_make_valid(rec, index, offsets);
}
rec_len = rec_get_n_fields(rec);
rec_len = rec_offs_n_fields(offsets);
entry = dtuple_create(heap, rec_len);
@ -295,17 +322,19 @@ row_rec_to_index_entry(
dict_index_copy_types(entry, index, rec_len);
dtuple_set_info_bits(entry, rec_get_info_bits(rec));
dtuple_set_info_bits(entry,
rec_get_info_bits(rec, rec_offs_comp(offsets)));
for (i = 0; i < rec_len; i++) {
dfield = dtuple_get_nth_field(entry, i);
field = rec_get_nth_field(rec, i, &len);
field = rec_get_nth_field(rec, offsets, i, &len);
dfield_set_data(dfield, field, len);
}
ut_ad(dtuple_check_typed(entry));
mem_heap_free(tmp_heap);
return(entry);
}
@ -345,15 +374,22 @@ row_build_row_ref(
byte* buf;
ulint clust_col_prefix_len;
ulint i;
mem_heap_t* tmp_heap;
ulint* offsets;
ut_ad(index && rec && heap);
tmp_heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, tmp_heap);
if (type == ROW_COPY_DATA) {
/* Take a copy of rec to heap */
buf = mem_heap_alloc(heap, rec_get_size(rec));
buf = mem_heap_alloc(heap, rec_offs_size(offsets));
rec = rec_copy(buf, rec);
rec = rec_copy(buf, rec, offsets);
/* Avoid a debug assertion in rec_offs_validate(). */
rec_offs_make_valid(rec, index, offsets);
}
table = index->table;
@ -373,7 +409,7 @@ row_build_row_ref(
ut_a(pos != ULINT_UNDEFINED);
field = rec_get_nth_field(rec, pos, &len);
field = rec_get_nth_field(rec, offsets, pos, &len);
dfield_set_data(dfield, field, len);
@ -397,6 +433,7 @@ row_build_row_ref(
}
ut_ad(dtuple_check_typed(ref));
mem_heap_free(tmp_heap);
return(ref);
}
@ -427,7 +464,9 @@ row_build_row_ref_in_tuple(
ulint pos;
ulint clust_col_prefix_len;
ulint i;
mem_heap_t* heap;
ulint* offsets;
ut_a(ref && index && rec);
if (!index->table) {
@ -446,7 +485,10 @@ row_build_row_ref_in_tuple(
fputs("InnoDB: clust index for table ", stderr);
goto notfound;
}
heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
ref_len = dict_index_get_n_unique(clust_index);
ut_ad(ref_len == dtuple_get_n_fields(ref));
@ -459,8 +501,8 @@ row_build_row_ref_in_tuple(
pos = dict_index_get_nth_field_pos(index, clust_index, i);
ut_a(pos != ULINT_UNDEFINED);
field = rec_get_nth_field(rec, pos, &len);
field = rec_get_nth_field(rec, offsets, pos, &len);
dfield_set_data(dfield, field, len);
@ -484,6 +526,7 @@ row_build_row_ref_in_tuple(
}
ut_ad(dtuple_check_typed(ref));
mem_heap_free(heap);
}
/***********************************************************************

View File

@ -78,8 +78,14 @@ row_sel_sec_rec_is_for_clust_rec(
ulint n;
ulint i;
dtype_t* cur_type;
mem_heap_t* heap;
ulint* clust_offs;
ulint* sec_offs;
UT_NOT_USED(clust_index);
heap = mem_heap_create(100);
clust_offs = rec_get_offsets(clust_rec, clust_index,
ULINT_UNDEFINED, heap);
sec_offs = rec_get_offsets(sec_rec, sec_index, ULINT_UNDEFINED, heap);
n = dict_index_get_n_ordering_defined_by_user(sec_index);
@ -87,10 +93,10 @@ row_sel_sec_rec_is_for_clust_rec(
ifield = dict_index_get_nth_field(sec_index, i);
col = dict_field_get_col(ifield);
clust_field = rec_get_nth_field(clust_rec,
clust_field = rec_get_nth_field(clust_rec, clust_offs,
dict_col_get_clust_pos(col),
&clust_len);
sec_field = rec_get_nth_field(sec_rec, i, &sec_len);
sec_field = rec_get_nth_field(sec_rec, sec_offs, i, &sec_len);
if (ifield->prefix_len > 0
&& clust_len != UNIV_SQL_NULL) {
@ -107,10 +113,12 @@ row_sel_sec_rec_is_for_clust_rec(
if (0 != cmp_data_data(dict_col_get_type(col),
clust_field, clust_len,
sec_field, sec_len)) {
mem_heap_free(heap);
return(FALSE);
}
}
mem_heap_free(heap);
return(TRUE);
}
@ -266,6 +274,7 @@ row_sel_fetch_columns(
dict_index_t* index, /* in: record index */
rec_t* rec, /* in: record in a clustered or non-clustered
index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
sym_node_t* column) /* in: first column in a column list, or
NULL */
{
@ -275,6 +284,8 @@ row_sel_fetch_columns(
byte* data;
ulint len;
ut_ad(rec_offs_validate(rec, index, offsets));
if (index->type & DICT_CLUSTERED) {
index_type = SYM_CLUST_FIELD_NO;
} else {
@ -286,7 +297,7 @@ row_sel_fetch_columns(
if (field_no != ULINT_UNDEFINED) {
data = rec_get_nth_field(rec, field_no, &len);
data = rec_get_nth_field(rec, offsets, field_no, &len);
if (column->copy_val) {
eval_node_copy_and_alloc_val(column, data,
@ -601,8 +612,15 @@ row_sel_get_clust_rec(
rec_t* clust_rec;
rec_t* old_vers;
ulint err;
mem_heap_t* heap;
ulint* offsets;
heap = mem_heap_create(100);
offsets = rec_get_offsets(rec,
btr_pcur_get_btr_cur(&plan->pcur)->index,
ULINT_UNDEFINED, heap);
row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec);
row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec, offsets);
index = dict_table_get_first_index(plan->table);
@ -619,7 +637,7 @@ row_sel_get_clust_rec(
|| btr_pcur_get_low_match(&(plan->clust_pcur))
< dict_index_get_n_unique(index)) {
ut_a(rec_get_deleted_flag(rec));
ut_a(rec_get_deleted_flag(rec, plan->table->comp));
ut_a(node->read_view);
/* In a rare case it is possible that no clust rec is found
@ -636,28 +654,30 @@ row_sel_get_clust_rec(
goto func_exit;
}
offsets = rec_reget_offsets(clust_rec, index,
offsets, ULINT_UNDEFINED, heap);
if (!node->read_view) {
/* Try to place a lock on the index record */
/* If innodb_locks_unsafe_for_binlog option is used,
we lock only the record, i.e. next-key locking is
not used.
*/
we lock only the record, i.e., next-key locking is
not used. */
ulint lock_type;
if (srv_locks_unsafe_for_binlog) {
err = lock_clust_rec_read_check_and_lock(0,
clust_rec,
index, node->row_lock_mode,
LOCK_REC_NOT_GAP, thr);
lock_type = LOCK_REC_NOT_GAP;
} else {
err = lock_clust_rec_read_check_and_lock(0,
clust_rec,
index, node->row_lock_mode,
LOCK_ORDINARY, thr);
lock_type = LOCK_ORDINARY;
}
err = lock_clust_rec_read_check_and_lock(0,
clust_rec, index, offsets,
node->row_lock_mode, lock_type, thr);
if (err != DB_SUCCESS) {
mem_heap_free(heap);
return(err);
}
} else {
@ -666,22 +686,21 @@ row_sel_get_clust_rec(
old_vers = NULL;
if (!lock_clust_rec_cons_read_sees(clust_rec, index,
if (!lock_clust_rec_cons_read_sees(clust_rec, index, offsets,
node->read_view)) {
err = row_sel_build_prev_vers(node->read_view, plan,
clust_rec, &old_vers, mtr);
if (err != DB_SUCCESS) {
mem_heap_free(heap);
return(err);
}
clust_rec = old_vers;
if (clust_rec == NULL) {
*out_rec = clust_rec;
return(DB_SUCCESS);
goto func_exit;
}
}
@ -698,23 +717,22 @@ row_sel_get_clust_rec(
visit through secondary index records that would not really
exist in our snapshot. */
if ((old_vers || rec_get_deleted_flag(rec))
if ((old_vers || rec_get_deleted_flag(rec, plan->table->comp))
&& !row_sel_sec_rec_is_for_clust_rec(rec, plan->index,
clust_rec, index)) {
clust_rec = NULL;
*out_rec = clust_rec;
return(DB_SUCCESS);
goto func_exit;
}
}
/* Fetch the columns needed in test conditions */
row_sel_fetch_columns(index, clust_rec,
row_sel_fetch_columns(index, clust_rec, offsets,
UT_LIST_GET_FIRST(plan->columns));
func_exit:
*out_rec = clust_rec;
mem_heap_free(heap);
return(DB_SUCCESS);
}
@ -727,6 +745,7 @@ sel_set_rec_lock(
/* out: DB_SUCCESS or error code */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: lock mode */
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP */
que_thr_t* thr) /* in: query thread */
@ -744,11 +763,11 @@ sel_set_rec_lock(
}
if (index->type & DICT_CLUSTERED) {
err = lock_clust_rec_read_check_and_lock(0, rec, index, mode,
type, thr);
err = lock_clust_rec_read_check_and_lock(0,
rec, index, offsets, mode, type, thr);
} else {
err = lock_sec_rec_read_check_and_lock(0, rec, index, mode,
type, thr);
err = lock_sec_rec_read_check_and_lock(0,
rec, index, offsets, mode, type, thr);
}
return(err);
@ -956,6 +975,8 @@ row_sel_try_search_shortcut(
{
dict_index_t* index;
rec_t* rec;
mem_heap_t* heap;
ulint* offsets;
index = plan->index;
@ -989,21 +1010,28 @@ row_sel_try_search_shortcut(
/* This is a non-locking consistent read: if necessary, fetch
a previous version of the record */
heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
if (index->type & DICT_CLUSTERED) {
if (!lock_clust_rec_cons_read_sees(rec, index,
if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
node->read_view)) {
mem_heap_free(heap);
return(SEL_RETRY);
}
} else if (!lock_sec_rec_cons_read_sees(rec, index, node->read_view)) {
mem_heap_free(heap);
return(SEL_RETRY);
}
/* Test deleted flag. Fetch the columns needed in test conditions. */
row_sel_fetch_columns(index, rec, UT_LIST_GET_FIRST(plan->columns));
if (rec_get_deleted_flag(rec)) {
row_sel_fetch_columns(index, rec, offsets,
UT_LIST_GET_FIRST(plan->columns));
mem_heap_free(heap);
if (rec_get_deleted_flag(rec, plan->table->comp)) {
return(SEL_EXHAUSTED);
}
@ -1067,7 +1095,9 @@ row_sel(
to the next non-clustered record */
ulint found_flag;
ulint err;
mem_heap_t* heap = mem_heap_create(100);
ulint* offsets = NULL;
ut_ad(thr->run_node == node);
search_latch_locked = FALSE;
@ -1218,22 +1248,23 @@ rec_loop:
if (!consistent_read) {
/* If innodb_locks_unsafe_for_binlog option is used,
we lock only the record, i.e. next-key locking is
not used.
*/
we lock only the record, i.e., next-key locking is
not used. */
rec_t* next_rec = page_rec_get_next(rec);
ulint lock_type;
offsets = rec_reget_offsets(next_rec, index,
offsets, ULINT_UNDEFINED, heap);
if (srv_locks_unsafe_for_binlog) {
err = sel_set_rec_lock(page_rec_get_next(rec),
index,
node->row_lock_mode,
LOCK_REC_NOT_GAP, thr);
lock_type = LOCK_REC_NOT_GAP;
} else {
err = sel_set_rec_lock(page_rec_get_next(rec),
index,
node->row_lock_mode,
LOCK_ORDINARY, thr);
lock_type = LOCK_ORDINARY;
}
err = sel_set_rec_lock(next_rec, index, offsets,
node->row_lock_mode, lock_type, thr);
if (err != DB_SUCCESS) {
/* Note that in this case we will store in pcur
the PREDECESSOR of the record we are waiting
@ -1260,18 +1291,22 @@ rec_loop:
/* Try to place a lock on the index record */
/* If innodb_locks_unsafe_for_binlog option is used,
we lock only the record, i.e. next-key locking is
not used.
*/
we lock only the record, i.e., next-key locking is
not used. */
ulint lock_type;
offsets = rec_reget_offsets(rec, index,
offsets, ULINT_UNDEFINED, heap);
if (srv_locks_unsafe_for_binlog) {
err = sel_set_rec_lock(rec, index, node->row_lock_mode,
LOCK_REC_NOT_GAP, thr);
lock_type = LOCK_REC_NOT_GAP;
} else {
err = sel_set_rec_lock(rec, index, node->row_lock_mode,
LOCK_ORDINARY, thr);
lock_type = LOCK_ORDINARY;
}
err = sel_set_rec_lock(rec, index, offsets,
node->row_lock_mode, lock_type, thr);
if (err != DB_SUCCESS) {
goto lock_wait_or_error;
@ -1334,6 +1369,8 @@ rec_loop:
/* PHASE 3: Get previous version in a consistent read */
cons_read_requires_clust_rec = FALSE;
offsets = rec_reget_offsets(rec, index,
offsets, ULINT_UNDEFINED, heap);
if (consistent_read) {
/* This is a non-locking consistent read: if necessary, fetch
@ -1341,7 +1378,7 @@ rec_loop:
if (index->type & DICT_CLUSTERED) {
if (!lock_clust_rec_cons_read_sees(rec, index,
if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
node->read_view)) {
err = row_sel_build_prev_vers(node->read_view,
@ -1354,6 +1391,7 @@ rec_loop:
if (old_vers == NULL) {
row_sel_fetch_columns(index, rec,
offsets,
UT_LIST_GET_FIRST(plan->columns));
if (!row_sel_test_end_conds(plan)) {
@ -1365,6 +1403,8 @@ rec_loop:
}
rec = old_vers;
offsets = rec_reget_offsets(rec, index,
offsets, ULINT_UNDEFINED, heap);
}
} else if (!lock_sec_rec_cons_read_sees(rec, index,
node->read_view)) {
@ -1376,7 +1416,8 @@ rec_loop:
/* Fetch the columns needed in test conditions */
row_sel_fetch_columns(index, rec, UT_LIST_GET_FIRST(plan->columns));
row_sel_fetch_columns(index, rec, offsets,
UT_LIST_GET_FIRST(plan->columns));
/* Test the selection end conditions: these can only contain columns
which already are found in the index, even though the index might be
@ -1391,7 +1432,8 @@ rec_loop:
goto table_exhausted;
}
if (rec_get_deleted_flag(rec) && !cons_read_requires_clust_rec) {
if (rec_get_deleted_flag(rec, plan->table->comp)
&& !cons_read_requires_clust_rec) {
/* The record is delete marked: we can skip it if this is
not a consistent read which might see an earlier version
@ -1434,7 +1476,7 @@ rec_loop:
goto next_rec;
}
if (rec_get_deleted_flag(clust_rec)) {
if (rec_get_deleted_flag(clust_rec, plan->table->comp)) {
/* The record is delete marked: we can skip it */
@ -1592,7 +1634,8 @@ next_table_no_mtr:
if (search_latch_locked) {
rw_lock_s_unlock(&btr_search_latch);
}
mem_heap_free(heap);
return(DB_SUCCESS);
}
@ -1626,6 +1669,7 @@ table_exhausted:
table_exhausted_no_mtr:
if (node->fetch_table == 0) {
mem_heap_free(heap);
if (node->is_aggregate && !node->aggregate_already_fetched) {
@ -1674,7 +1718,7 @@ stop_for_a_while:
mtr_commit(&mtr);
ut_ad(sync_thread_levels_empty_gen(TRUE));
mem_heap_free(heap);
return(DB_SUCCESS);
commit_mtr_for_a_while:
@ -1710,6 +1754,7 @@ lock_wait_or_error:
ut_ad(sync_thread_levels_empty_gen(TRUE));
mem_heap_free(heap);
return(err);
}
@ -2133,11 +2178,16 @@ row_sel_store_row_id_to_prebuilt(
/*=============================*/
row_prebuilt_t* prebuilt, /* in: prebuilt */
rec_t* index_rec, /* in: record */
dict_index_t* index) /* in: index of the record */
dict_index_t* index, /* in: index of the record */
const ulint* offsets) /* in: rec_get_offsets
(index_rec, index) */
{
byte* data;
ulint len;
data = rec_get_nth_field(index_rec,
ut_ad(rec_offs_validate(index_rec, index, offsets));
data = rec_get_nth_field(index_rec, offsets,
dict_index_get_sys_col_pos(index, DATA_ROW_ID), &len);
if (len != DATA_ROW_ID_LEN) {
@ -2147,7 +2197,7 @@ row_sel_store_row_id_to_prebuilt(
fprintf(stderr, "\n"
"InnoDB: Field number %lu, record:\n",
(ulong) dict_index_get_sys_col_pos(index, DATA_ROW_ID));
rec_print(stderr, index_rec);
rec_print(stderr, index_rec, offsets);
putc('\n', stderr);
ut_error;
}
@ -2236,9 +2286,11 @@ row_sel_store_mysql_rec(
case) */
byte* mysql_rec, /* out: row in the MySQL format */
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
rec_t* rec) /* in: Innobase record in the index
rec_t* rec, /* in: Innobase record in the index
which was described in prebuilt's
template */
const ulint* offsets) /* in: array returned by
rec_get_offsets() */
{
mysql_row_templ_t* templ;
mem_heap_t* extern_field_heap = NULL;
@ -2247,8 +2299,15 @@ row_sel_store_mysql_rec(
byte* blob_buf;
int pad_char;
ulint i;
dict_index_t* index;
ut_ad(prebuilt->mysql_template);
ut_ad(rec_offs_validate(rec, NULL, offsets));
index = prebuilt->index;
if (prebuilt->need_to_access_clustered) {
index = dict_table_get_first_index(index->table);
}
if (prebuilt->blob_heap != NULL) {
mem_heap_free(prebuilt->blob_heap);
@ -2264,9 +2323,10 @@ row_sel_store_mysql_rec(
templ = prebuilt->mysql_template + i;
data = rec_get_nth_field(rec, templ->rec_field_no, &len);
data = rec_get_nth_field(rec, offsets,
templ->rec_field_no, &len);
if (rec_get_nth_field_extern_bit(rec, templ->rec_field_no)) {
if (rec_offs_nth_extern(offsets, templ->rec_field_no)) {
/* Copy an externally stored field to the temporary
heap */
@ -2280,7 +2340,7 @@ row_sel_store_mysql_rec(
causes an assert */
data = btr_rec_copy_externally_stored_field(rec,
templ->rec_field_no, &len,
offsets, templ->rec_field_no, &len,
extern_field_heap);
ut_a(len != UNIV_SQL_NULL);
@ -2436,6 +2496,8 @@ row_sel_get_clust_rec_for_mysql(
rec_t* old_vers;
ulint err;
trx_t* trx;
mem_heap_t* heap = mem_heap_create(100);
ulint* offsets = NULL;
*out_rec = NULL;
trx = thr_get_trx(thr);
@ -2466,9 +2528,8 @@ row_sel_get_clust_rec_for_mysql(
clustered index record did not exist in the read view of
trx. */
if (!rec_get_deleted_flag(rec)
if (!rec_get_deleted_flag(rec, sec_index->table->comp)
|| prebuilt->select_lock_type != LOCK_NONE) {
ut_print_timestamp(stderr);
fputs(" InnoDB: error clustered record"
" for sec rec not found\n"
@ -2476,10 +2537,14 @@ row_sel_get_clust_rec_for_mysql(
dict_index_name_print(stderr, trx, sec_index);
fputs("\n"
"InnoDB: sec index record ", stderr);
rec_print(stderr, rec);
offsets = rec_get_offsets(rec, sec_index,
ULINT_UNDEFINED, heap);
rec_print(stderr, rec, offsets);
fputs("\n"
"InnoDB: clust index record ", stderr);
rec_print(stderr, clust_rec);
offsets = rec_reget_offsets(clust_rec, clust_index,
offsets, ULINT_UNDEFINED, heap);
rec_print(stderr, clust_rec, offsets);
putc('\n', stderr);
trx_print(stderr, trx);
@ -2492,17 +2557,21 @@ row_sel_get_clust_rec_for_mysql(
goto func_exit;
}
offsets = rec_get_offsets(clust_rec, clust_index,
ULINT_UNDEFINED, heap);
if (prebuilt->select_lock_type != LOCK_NONE) {
/* Try to place a lock on the index record; we are searching
the clust rec with a unique condition, hence
we set a LOCK_REC_NOT_GAP type lock */
err = lock_clust_rec_read_check_and_lock(0, clust_rec,
clust_index,
clust_index, offsets,
prebuilt->select_lock_type,
LOCK_REC_NOT_GAP, thr);
if (err != DB_SUCCESS) {
mem_heap_free(heap);
return(err);
}
} else {
@ -2516,7 +2585,7 @@ row_sel_get_clust_rec_for_mysql(
if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED
&& !lock_clust_rec_cons_read_sees(clust_rec, clust_index,
trx->read_view)) {
offsets, trx->read_view)) {
err = row_sel_build_prev_vers_for_mysql(
trx->read_view, clust_index,
@ -2525,6 +2594,7 @@ row_sel_get_clust_rec_for_mysql(
if (err != DB_SUCCESS) {
mem_heap_free(heap);
return(err);
}
@ -2544,7 +2614,8 @@ row_sel_get_clust_rec_for_mysql(
visit through secondary index records that would not really
exist in our snapshot. */
if (clust_rec && (old_vers || rec_get_deleted_flag(rec))
if (clust_rec && (old_vers
|| rec_get_deleted_flag(rec, sec_index->table->comp))
&& !row_sel_sec_rec_is_for_clust_rec(rec, sec_index,
clust_rec, clust_index)) {
clust_rec = NULL;
@ -2566,6 +2637,7 @@ func_exit:
btr_pcur_store_position(prebuilt->clust_pcur, mtr);
}
mem_heap_free(heap);
return(DB_SUCCESS);
}
@ -2687,12 +2759,14 @@ void
row_sel_push_cache_row_for_mysql(
/*=============================*/
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
rec_t* rec) /* in: record to push */
rec_t* rec, /* in: record to push */
const ulint* offsets) /* in: rec_get_offsets() */
{
byte* buf;
ulint i;
ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_a(!prebuilt->templ_contains_blob);
if (prebuilt->fetch_cache[0] == NULL) {
@ -2718,7 +2792,7 @@ row_sel_push_cache_row_for_mysql(
ut_a(row_sel_store_mysql_rec(
prebuilt->fetch_cache[prebuilt->n_fetch_cached],
prebuilt, rec));
prebuilt, rec, offsets));
prebuilt->n_fetch_cached++;
}
@ -2735,6 +2809,8 @@ row_sel_try_search_shortcut_for_mysql(
/* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
rec_t** out_rec,/* out: record if found */
row_prebuilt_t* prebuilt,/* in: prebuilt struct */
ulint** offsets,/* in/out: for rec_reget_offsets(*out_rec) */
mem_heap_t* heap, /* in: heap for rec_reget_offsets() */
mtr_t* mtr) /* in: started mtr */
{
dict_index_t* index = prebuilt->index;
@ -2772,13 +2848,17 @@ row_sel_try_search_shortcut_for_mysql(
/* This is a non-locking consistent read: if necessary, fetch
a previous version of the record */
if (!lock_clust_rec_cons_read_sees(rec, index, trx->read_view)) {
*offsets = rec_reget_offsets(rec, index,
*offsets, ULINT_UNDEFINED, heap);
if (!lock_clust_rec_cons_read_sees(rec, index,
*offsets, trx->read_view)) {
return(SEL_RETRY);
}
if (rec_get_deleted_flag(rec)) {
if (rec_get_deleted_flag(rec, index->table->comp)) {
return(SEL_EXHAUSTED);
}
@ -2847,9 +2927,12 @@ row_search_for_mysql(
level is <= TRX_ISO_READ_COMMITTED,
then this is set to FALSE */
ibool success;
ibool comp;
ulint cnt = 0;
ulint next_offs;
mtr_t mtr;
mem_heap_t* heap;
ulint* offsets = NULL;
ut_ad(index && pcur && search_tuple);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
@ -3003,6 +3086,7 @@ row_search_for_mysql(
}
mtr_start(&mtr);
heap = mem_heap_create(100);
/*-------------------------------------------------------------*/
/* PHASE 2: Try fast adaptive hash index search if possible */
@ -3048,13 +3132,14 @@ row_search_for_mysql(
}
#endif
shortcut = row_sel_try_search_shortcut_for_mysql(&rec,
prebuilt, &mtr);
prebuilt, &offsets, heap, &mtr);
if (shortcut == SEL_FOUND) {
#ifdef UNIV_SEARCH_DEBUG
ut_a(0 == cmp_dtuple_rec(search_tuple, rec));
ut_a(0 == cmp_dtuple_rec(search_tuple,
rec, offsets));
#endif
if (!row_sel_store_mysql_rec(buf, prebuilt,
rec)) {
rec, offsets)) {
err = DB_TOO_BIG_RECORD;
/* We let the main loop to do the
@ -3082,7 +3167,7 @@ row_search_for_mysql(
/* NOTE that we do NOT store the cursor
position */
mem_heap_free(heap);
return(DB_SUCCESS);
} else if (shortcut == SEL_EXHAUSTED) {
@ -3106,6 +3191,7 @@ row_search_for_mysql(
/* NOTE that we do NOT store the cursor
position */
mem_heap_free(heap);
return(DB_RECORD_NOT_FOUND);
}
shortcut_fails_too_big_rec:
@ -3219,6 +3305,8 @@ rec_loop:
/* PHASE 4: Look for matching records in a loop */
rec = btr_pcur_get_rec(pcur);
comp = index->table->comp;
ut_ad(comp == page_is_comp(buf_frame_align(rec)));
/*
fputs("Using ", stderr);
dict_index_name_print(stderr, index);
@ -3247,7 +3335,9 @@ rec_loop:
a gap and therefore we do not set locks there. */
if (srv_locks_unsafe_for_binlog == FALSE) {
err = sel_set_rec_lock(rec, index,
offsets = rec_reget_offsets(rec, index,
offsets, ULINT_UNDEFINED, heap);
err = sel_set_rec_lock(rec, index, offsets,
prebuilt->select_lock_type,
LOCK_ORDINARY, thr);
}
@ -3267,9 +3357,11 @@ rec_loop:
/* Do sanity checks in case our cursor has bumped into page
corruption */
next_offs = rec_get_next_offs(rec);
next_offs = rec_get_next_offs(rec, comp);
if (next_offs >= UNIV_PAGE_SIZE || next_offs < PAGE_SUPREMUM) {
if (next_offs >= UNIV_PAGE_SIZE
|| next_offs <
(ulint) (comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM)) {
if (srv_force_recovery == 0 || moves_up == FALSE) {
ut_print_timestamp(stderr);
@ -3314,9 +3406,12 @@ rec_loop:
}
}
offsets = rec_reget_offsets(rec, index,
offsets, ULINT_UNDEFINED, heap);
if (srv_force_recovery > 0) {
if (!rec_validate(rec) || !btr_index_rec_validate(rec, index,
FALSE)) {
if (!rec_validate(rec, offsets)
|| !btr_index_rec_validate(rec, index, FALSE)) {
fprintf(stderr,
"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
"InnoDB: ",
@ -3344,7 +3439,7 @@ rec_loop:
/* fputs("Comparing rec and search tuple\n", stderr); */
if (0 != cmp_dtuple_rec(search_tuple, rec)) {
if (0 != cmp_dtuple_rec(search_tuple, rec, offsets)) {
if (prebuilt->select_lock_type != LOCK_NONE
&& set_also_gap_locks) {
@ -3356,6 +3451,7 @@ rec_loop:
if (srv_locks_unsafe_for_binlog == FALSE) {
err = sel_set_rec_lock(rec, index,
offsets,
prebuilt->select_lock_type,
LOCK_GAP, thr);
}
@ -3377,7 +3473,7 @@ rec_loop:
} else if (match_mode == ROW_SEL_EXACT_PREFIX) {
if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec)) {
if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec, offsets)) {
if (prebuilt->select_lock_type != LOCK_NONE
&& set_also_gap_locks) {
@ -3389,6 +3485,7 @@ rec_loop:
if (srv_locks_unsafe_for_binlog == FALSE) {
err = sel_set_rec_lock(rec, index,
offsets,
prebuilt->select_lock_type,
LOCK_GAP, thr);
}
@ -3420,27 +3517,27 @@ rec_loop:
is a non-delete marked record, then it is enough to lock its
existence with LOCK_REC_NOT_GAP. */
ulint lock_type;
if (!set_also_gap_locks
|| (unique_search && !rec_get_deleted_flag(rec))) {
err = sel_set_rec_lock(rec, index,
prebuilt->select_lock_type,
LOCK_REC_NOT_GAP, thr);
|| (unique_search && !rec_get_deleted_flag(rec, comp))) {
lock_type = LOCK_REC_NOT_GAP;
} else {
/* If innodb_locks_unsafe_for_binlog option is used,
we lock only the record, i.e. next-key locking is
we lock only the record, i.e., next-key locking is
not used. */
if (srv_locks_unsafe_for_binlog) {
err = sel_set_rec_lock(rec, index,
prebuilt->select_lock_type,
LOCK_REC_NOT_GAP, thr);
if (srv_locks_unsafe_for_binlog) {
lock_type = LOCK_REC_NOT_GAP;
} else {
err = sel_set_rec_lock(rec, index,
prebuilt->select_lock_type,
LOCK_ORDINARY, thr);
}
lock_type = LOCK_ORDINARY;
}
}
err = sel_set_rec_lock(rec, index, offsets,
prebuilt->select_lock_type,
lock_type, thr);
if (err != DB_SUCCESS) {
goto lock_wait_or_error;
@ -3463,7 +3560,7 @@ rec_loop:
if (srv_force_recovery < 5
&& !lock_clust_rec_cons_read_sees(rec, index,
trx->read_view)) {
offsets, trx->read_view)) {
err = row_sel_build_prev_vers_for_mysql(
trx->read_view, clust_index,
@ -3496,7 +3593,8 @@ rec_loop:
}
}
if (rec_get_deleted_flag(rec) && !cons_read_requires_clust_rec) {
if (rec_get_deleted_flag(rec, comp)
&& !cons_read_requires_clust_rec) {
/* The record is delete-marked: we can skip it if this is
not a consistent read which might see an earlier version
@ -3532,7 +3630,7 @@ rec_loop:
goto next_rec;
}
if (rec_get_deleted_flag(clust_rec)) {
if (rec_get_deleted_flag(clust_rec, comp)) {
/* The record is delete marked: we can skip it */
@ -3544,6 +3642,15 @@ rec_loop:
}
}
if (prebuilt->need_to_access_clustered) {
ut_ad(rec == clust_rec || index == clust_index);
offsets = rec_reget_offsets(rec, clust_index,
offsets, ULINT_UNDEFINED, heap);
} else {
offsets = rec_reget_offsets(rec, index,
offsets, ULINT_UNDEFINED, heap);
}
/* We found a qualifying row */
if (prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD
@ -3563,7 +3670,7 @@ rec_loop:
not cache rows because there the cursor is a scrollable
cursor. */
row_sel_push_cache_row_for_mysql(prebuilt, rec);
row_sel_push_cache_row_for_mysql(prebuilt, rec, offsets);
if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
@ -3573,11 +3680,13 @@ rec_loop:
goto next_rec;
} else {
if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
ut_memcpy(buf + 4, rec - rec_get_extra_size(rec),
rec_get_size(rec));
mach_write_to_4(buf, rec_get_extra_size(rec) + 4);
memcpy(buf + 4, rec - rec_offs_extra_size(offsets),
rec_offs_size(offsets));
mach_write_to_4(buf,
rec_offs_extra_size(offsets) + 4);
} else {
if (!row_sel_store_mysql_rec(buf, prebuilt, rec)) {
if (!row_sel_store_mysql_rec(buf, prebuilt,
rec, offsets)) {
err = DB_TOO_BIG_RECORD;
goto lock_wait_or_error;
@ -3586,7 +3695,7 @@ rec_loop:
if (prebuilt->clust_index_was_generated) {
row_sel_store_row_id_to_prebuilt(prebuilt, index_rec,
index);
index, offsets);
}
}
got_row:
@ -3688,6 +3797,7 @@ lock_wait_or_error:
fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */
trx->op_info = "";
mem_heap_free(heap);
return(err);
normal_return:
@ -3711,6 +3821,7 @@ normal_return:
trx->op_info = "";
mem_heap_free(heap);
return(ret);
}

View File

@ -430,6 +430,7 @@ row_undo_mod_del_unmark_sec_and_undo_update(
found = row_search_index_entry(index, entry, mode, &pcur, &mtr);
if (!found) {
heap = mem_heap_create(100);
fputs("InnoDB: error in sec index entry del undo in\n"
"InnoDB: ", stderr);
dict_index_name_print(stderr, trx, index);
@ -438,11 +439,14 @@ row_undo_mod_del_unmark_sec_and_undo_update(
dtuple_print(stderr, entry);
fputs("\n"
"InnoDB: record ", stderr);
rec_print(stderr, btr_pcur_get_rec(&pcur));
rec_print(stderr, btr_pcur_get_rec(&pcur),
rec_get_offsets(btr_pcur_get_rec(&pcur),
index, ULINT_UNDEFINED, heap));
putc('\n', stderr);
trx_print(stderr, trx);
fputs("\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr);
mem_heap_free(heap);
} else {
btr_cur_t* btr_cur = btr_pcur_get_btr_cur(&pcur);

View File

@ -151,6 +151,8 @@ row_undo_search_clust_to_pcur(
mtr_t mtr;
ibool ret;
rec_t* rec;
mem_heap_t* heap;
const ulint* offsets;
mtr_start(&mtr);
@ -161,8 +163,11 @@ row_undo_search_clust_to_pcur(
rec = btr_pcur_get_rec(&(node->pcur));
heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, clust_index, ULINT_UNDEFINED, heap);
if (!found || 0 != ut_dulint_cmp(node->roll_ptr,
row_get_rec_roll_ptr(rec, clust_index))) {
row_get_rec_roll_ptr(rec, clust_index, offsets))) {
/* We must remove the reservation on the undo log record
BEFORE releasing the latch on the clustered index page: this
@ -175,7 +180,7 @@ row_undo_search_clust_to_pcur(
ret = FALSE;
} else {
node->row = row_build(ROW_COPY_DATA, clust_index, rec,
node->heap);
offsets, node->heap);
btr_pcur_store_position(&(node->pcur), &mtr);
ret = TRUE;

View File

@ -301,19 +301,20 @@ recovery. */
void
row_upd_rec_sys_fields_in_recovery(
/*===============================*/
rec_t* rec, /* in: record */
ulint pos, /* in: TRX_ID position in rec */
dulint trx_id, /* in: transaction id */
dulint roll_ptr)/* in: roll ptr of the undo log record */
rec_t* rec, /* in: record */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint pos, /* in: TRX_ID position in rec */
dulint trx_id, /* in: transaction id */
dulint roll_ptr)/* in: roll ptr of the undo log record */
{
byte* field;
ulint len;
field = rec_get_nth_field(rec, pos, &len);
field = rec_get_nth_field(rec, offsets, pos, &len);
ut_ad(len == DATA_TRX_ID_LEN);
trx_write_trx_id(field, trx_id);
field = rec_get_nth_field(rec, pos + 1, &len);
field = rec_get_nth_field(rec, offsets, pos + 1, &len);
ut_ad(len == DATA_ROLL_PTR_LEN);
trx_write_roll_ptr(field, roll_ptr);
}
@ -361,8 +362,8 @@ row_upd_changes_field_size_or_external(
/* out: TRUE if the update changes the size of
some field in index or the field is external
in rec or update */
rec_t* rec, /* in: record in index */
dict_index_t* index, /* in: index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
upd_t* update) /* in: update vector */
{
upd_field_t* upd_field;
@ -372,6 +373,7 @@ row_upd_changes_field_size_or_external(
ulint n_fields;
ulint i;
ut_ad(rec_offs_validate(NULL, index, offsets));
n_fields = upd_get_n_fields(update);
for (i = 0; i < n_fields; i++) {
@ -380,19 +382,19 @@ row_upd_changes_field_size_or_external(
new_val = &(upd_field->new_val);
new_len = new_val->len;
if (new_len == UNIV_SQL_NULL) {
if (new_len == UNIV_SQL_NULL && !rec_offs_comp(offsets)) {
new_len = dtype_get_sql_null_size(
dict_index_get_nth_type(index, i));
}
old_len = rec_get_nth_field_size(rec, upd_field->field_no);
old_len = rec_offs_nth_size(offsets, upd_field->field_no);
if (old_len != new_len) {
return(TRUE);
}
if (rec_get_nth_field_extern_bit(rec, upd_field->field_no)) {
if (rec_offs_nth_extern(offsets, upd_field->field_no)) {
return(TRUE);
}
@ -414,15 +416,18 @@ a clustered index */
void
row_upd_rec_in_place(
/*=================*/
rec_t* rec, /* in/out: record where replaced */
upd_t* update) /* in: update vector */
rec_t* rec, /* in/out: record where replaced */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
upd_t* update) /* in: update vector */
{
upd_field_t* upd_field;
dfield_t* new_val;
ulint n_fields;
ulint i;
rec_set_info_bits(rec, update->info_bits);
ut_ad(rec_offs_validate(rec, NULL, offsets));
rec_set_info_bits(rec, rec_offs_comp(offsets), update->info_bits);
n_fields = upd_get_n_fields(update);
@ -430,7 +435,7 @@ row_upd_rec_in_place(
upd_field = upd_get_nth_field(update, i);
new_val = &(upd_field->new_val);
rec_set_nth_field(rec, upd_field->field_no,
rec_set_nth_field(rec, offsets, upd_field->field_no,
dfield_get_data(new_val),
dfield_get_len(new_val));
}
@ -695,6 +700,7 @@ row_upd_build_sec_rec_difference_binary(
upd_t* update;
ulint n_diff;
ulint i;
const ulint* offsets;
/* This function is used only for a secondary index */
ut_a(0 == (index->type & DICT_CLUSTERED));
@ -702,10 +708,11 @@ row_upd_build_sec_rec_difference_binary(
update = upd_create(dtuple_get_n_fields(entry), heap);
n_diff = 0;
offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
for (i = 0; i < dtuple_get_n_fields(entry); i++) {
data = rec_get_nth_field(rec, i, &len);
data = rec_get_nth_field(rec, offsets, i, &len);
dfield = dtuple_get_nth_field(entry, i);
@ -768,6 +775,7 @@ row_upd_build_difference_binary(
ulint trx_id_pos;
ibool extern_bit;
ulint i;
const ulint* offsets;
/* This function is used only for a clustered index */
ut_a(index->type & DICT_CLUSTERED);
@ -779,9 +787,11 @@ row_upd_build_difference_binary(
roll_ptr_pos = dict_index_get_sys_col_pos(index, DATA_ROLL_PTR);
trx_id_pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
for (i = 0; i < dtuple_get_n_fields(entry); i++) {
data = rec_get_nth_field(rec, i, &len);
data = rec_get_nth_field(rec, offsets, i, &len);
dfield = dtuple_get_nth_field(entry, i);
@ -793,7 +803,7 @@ row_upd_build_difference_binary(
goto skip_compare;
}
extern_bit = rec_get_nth_field_extern_bit(rec, i);
extern_bit = rec_offs_nth_extern(offsets, i);
if (extern_bit != upd_ext_vec_contains(ext_vec, n_ext_vec, i)
|| !dfield_data_is_binary_equal(dfield, len, data)) {
@ -1117,6 +1127,7 @@ void
row_upd_copy_columns(
/*=================*/
rec_t* rec, /* in: record in a clustered index */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
sym_node_t* column) /* in: first column in a column list, or
NULL */
{
@ -1124,7 +1135,7 @@ row_upd_copy_columns(
ulint len;
while (column) {
data = rec_get_nth_field(rec,
data = rec_get_nth_field(rec, offsets,
column->field_nos[SYM_CLUST_FIELD_NO],
&len);
eval_node_copy_and_alloc_val(column, data, len);
@ -1171,7 +1182,9 @@ row_upd_store_row(
dict_index_t* clust_index;
upd_t* update;
rec_t* rec;
mem_heap_t* heap;
const ulint* offsets;
ut_ad(node->pcur->latch_mode != BTR_NO_LATCHES);
if (node->row != NULL) {
@ -1183,10 +1196,12 @@ row_upd_store_row(
rec = btr_pcur_get_rec(node->pcur);
node->row = row_build(ROW_COPY_DATA, clust_index, rec, node->heap);
heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, clust_index, ULINT_UNDEFINED, heap);
node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
node->heap);
node->ext_vec = mem_heap_alloc(node->heap, sizeof(ulint)
* rec_get_n_fields(rec));
* rec_offs_n_fields(offsets));
if (node->is_delete) {
update = NULL;
} else {
@ -1194,7 +1209,8 @@ row_upd_store_row(
}
node->n_ext_vec = btr_push_update_extern_fields(node->ext_vec,
rec, update);
offsets, update);
mem_heap_free(heap);
}
/***************************************************************
@ -1247,7 +1263,8 @@ row_upd_sec_index_entry(
dtuple_print(stderr, entry);
fputs("\n"
"InnoDB: record ", stderr);
rec_print(stderr, rec);
rec_print(stderr, rec,
rec_get_offsets(rec, index, ULINT_UNDEFINED, heap));
putc('\n', stderr);
trx_print(stderr, trx);
@ -1259,7 +1276,7 @@ row_upd_sec_index_entry(
delete marked if we return after a lock wait in
row_ins_index_entry below */
if (!rec_get_deleted_flag(rec)) {
if (!rec_get_deleted_flag(rec, index->table->comp)) {
err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE,
thr, &mtr);
if (err == DB_SUCCESS && check_ref) {
@ -1362,6 +1379,7 @@ row_upd_clust_rec_by_insert(
table = node->table;
pcur = node->pcur;
btr_cur = btr_pcur_get_btr_cur(pcur);
heap = mem_heap_create(500);
if (node->state != UPD_NODE_INSERT_CLUSTERED) {
@ -1369,7 +1387,7 @@ row_upd_clust_rec_by_insert(
btr_cur, TRUE, thr, mtr);
if (err != DB_SUCCESS) {
mtr_commit(mtr);
mem_heap_free(heap);
return(err);
}
@ -1379,7 +1397,9 @@ row_upd_clust_rec_by_insert(
record is removed from the index tree, or updated. */
btr_cur_mark_extern_inherited_fields(btr_cur_get_rec(btr_cur),
node->update, mtr);
rec_get_offsets(btr_cur_get_rec(btr_cur),
dict_table_get_first_index(table),
ULINT_UNDEFINED, heap), node->update, mtr);
if (check_ref) {
/* NOTE that the following call loses
the position of pcur ! */
@ -1399,8 +1419,6 @@ row_upd_clust_rec_by_insert(
node->state = UPD_NODE_INSERT_CLUSTERED;
heap = mem_heap_create(500);
entry = row_build_index_entry(node->row, index, heap);
row_upd_index_replace_new_col_vals(entry, index, node->update, NULL);
@ -1452,7 +1470,8 @@ row_upd_clust_rec(
pcur = node->pcur;
btr_cur = btr_pcur_get_btr_cur(pcur);
ut_ad(FALSE == rec_get_deleted_flag(btr_pcur_get_rec(pcur)));
ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
index->table->comp));
/* Try optimistic updating of the record, keeping changes within
the page; we do not check locks because we assume the x-lock on the
@ -1488,7 +1507,8 @@ row_upd_clust_rec(
ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
ut_ad(FALSE == rec_get_deleted_flag(btr_pcur_get_rec(pcur)));
ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
index->table->comp));
err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG, btr_cur,
&big_rec, node->update,
@ -1496,12 +1516,17 @@ row_upd_clust_rec(
mtr_commit(mtr);
if (err == DB_SUCCESS && big_rec) {
mem_heap_t* heap;
rec_t* rec;
mtr_start(mtr);
heap = mem_heap_create(100);
rec = btr_cur_get_rec(btr_cur);
ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
err = btr_store_big_rec_extern_fields(index,
btr_cur_get_rec(btr_cur),
big_rec, mtr);
err = btr_store_big_rec_extern_fields(index, rec,
rec_get_offsets(rec, index, ULINT_UNDEFINED, heap),
big_rec, mtr);
mem_heap_free(heap);
mtr_commit(mtr);
}
@ -1585,7 +1610,10 @@ row_upd_clust_step(
ulint err;
mtr_t* mtr;
mtr_t mtr_buf;
rec_t* rec;
mem_heap_t* heap;
const ulint* offsets;
index = dict_table_get_first_index(node->table);
check_ref = row_upd_index_is_referenced(index, thr_get_trx(thr));
@ -1641,13 +1669,16 @@ row_upd_clust_step(
}
}
rec = btr_pcur_get_rec(pcur);
heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
if (!node->has_clust_rec_x_lock) {
err = lock_clust_rec_modify_check_and_lock(0,
btr_pcur_get_rec(pcur),
index, thr);
rec, index, offsets, thr);
if (err != DB_SUCCESS) {
mtr_commit(mtr);
mem_heap_free(heap);
return(err);
}
}
@ -1655,6 +1686,7 @@ row_upd_clust_step(
/* NOTE: the following function calls will also commit mtr */
if (node->is_delete) {
mem_heap_free(heap);
err = row_upd_del_mark_clust_rec(node, index, thr, check_ref,
mtr);
if (err != DB_SUCCESS) {
@ -1674,12 +1706,13 @@ row_upd_clust_step(
if (!node->in_mysql_interface) {
/* Copy the necessary columns from clust_rec and calculate the
new values to set */
row_upd_copy_columns(btr_pcur_get_rec(pcur),
row_upd_copy_columns(rec, offsets,
UT_LIST_GET_FIRST(node->columns));
row_upd_eval_new_vals(node->update);
}
mem_heap_free(heap);
if (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE) {
err = row_upd_clust_rec(node, index, thr, mtr);
@ -1935,6 +1968,7 @@ row_upd_in_place_in_select(
btr_pcur_t* pcur;
btr_cur_t* btr_cur;
ulint err;
mem_heap_t* heap;
ut_ad(sel_node->select_will_do_update);
ut_ad(sel_node->latch_mode == BTR_MODIFY_LEAF);
@ -1950,11 +1984,15 @@ row_upd_in_place_in_select(
/* Copy the necessary columns from clust_rec and calculate the new
values to set */
row_upd_copy_columns(btr_pcur_get_rec(pcur),
UT_LIST_GET_FIRST(node->columns));
heap = mem_heap_create(100);
row_upd_copy_columns(btr_pcur_get_rec(pcur), rec_get_offsets(
btr_pcur_get_rec(pcur), btr_cur->index, ULINT_UNDEFINED, heap),
UT_LIST_GET_FIRST(node->columns));
mem_heap_free(heap);
row_upd_eval_new_vals(node->update);
ut_ad(FALSE == rec_get_deleted_flag(btr_pcur_get_rec(pcur)));
ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
btr_cur->index->table->comp));
ut_ad(node->cmpl_info & UPD_NODE_NO_SIZE_CHANGE);
ut_ad(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE);

View File

@ -41,10 +41,12 @@ row_vers_impl_x_locked_off_kernel(
transaction; NOTE that the kernel mutex is
temporarily released! */
rec_t* rec, /* in: record in a secondary index */
dict_index_t* index) /* in: the secondary index */
dict_index_t* index, /* in: the secondary index */
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
dict_index_t* clust_index;
rec_t* clust_rec;
ulint* clust_offsets;
rec_t* version;
rec_t* prev_version;
dulint trx_id;
@ -59,6 +61,7 @@ row_vers_impl_x_locked_off_kernel(
ibool rec_del;
ulint err;
mtr_t mtr;
ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@ -96,7 +99,10 @@ row_vers_impl_x_locked_off_kernel(
return(NULL);
}
trx_id = row_get_rec_trx_id(clust_rec, clust_index);
heap = mem_heap_create(1024);
clust_offsets = rec_get_offsets(clust_rec, clust_index,
ULINT_UNDEFINED, heap);
trx_id = row_get_rec_trx_id(clust_rec, clust_index, clust_offsets);
mtr_s_lock(&(purge_sys->latch), &mtr);
@ -106,19 +112,27 @@ row_vers_impl_x_locked_off_kernel(
/* The transaction that modified or inserted clust_rec is no
longer active: no implicit lock on rec */
mem_heap_free(heap);
mtr_commit(&mtr);
return(NULL);
}
if (!lock_check_trx_id_sanity(trx_id, clust_rec, clust_index, TRUE)) {
if (!lock_check_trx_id_sanity(trx_id, clust_rec, clust_index,
clust_offsets, TRUE)) {
/* Corruption noticed: try to avoid a crash by returning */
mem_heap_free(heap);
mtr_commit(&mtr);
return(NULL);
}
comp = index->table->comp;
ut_ad(index->table == clust_index->table);
ut_ad(comp == page_is_comp(buf_frame_align(rec)));
ut_ad(comp == page_is_comp(buf_frame_align(clust_rec)));
/* We look up if some earlier version, which was modified by the trx_id
transaction, of the clustered index record would require rec to be in
a different state (delete marked or unmarked, or have different field
@ -128,11 +142,10 @@ row_vers_impl_x_locked_off_kernel(
different state, then the trx_id transaction has not yet had time to
modify rec, and does not necessarily have an implicit x-lock on rec. */
rec_del = rec_get_deleted_flag(rec);
rec_del = rec_get_deleted_flag(rec, comp);
trx = NULL;
version = clust_rec;
heap = NULL;
for (;;) {
mutex_exit(&kernel_mutex);
@ -146,18 +159,16 @@ row_vers_impl_x_locked_off_kernel(
heap2 = heap;
heap = mem_heap_create(1024);
err = trx_undo_prev_version_build(clust_rec, &mtr, version,
clust_index, heap,
&prev_version);
if (heap2) {
mem_heap_free(heap2); /* version was stored in heap2,
if heap2 != NULL */
}
clust_index, clust_offsets, heap,
&prev_version);
mem_heap_free(heap2); /* free version and clust_offsets */
if (prev_version) {
clust_offsets = rec_get_offsets(prev_version,
clust_index, ULINT_UNDEFINED, heap);
row = row_build(ROW_COPY_POINTERS, clust_index,
prev_version, heap);
prev_version, clust_offsets, heap);
entry = row_build_index_entry(row, index, heap);
}
@ -189,11 +200,11 @@ row_vers_impl_x_locked_off_kernel(
if prev_version would require rec to be in a different
state. */
vers_del = rec_get_deleted_flag(prev_version);
vers_del = rec_get_deleted_flag(prev_version, comp);
/* We check if entry and rec are identified in the alphabetical
ordering */
if (0 == cmp_dtuple_rec(entry, rec)) {
if (0 == cmp_dtuple_rec(entry, rec, offsets)) {
/* The delete marks of rec and prev_version should be
equal for rec to be in the state required by
prev_version */
@ -211,7 +222,7 @@ row_vers_impl_x_locked_off_kernel(
dtuple_set_types_binary(entry,
dtuple_get_n_fields(entry));
if (0 != cmp_dtuple_rec(entry, rec)) {
if (0 != cmp_dtuple_rec(entry, rec, offsets)) {
trx = trx_get_on_id(trx_id);
@ -226,7 +237,8 @@ row_vers_impl_x_locked_off_kernel(
break;
}
prev_trx_id = row_get_rec_trx_id(prev_version, clust_index);
prev_trx_id = row_get_rec_trx_id(prev_version, clust_index,
clust_offsets);
if (0 != ut_dulint_cmp(trx_id, prev_trx_id)) {
/* The versions modified by the trx_id transaction end
@ -297,12 +309,14 @@ row_vers_old_has_index_entry(
rec_t* version;
rec_t* prev_version;
dict_index_t* clust_index;
ulint* clust_offsets;
mem_heap_t* heap;
mem_heap_t* heap2;
dtuple_t* row;
dtuple_t* entry;
ulint err;
ibool comp;
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains(mtr, buf_block_align(rec),
MTR_MEMO_PAGE_S_FIX));
@ -313,10 +327,15 @@ row_vers_old_has_index_entry(
clust_index = dict_table_get_first_index(index->table);
if (also_curr && !rec_get_deleted_flag(rec)) {
comp = index->table->comp;
ut_ad(comp == page_is_comp(buf_frame_align(rec)));
heap = mem_heap_create(1024);
clust_offsets = rec_get_offsets(rec, clust_index,
ULINT_UNDEFINED, heap);
heap = mem_heap_create(1024);
row = row_build(ROW_COPY_POINTERS, clust_index, rec, heap);
if (also_curr && !rec_get_deleted_flag(rec, comp)) {
row = row_build(ROW_COPY_POINTERS, clust_index,
rec, clust_offsets, heap);
entry = row_build_index_entry(row, index, heap);
/* NOTE that we cannot do the comparison as binary
@ -331,24 +350,17 @@ row_vers_old_has_index_entry(
return(TRUE);
}
mem_heap_free(heap);
}
version = rec;
heap = NULL;
for (;;) {
heap2 = heap;
heap = mem_heap_create(1024);
err = trx_undo_prev_version_build(rec, mtr, version,
clust_index, heap,
&prev_version);
if (heap2) {
mem_heap_free(heap2); /* version was stored in heap2,
if heap2 != NULL */
}
clust_index, clust_offsets, heap,
&prev_version);
mem_heap_free(heap2); /* free version and clust_offsets */
if (err != DB_SUCCESS || !prev_version) {
/* Versions end here */
@ -358,9 +370,12 @@ row_vers_old_has_index_entry(
return(FALSE);
}
if (!rec_get_deleted_flag(prev_version)) {
clust_offsets = rec_get_offsets(prev_version, clust_index,
ULINT_UNDEFINED, heap);
if (!rec_get_deleted_flag(prev_version, comp)) {
row = row_build(ROW_COPY_POINTERS, clust_index,
prev_version, heap);
prev_version, clust_offsets, heap);
entry = row_build_index_entry(row, index, heap);
/* NOTE that we cannot do the comparison as binary
@ -412,6 +427,7 @@ row_vers_build_for_consistent_read(
mem_heap_t* heap2;
byte* buf;
ulint err;
ulint* offsets;
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)
@ -420,22 +436,23 @@ row_vers_build_for_consistent_read(
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(!read_view_sees_trx_id(view, row_get_rec_trx_id(rec, index)));
heap = mem_heap_create(1024);
offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
ut_ad(!read_view_sees_trx_id(view,
row_get_rec_trx_id(rec, index, offsets)));
rw_lock_s_lock(&(purge_sys->latch));
version = rec;
heap = NULL;
for (;;) {
heap2 = heap;
heap = mem_heap_create(1024);
err = trx_undo_prev_version_build(rec, mtr, version, index,
heap, &prev_version);
if (heap2) {
mem_heap_free(heap2); /* version was stored in heap2,
if heap2 != NULL */
}
offsets, heap, &prev_version);
mem_heap_free(heap2); /* free version and offsets */
if (err != DB_SUCCESS) {
break;
@ -449,16 +466,17 @@ row_vers_build_for_consistent_read(
break;
}
prev_trx_id = row_get_rec_trx_id(prev_version, index);
offsets = rec_get_offsets(prev_version, index,
ULINT_UNDEFINED, heap);
prev_trx_id = row_get_rec_trx_id(prev_version, index, offsets);
if (read_view_sees_trx_id(view, prev_trx_id)) {
/* The view already sees this version: we can copy
it to in_heap and return */
buf = mem_heap_alloc(in_heap, rec_get_size(
prev_version));
*old_vers = rec_copy(buf, prev_version);
buf = mem_heap_alloc(in_heap, rec_offs_size(offsets));
*old_vers = rec_copy(buf, prev_version, offsets);
err = DB_SUCCESS;
break;

View File

@ -44,6 +44,7 @@ Created 10/8/1995 Heikki Tuuri
#include "buf0flu.h"
#include "btr0sea.h"
#include "dict0load.h"
#include "dict0boot.h"
#include "srv0start.h"
#include "row0mysql.h"
@ -845,6 +846,7 @@ srv_init(void)
{
srv_conc_slot_t* conc_slot;
srv_slot_t* slot;
dict_table_t* table;
ulint i;
srv_sys = mem_alloc(sizeof(srv_sys_t));
@ -894,6 +896,31 @@ srv_init(void)
UT_LIST_INIT(srv_sys->tasks);
/* create dummy table and index for old-style infimum and supremum */
table = dict_mem_table_create("SYS_DUMMY1",
DICT_HDR_SPACE, 1, FALSE);
dict_mem_table_add_col(table, "DUMMY", DATA_CHAR,
DATA_ENGLISH | DATA_NOT_NULL, 8, 0);
srv_sys->dummy_ind1 = dict_mem_index_create("SYS_DUMMY1",
"SYS_DUMMY1", DICT_HDR_SPACE, 0, 1);
dict_index_add_col(srv_sys->dummy_ind1,
dict_table_get_nth_col(table, 0), 0, 0);
srv_sys->dummy_ind1->table = table;
/* create dummy table and index for new-style infimum and supremum */
table = dict_mem_table_create("SYS_DUMMY2",
DICT_HDR_SPACE, 1, TRUE);
dict_mem_table_add_col(table, "DUMMY", DATA_CHAR,
DATA_ENGLISH | DATA_NOT_NULL, 8, 0);
srv_sys->dummy_ind2 = dict_mem_index_create("SYS_DUMMY2",
"SYS_DUMMY2", DICT_HDR_SPACE, 0, 1);
dict_index_add_col(srv_sys->dummy_ind2,
dict_table_get_nth_col(table, 0), 0, 0);
srv_sys->dummy_ind2->table = table;
/* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
srv_sys->dummy_ind1->cached = srv_sys->dummy_ind2->cached = TRUE;
/* Init the server concurrency restriction data structures */
os_fast_mutex_init(&srv_conc_mutex);

View File

@ -38,16 +38,18 @@ trx_undof_page_add_undo_rec_log(
ulint new_free, /* in: end offset of the entry */
mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
ulint len;
byte* log_ptr;
const byte* log_end;
ulint len;
log_ptr = mlog_open(mtr, 30 + MLOG_BUF_MARGIN);
log_ptr = mlog_open(mtr, 11 + 13 + MLOG_BUF_MARGIN);
if (log_ptr == NULL) {
return;
}
log_end = &log_ptr[11 + 13 + MLOG_BUF_MARGIN];
log_ptr = mlog_write_initial_log_record_fast(undo_page,
MLOG_UNDO_INSERT, log_ptr, mtr);
len = new_free - old_free - 4;
@ -55,14 +57,11 @@ trx_undof_page_add_undo_rec_log(
mach_write_to_2(log_ptr, len);
log_ptr += 2;
if (len < 256) {
ut_memcpy(log_ptr, undo_page + old_free + 2, len);
log_ptr += len;
}
mlog_close(mtr, log_ptr);
if (len >= MLOG_BUF_MARGIN) {
if (log_ptr + len <= log_end) {
memcpy(log_ptr, undo_page + old_free + 2, len);
mlog_close(mtr, log_ptr + len);
} else {
mlog_close(mtr, log_ptr);
mlog_catenate_string(mtr, undo_page + old_free + 2, len);
}
}
@ -404,6 +403,7 @@ trx_undo_page_report_modify(
delete marking is done */
rec_t* rec, /* in: clustered index record which
has NOT yet been modified */
const ulint* offsets, /* in: rec_get_offsets(rec, index) */
upd_t* update, /* in: update vector which tells the
columns to be updated; in the case of
a delete, this should be set to NULL */
@ -430,6 +430,7 @@ trx_undo_page_report_modify(
ulint i;
ut_a(index->type & DICT_CLUSTERED);
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
+ TRX_UNDO_PAGE_TYPE) == TRX_UNDO_UPDATE);
table = index->table;
@ -454,7 +455,7 @@ trx_undo_page_report_modify(
/* Store first some general parameters to the undo log */
if (update) {
if (rec_get_deleted_flag(rec)) {
if (rec_get_deleted_flag(rec, table->comp)) {
type_cmpl = TRX_UNDO_UPD_DEL_REC;
} else {
type_cmpl = TRX_UNDO_UPD_EXIST_REC;
@ -479,14 +480,15 @@ trx_undo_page_report_modify(
/*----------------------------------------*/
/* Store the state of the info bits */
bits = rec_get_info_bits(rec);
bits = rec_get_info_bits(rec, table->comp);
mach_write_to_1(ptr, bits);
ptr += 1;
/* Store the values of the system columns */
trx_id = dict_index_rec_get_sys_col(index, DATA_TRX_ID, rec);
roll_ptr = dict_index_rec_get_sys_col(index, DATA_ROLL_PTR, rec);
trx_id = dict_index_rec_get_sys_col(index, offsets,
DATA_TRX_ID, rec);
roll_ptr = dict_index_rec_get_sys_col(index, offsets,
DATA_ROLL_PTR, rec);
len = mach_dulint_write_compressed(ptr, trx_id);
ptr += len;
@ -499,7 +501,7 @@ trx_undo_page_report_modify(
for (i = 0; i < dict_index_get_n_unique(index); i++) {
field = rec_get_nth_field(rec, i, &flen);
field = rec_get_nth_field(rec, offsets, i, &flen);
if (trx_undo_left(undo_page, ptr) < 4) {
@ -547,14 +549,14 @@ trx_undo_page_report_modify(
ptr += len;
/* Save the old value of field */
field = rec_get_nth_field(rec, pos, &flen);
field = rec_get_nth_field(rec, offsets, pos, &flen);
if (trx_undo_left(undo_page, ptr) < 5) {
return(0);
}
if (rec_get_nth_field_extern_bit(rec, pos)) {
if (rec_offs_nth_extern(offsets, pos)) {
/* If a field has external storage, we add to
flen the flag */
@ -631,7 +633,7 @@ trx_undo_page_report_modify(
ptr += len;
/* Save the old value of field */
field = rec_get_nth_field(rec, pos, &flen);
field = rec_get_nth_field(rec, offsets, pos, &flen);
if (trx_undo_left(undo_page, ptr) < 5) {
@ -1008,7 +1010,9 @@ trx_undo_report_row_operation(
ibool is_insert;
trx_rseg_t* rseg;
mtr_t mtr;
mem_heap_t* heap;
ulint* offsets = NULL;
ut_a(index->type & DICT_CLUSTERED);
if (flags & BTR_NO_UNDO_LOG_FLAG) {
@ -1019,7 +1023,6 @@ trx_undo_report_row_operation(
}
ut_ad(thr);
ut_a(index->type & DICT_CLUSTERED);
ut_ad((op_type != TRX_UNDO_INSERT_OP)
|| (clust_entry && !update && !rec));
@ -1063,6 +1066,8 @@ trx_undo_report_row_operation(
mtr_start(&mtr);
heap = mem_heap_create(100);
for (;;) {
undo_page = buf_page_get_gen(undo->space, page_no,
RW_X_LATCH, undo->guess_page,
@ -1079,9 +1084,10 @@ trx_undo_report_row_operation(
index, clust_entry,
&mtr);
} else {
offsets = rec_reget_offsets(rec, index,
offsets, ULINT_UNDEFINED, heap);
offset = trx_undo_page_report_modify(undo_page, trx,
index, rec, update,
cmpl_info, &mtr);
index, rec, offsets, update, cmpl_info, &mtr);
}
if (offset == 0) {
@ -1123,7 +1129,7 @@ trx_undo_report_row_operation(
mutex_exit(&(trx->undo_mutex));
mtr_commit(&mtr);
mem_heap_free(heap);
return(DB_OUT_OF_FILE_SPACE);
}
}
@ -1140,6 +1146,7 @@ trx_undo_report_row_operation(
*roll_ptr = trx_undo_build_roll_ptr(is_insert, rseg->id, page_no,
offset);
mem_heap_free(heap);
return(DB_SUCCESS);
}
@ -1236,6 +1243,7 @@ trx_undo_prev_version_build(
index_rec page and purge_view */
rec_t* rec, /* in: version of a clustered index record */
dict_index_t* index, /* in: clustered index */
ulint* offsets,/* in: rec_get_offsets(rec, index) */
mem_heap_t* heap, /* in: memory heap from which the memory
needed is allocated */
rec_t** old_vers)/* out, own: previous version, or NULL if
@ -1258,7 +1266,7 @@ trx_undo_prev_version_build(
ibool dummy_extern;
byte* buf;
ulint err;
ulint* index_offsets = NULL;
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
#endif /* UNIV_SYNC_DEBUG */
@ -1266,21 +1274,25 @@ trx_undo_prev_version_build(
MTR_MEMO_PAGE_S_FIX) ||
mtr_memo_contains(index_mtr, buf_block_align(index_rec),
MTR_MEMO_PAGE_X_FIX));
ut_ad(rec_offs_validate(rec, index, offsets));
if (!(index->type & DICT_CLUSTERED)) {
fprintf(stderr, "InnoDB: Error: trying to access"
" update undo rec for non-clustered index %s\n"
"InnoDB: Submit a detailed bug report to"
" http://bugs.mysql.com\n"
"InnoDB: index record ", index->name);
rec_print(stderr, index_rec);
index_offsets = rec_get_offsets(index_rec, index,
ULINT_UNDEFINED, heap);
rec_print(stderr, index_rec, index_offsets);
fputs("\n"
"InnoDB: record version ", stderr);
rec_print(stderr, rec);
rec_print(stderr, rec, offsets);
putc('\n', stderr);
return(DB_ERROR);
}
roll_ptr = row_get_rec_roll_ptr(rec, index);
roll_ptr = row_get_rec_roll_ptr(rec, index, offsets);
old_roll_ptr = roll_ptr;
*old_vers = NULL;
@ -1292,7 +1304,7 @@ trx_undo_prev_version_build(
return(DB_SUCCESS);
}
rec_trx_id = row_get_rec_trx_id(rec, index);
rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
err = trx_undo_get_undo_rec(roll_ptr, rec_trx_id, &undo_rec, heap);
@ -1341,10 +1353,12 @@ trx_undo_prev_version_build(
ut_print_buf(stderr, undo_rec, 150);
fputs("\n"
"InnoDB: index record ", stderr);
rec_print(stderr, index_rec);
index_offsets = rec_get_offsets(index_rec, index,
ULINT_UNDEFINED, heap);
rec_print(stderr, index_rec, index_offsets);
fputs("\n"
"InnoDB: record version ", stderr);
rec_print(stderr, rec);
rec_print(stderr, rec, offsets);
fprintf(stderr, "\n"
"InnoDB: Record trx id %lu %lu, update rec trx id %lu %lu\n"
"InnoDB: Roll ptr in rec %lu %lu, in update rec %lu %lu\n",
@ -1358,11 +1372,10 @@ trx_undo_prev_version_build(
(ulong) ut_dulint_get_low(roll_ptr));
trx_purge_sys_print();
return(DB_ERROR);
}
if (row_upd_changes_field_size_or_external(rec, index, update)) {
if (row_upd_changes_field_size_or_external(index, offsets, update)) {
ulint* ext_vect;
ulint n_ext_vect;
@ -1372,27 +1385,28 @@ trx_undo_prev_version_build(
those fields that update updates to become externally stored
fields. Store the info to ext_vect: */
ext_vect = mem_alloc(sizeof(ulint) * rec_get_n_fields(rec));
n_ext_vect = btr_push_update_extern_fields(ext_vect, rec,
ext_vect = mem_alloc(sizeof(ulint)
* rec_offs_n_fields(offsets));
n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets,
update);
entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec,
heap);
row_upd_index_replace_new_col_vals(entry, index, update, heap);
buf = mem_heap_alloc(heap, rec_get_converted_size(entry));
buf = mem_heap_alloc(heap,
rec_get_converted_size(index, entry));
*old_vers = rec_convert_dtuple_to_rec(buf, entry);
*old_vers = rec_convert_dtuple_to_rec(buf, index, entry);
/* Now set the extern bits in the old version of the record */
rec_set_field_extern_bits(*old_vers, ext_vect, n_ext_vect,
NULL);
rec_set_field_extern_bits(*old_vers, index,
ext_vect, n_ext_vect, NULL);
mem_free(ext_vect);
} else {
buf = mem_heap_alloc(heap, rec_get_size(rec));
*old_vers = rec_copy(buf, rec);
row_upd_rec_in_place(*old_vers, update);
buf = mem_heap_alloc(heap, rec_offs_size(offsets));
*old_vers = rec_copy(buf, rec, offsets);
rec_offs_make_valid(*old_vers, index, offsets);
row_upd_rec_in_place(*old_vers, offsets, update);
}
return(DB_SUCCESS);

View File

@ -880,7 +880,6 @@ trx_undo_free_page(
list */
ulint space, /* in: space */
ulint hdr_page_no, /* in: header page number */
ulint hdr_offset, /* in: header offset */
ulint page_no, /* in: page number to free: must not be the
header page */
mtr_t* mtr) /* in: mtr which does not have a latch to any
@ -893,7 +892,6 @@ trx_undo_free_page(
trx_rsegf_t* rseg_header;
ulint hist_size;
UT_NOT_USED(hdr_offset);
ut_a(hdr_page_no != page_no);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
@ -950,8 +948,7 @@ trx_undo_free_page_in_rollback(
#endif /* UNIV_SYNC_DEBUG */
last_page_no = trx_undo_free_page(undo->rseg, FALSE, undo->space,
undo->hdr_page_no, undo->hdr_offset,
page_no, mtr);
undo->hdr_page_no, page_no, mtr);
undo->last_page_no = last_page_no;
undo->size--;
@ -1119,7 +1116,7 @@ loop:
trx_undo_empty_header_page(space, hdr_page_no, hdr_offset,
&mtr);
} else {
trx_undo_free_page(rseg, TRUE, space, hdr_page_no, hdr_offset,
trx_undo_free_page(rseg, TRUE, space, hdr_page_no,
page_no, &mtr);
}

View File

@ -3576,7 +3576,7 @@ create_table_def(
TABLE* form, /* in: information on table
columns and indexes */
const char* table_name, /* in: table name */
const char* path_of_temp_table)/* in: if this is a table explicitly
const char* path_of_temp_table,/* in: if this is a table explicitly
created by the user with the
TEMPORARY keyword, then this
parameter is the dir path where the
@ -3584,6 +3584,7 @@ create_table_def(
an .ibd file for it (no .ibd extension
in the path, though); otherwise this
is NULL */
ibool comp) /* in: TRUE=compact record format */
{
Field* field;
dict_table_t* table;
@ -3604,7 +3605,7 @@ create_table_def(
/* We pass 0 as the space id, and determine at a lower level the space
id where to store the table */
table = dict_mem_table_create((char*) table_name, 0, n_cols);
table = dict_mem_table_create(table_name, 0, n_cols, comp);
if (path_of_temp_table) {
table->dir_path_of_temp_table =
@ -3868,12 +3869,9 @@ ha_innobase::create(
/* Create the table definition in InnoDB */
if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
error = create_table_def(trx, form, norm_name, name2);
} else {
error = create_table_def(trx, form, norm_name, NULL);
}
error = create_table_def(trx, form, norm_name,
create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
!(form->db_options_in_use & HA_OPTION_PACK_RECORD));
if (error) {
innobase_commit_low(trx);