Commit df4c733d authored by marko's avatar marko

branches/zip: Initialize dfield_t::ext as soon as possible. This should

fix the bugs introduced in r1591.

row_rec_to_index_entry_low(): Clear "n_ext".  Do not allow it to be NULL.
Add const qualifier to dict_index_t*.

row_rec_to_index_entry(): Add the parameters "offsets" and "n_ext".

btr_cur_optimistic_update(): Add an assertion that there are no externally
stored columns.  Remove the unreachable call to btr_cur_unmark_extern_fields()
and the preceding unnecessary call to rec_get_offsets().

btr_push_update_extern_fields(): Remove the parameters index, offsets.
Only report the additional externally stored columns of the update vector.

row_build(), trx_undo_rec_get_partial_row(): Flag externally stored columns
also with dfield_set_ext().

rec_copy_prefix_to_dtuple(): Assert that there are no externally stored
columns in the prefix.

row_build_row_ref(): Note and assert that the index is a secondary index,
and assert that there are no externally stored columns.

row_build_row_ref_fast(): Assert that there are no externally stored columns.

rec_offs_get_n_alloc(): Expose the function.

row_build_row_ref_in_tuple(): Assert that there are no externally stored
columns in a record of a secondary index.

row_build_row_ref_from_row(): Assert that there are no externally stored
columns.

row_upd_check_references_constraints(): Add the parameter offsets, to
avoid a redundant call to rec_get_offsets().

row_upd_del_mark_clust_rec(): Add the parameter offsets.  Remove
duplicated code.

row_ins_index_entry_set_vals(): Copy the external storage flag.

sel_pop_prefetched_row(): Assert that there are no externally stored
columns.

row_scan_and_check_index(): Copy offsets to a temporary heap across
the invocation of row_rec_to_index_entry().
parent d49217dd
......@@ -1802,6 +1802,7 @@ btr_cur_optimistic_update(
trx_t* trx;
mem_heap_t* heap;
ulint i;
ulint n_ext;
ulint* offsets;
block = btr_cur_get_block(cursor);
......@@ -1851,7 +1852,10 @@ any_extern:
page_cursor = btr_cur_get_page_cur(cursor);
new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
new_entry = row_rec_to_index_entry(ROW_COPY_DATA, rec, index, offsets,
&n_ext, heap);
/* We checked above that there are no externally stored fields. */
ut_a(!n_ext);
row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
FALSE, NULL);
......@@ -1920,6 +1924,12 @@ err_exit:
btr_search_update_hash_on_delete(cursor);
/* The call to row_rec_to_index_entry(ROW_COPY_DATA, ...) above
invokes rec_offs_make_valid() to point to the copied record that
the fields of new_entry point to. We have to undo it here. */
ut_ad(rec_offs_validate(NULL, index, offsets));
rec_offs_make_valid(page_cur_get_rec(page_cursor), index, offsets);
page_cur_delete_rec(page_cursor, index, offsets, mtr);
page_cur_move_to_prev(page_cursor);
......@@ -1934,7 +1944,7 @@ err_exit:
}
/* There are no externally stored columns in new_entry */
rec = btr_cur_insert_if_possible(cursor, new_entry, 0, mtr);
rec = btr_cur_insert_if_possible(cursor, new_entry, 0/*n_ext*/, mtr);
ut_a(rec); /* <- We calculated above the insert would fit */
if (page_zip && !dict_index_is_clust(index)
......@@ -1943,16 +1953,6 @@ err_exit:
ibuf_update_free_bits_zip(block, mtr);
}
if (!rec_get_deleted_flag(rec, page_is_comp(page))) {
/* The new inserted record owns its possible externally
stored fields */
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
btr_cur_unmark_extern_fields(page_zip,
rec, index, offsets, mtr);
}
/* Restore the old explicit lock state on the record */
lock_rec_restore_from_page_infimum(block, rec, block);
......@@ -2120,7 +2120,13 @@ btr_cur_pessimistic_update(
trx = thr_get_trx(thr);
new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, *heap);
new_entry = row_rec_to_index_entry(ROW_COPY_DATA, rec, index, offsets,
&n_ext, *heap);
/* The call to row_rec_to_index_entry(ROW_COPY_DATA, ...) above
invokes rec_offs_make_valid() to point to the copied record that
the fields of new_entry point to. We have to undo it here. */
ut_ad(rec_offs_validate(NULL, index, offsets));
rec_offs_make_valid(rec, index, offsets);
row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
FALSE, *heap);
......@@ -2150,8 +2156,7 @@ btr_cur_pessimistic_update(
ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, heap);
n_ext = btr_push_update_extern_fields(new_entry, index, offsets,
update);
n_ext += btr_push_update_extern_fields(new_entry, update);
if (page_zip_rec_needs_ext(rec_get_converted_size(index, new_entry,
n_ext),
......@@ -3517,70 +3522,34 @@ btr_cur_unmark_dtuple_extern_fields(
}
/***********************************************************************
Stores the positions of the fields marked as extern storage in the update
vector, and also those fields who are marked as extern storage in rec
and not mentioned in updated fields. We use this function to remember
which fields we must mark as extern storage in a record inserted for an
update. */
Flags the data tuple fields that are marked as extern storage in the
update vector. We use this function to remember which fields we must
mark as extern storage in a record inserted for an update. */
ulint
btr_push_update_extern_fields(
/*==========================*/
/* out: number of externally
stored columns */
dtuple_t* tuple, /* in/out: data tuple */
const dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: array returned by
rec_get_offsets() */
const upd_t* update) /* in: update vector or NULL */
/* out: number of flagged external columns */
dtuple_t* tuple, /* in/out: data tuple */
const upd_t* update) /* in: update vector */
{
ulint n_pushed = 0;
ulint n;
ulint i;
ulint n_pushed = 0;
ulint n;
const upd_field_t* uf;
ut_ad(tuple);
ut_ad(offsets);
ut_ad(dict_index_is_clust(index));
#ifdef UNIV_DEBUG
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
ut_ad(!dfield_is_ext(dtuple_get_nth_field(tuple, i)));
}
#endif /* UNIV_DEBUG */
if (update) {
const upd_field_t* ufield;
ufield = update->fields;
n = upd_get_n_fields(update);
for (; n--; ufield++) {
if (dfield_is_ext(&ufield->new_val)) {
dfield_set_ext(dtuple_get_nth_field(
tuple,
ufield->field_no));
n_pushed++;
}
}
}
ut_ad(update);
if (!rec_offs_any_extern(offsets)) {
return(n_pushed);
}
uf = update->fields;
n = upd_get_n_fields(update);
n = rec_offs_n_fields(offsets);
for (; n--; uf++) {
if (dfield_is_ext(&uf->new_val)) {
dfield_t* field
= dtuple_get_nth_field(tuple, uf->field_no);
for (i = 0; i < n; i++) {
if (rec_offs_nth_extern(offsets, i)) {
const dict_field_t* ifield
= dict_index_get_nth_field(index, i);
ulint col_no
= dict_col_get_no(dict_field_get_col(ifield));
dfield_t* dfield
= dtuple_get_nth_field(tuple, col_no);
/* Check it is not flagged already */
if (!dfield_is_ext(dfield)) {
dfield_set_ext(dfield);
if (!dfield_is_ext(field)) {
dfield_set_ext(field);
n_pushed++;
}
}
......
......@@ -551,22 +551,17 @@ btr_rec_copy_externally_stored_field(
ulint* len, /* out: length of the field */
mem_heap_t* heap); /* in: mem heap */
/***********************************************************************
Stores the positions of the fields marked as extern storage in the update
vector, and also those fields who are marked as extern storage in rec
and not mentioned in updated fields. We use this function to remember
which fields we must mark as extern storage in a record inserted for an
update. */
Flags the data tuple fields that are marked as extern storage in the
update vector. We use this function to remember which fields we must
mark as extern storage in a record inserted for an update. */
ulint
btr_push_update_extern_fields(
/*==========================*/
/* out: number of externally
stored columns */
dtuple_t* tuple, /* in/out: data tuple */
const dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: array returned by
rec_get_offsets() */
const upd_t* update);/* in: update vector or NULL */
/* out: number of flagged external columns */
dtuple_t* tuple, /* in/out: data tuple */
const upd_t* update) /* in: update vector */
__attribute__((nonnull));
/*######################################################################*/
......
......@@ -522,6 +522,15 @@ rec_get_data_size_old(
/* out: size */
const rec_t* rec); /* in: physical record */
/**************************************************************
The following function returns the number of allocated elements
for an array of offsets. */
UNIV_INLINE
ulint
rec_offs_get_n_alloc(
/*=================*/
/* out: number of elements */
const ulint* offsets);/* in: array for rec_get_offsets() */
/**************************************************************
The following function sets the number of allocated elements
for an array of offsets. */
UNIV_INLINE
......
......@@ -101,17 +101,16 @@ Converts an index record to a typed data tuple. */
dtuple_t*
row_rec_to_index_entry_low(
/*=======================*/
/* out: index entry built; does not
set info_bits, and the data fields in
the entry will point directly to rec */
const rec_t* rec, /* in: record in the index */
dict_index_t* index, /* in: index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint* n_ext, /* out: number of externally stored columns;
if this is passed as NULL, such columns are
not flagged nor counted */
mem_heap_t* heap); /* in: memory heap from which the memory
needed is allocated */
/* out: index entry built; does not
set info_bits, and the data fields in
the entry will point directly to rec */
const rec_t* rec, /* in: record in the index */
const dict_index_t* index, /* in: index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint* n_ext, /* out: number of externally
stored columns */
mem_heap_t* heap); /* in: memory heap from which
the memory needed is allocated */
/***********************************************************************
Converts an index record to a typed data tuple. NOTE that externally
stored (often big) fields are NOT copied to heap. */
......@@ -119,22 +118,29 @@ stored (often big) fields are NOT copied to heap. */
dtuple_t*
row_rec_to_index_entry(
/*===================*/
/* out, own: index entry built; see the
NOTE below! */
ulint type, /* in: ROW_COPY_DATA, or ROW_COPY_POINTERS:
the former copies also the data fields to
heap as the latter only places pointers to
data fields on the index page */
dict_index_t* index, /* in: index */
const rec_t* rec, /* in: record in the index;
NOTE: in the case ROW_COPY_POINTERS
the data fields in the row will point
directly into this record, therefore,
the buffer page of this record must be
at least s-latched and the latch held
as long as the dtuple is used! */
mem_heap_t* heap); /* in: memory heap from which the memory
needed is allocated */
/* out, own: index entry
built; see the NOTE below! */
ulint type, /* in: ROW_COPY_DATA, or
ROW_COPY_POINTERS: the former
copies also the data fields to
heap as the latter only places
pointers to data fields on the
index page */
const rec_t* rec, /* in: record in the index;
NOTE: in the case
ROW_COPY_POINTERS the data
fields in the row will point
directly into this record,
therefore, the buffer page of
this record must be at least
s-latched and the latch held
as long as the dtuple is used! */
const dict_index_t* index, /* in: index */
ulint* offsets,/* in/out: rec_get_offsets(rec) */
ulint* n_ext, /* out: number of externally
stored columns */
mem_heap_t* heap); /* in: memory heap from which
the memory needed is allocated */
/***********************************************************************
Builds from a secondary index record a row reference with which we can
search the clustered index record. */
......@@ -148,7 +154,7 @@ row_build_row_ref(
the former copies also the data fields to
heap, whereas the latter only places pointers
to data fields on the index page */
dict_index_t* index, /* in: index */
dict_index_t* index, /* in: secondary index */
const rec_t* rec, /* in: record in the index;
NOTE: in the case ROW_COPY_POINTERS
the data fields in the row will point
......
......@@ -85,6 +85,7 @@ row_build_row_ref_fast(
ulint i;
ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_ad(!rec_offs_any_extern(offsets));
ref_len = dtuple_get_n_fields(ref);
for (i = 0; i < ref_len; i++) {
......
......@@ -1234,6 +1234,7 @@ rec_copy_prefix_to_dtuple(
if (len != UNIV_SQL_NULL) {
dfield_set_data(field,
mem_heap_dup(heap, data, len), len);
ut_ad(!rec_offs_nth_extern(offsets, i));
} else {
dfield_set_null(field);
}
......
......@@ -2243,6 +2243,10 @@ row_ins_index_entry_set_vals(
}
dfield_set_data(field, row_field->data, len);
if (dfield_is_ext(row_field)) {
ut_ad(dict_index_is_clust(index));
dfield_set_ext(field);
}
}
}
......
......@@ -1588,7 +1588,6 @@ row_merge_insert_index_tuples(
break;
}
n_ext = 0;
dtuple = row_rec_to_index_entry_low(
mrec, index, offsets, &n_ext, tuple_heap);
......
......@@ -3959,8 +3959,10 @@ row_scan_and_check_index(
ulint i;
ulint cnt;
mem_heap_t* heap = NULL;
mem_heap_t* tmp_heap;
ulint n_ext;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
ulint* offsets;
rec_offs_init(offsets_);
*n_rows = 0;
......@@ -4007,12 +4009,13 @@ func_exit:
rec = buf + mach_read_from_4(buf);
offsets = rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap);
if (prev_entry != NULL) {
matched_fields = 0;
matched_bytes = 0;
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
cmp = cmp_dtuple_rec_with_match(prev_entry, rec, offsets,
&matched_fields,
&matched_bytes);
......@@ -4056,10 +4059,24 @@ not_ok:
}
}
/* Empty the heap on each round. But preserve offsets[]
for the row_rec_to_index_entry() call, by copying them
into a separate memory heap when needed. */
if (offsets != offsets_) {
ulint size = rec_offs_get_n_alloc(offsets) * sizeof *offsets;
tmp_heap = mem_heap_create(size);
offsets = mem_heap_dup(tmp_heap, offsets, size);
}
mem_heap_empty(heap);
offsets = offsets_;
prev_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
prev_entry = row_rec_to_index_entry(ROW_COPY_DATA, rec,
index, offsets, &n_ext, heap);
if (offsets != offsets_) {
mem_heap_free(tmp_heap);
}
ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, ROW_SEL_NEXT);
......
......@@ -220,11 +220,11 @@ row_build(
= dict_index_get_nth_field(index, i);
const dict_col_t* col
= dict_field_get_col(ind_field);
dfield_t* dfield
= dtuple_get_nth_field(row, dict_col_get_no(col));
if (ind_field->prefix_len == 0) {
dfield_t* dfield = dtuple_get_nth_field(
row, dict_col_get_no(col));
const byte* field = rec_get_nth_field(
rec, offsets, i, &len);
......@@ -233,6 +233,7 @@ row_build(
if (rec_offs_nth_extern(offsets, i)) {
ext_cols[j++] = dict_col_get_no(col);
dfield_set_ext(dfield);
}
}
......@@ -260,17 +261,16 @@ Converts an index record to a typed data tuple. */
dtuple_t*
row_rec_to_index_entry_low(
/*=======================*/
/* out: index entry built; does not
set info_bits, and the data fields in
the entry will point directly to rec */
const rec_t* rec, /* in: record in the index */
dict_index_t* index, /* in: index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint* n_ext, /* out: number of externally stored columns;
if this is passed as NULL, such columns are
not flagged nor counted */
mem_heap_t* heap) /* in: memory heap from which the memory
needed is allocated */
/* out: index entry built; does not
set info_bits, and the data fields in
the entry will point directly to rec */
const rec_t* rec, /* in: record in the index */
const dict_index_t* index, /* in: index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint* n_ext, /* out: number of externally
stored columns */
mem_heap_t* heap) /* in: memory heap from which
the memory needed is allocated */
{
dtuple_t* entry;
dfield_t* dfield;
......@@ -280,6 +280,9 @@ row_rec_to_index_entry_low(
ulint rec_len;
ut_ad(rec && heap && index);
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(n_ext);
*n_ext = 0;
rec_len = rec_offs_n_fields(offsets);
......@@ -298,7 +301,7 @@ row_rec_to_index_entry_low(
dfield_set_data(dfield, field, len);
if (n_ext && rec_offs_nth_extern(offsets, i)) {
if (rec_offs_nth_extern(offsets, i)) {
dfield_set_ext(dfield);
(*n_ext)++;
}
......@@ -316,34 +319,35 @@ stored (often big) fields are NOT copied to heap. */
dtuple_t*
row_rec_to_index_entry(
/*===================*/
/* out, own: index entry built; see the
NOTE below! */
ulint type, /* in: ROW_COPY_DATA, or ROW_COPY_POINTERS:
the former copies also the data fields to
heap as the latter only places pointers to
data fields on the index page */
dict_index_t* index, /* in: index */
const rec_t* rec, /* in: record in the index;
NOTE: in the case ROW_COPY_POINTERS
the data fields in the row will point
directly into this record, therefore,
the buffer page of this record must be
at least s-latched and the latch held
as long as the dtuple is used! */
mem_heap_t* heap) /* in: memory heap from which the memory
needed is allocated */
/* out, own: index entry
built; see the NOTE below! */
ulint type, /* in: ROW_COPY_DATA, or
ROW_COPY_POINTERS: the former
copies also the data fields to
heap as the latter only places
pointers to data fields on the
index page */
const rec_t* rec, /* in: record in the index;
NOTE: in the case
ROW_COPY_POINTERS the data
fields in the row will point
directly into this record,
therefore, the buffer page of
this record must be at least
s-latched and the latch held
as long as the dtuple is used! */
const dict_index_t* index, /* in: index */
ulint* offsets,/* in/out: rec_get_offsets(rec) */
ulint* n_ext, /* out: number of externally
stored columns */
mem_heap_t* heap) /* in: memory heap from which
the memory needed is allocated */
{
dtuple_t* entry;
byte* buf;
mem_heap_t* tmp_heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
rec_offs_init(offsets_);
ut_ad(rec && heap && index);
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &tmp_heap);
ut_ad(rec_offs_validate(rec, index, offsets));
if (type == ROW_COPY_DATA) {
/* Take a copy of rec to heap */
......@@ -353,15 +357,11 @@ row_rec_to_index_entry(
rec_offs_make_valid(rec, index, offsets);
}
entry = row_rec_to_index_entry_low(rec, index, offsets, NULL, heap);
entry = row_rec_to_index_entry_low(rec, index, offsets, n_ext, heap);
dtuple_set_info_bits(entry,
rec_get_info_bits(rec, rec_offs_comp(offsets)));
if (UNIV_LIKELY_NULL(tmp_heap)) {
mem_heap_free(tmp_heap);
}
return(entry);
}
......@@ -378,7 +378,7 @@ row_build_row_ref(
the former copies also the data fields to
heap, whereas the latter only places pointers
to data fields on the index page */
dict_index_t* index, /* in: index */
dict_index_t* index, /* in: secondary index */
const rec_t* rec, /* in: record in the index;
NOTE: in the case ROW_COPY_POINTERS
the data fields in the row will point
......@@ -406,9 +406,12 @@ row_build_row_ref(
rec_offs_init(offsets_);
ut_ad(index && rec && heap);
ut_ad(!dict_index_is_clust(index));
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &tmp_heap);
/* Secondary indexes must not contain externally stored columns. */
ut_ad(!rec_offs_any_extern(offsets));
if (type == ROW_COPY_DATA) {
/* Take a copy of rec to heap */
......@@ -537,6 +540,8 @@ notfound:
ut_ad(rec_offs_validate(rec, index, offsets));
}
/* Secondary indexes must not contain externally stored columns. */
ut_ad(!rec_offs_any_extern(offsets));
ref_len = dict_index_get_n_unique(clust_index);
ut_ad(ref_len == dtuple_get_n_fields(ref));
......@@ -628,6 +633,7 @@ row_build_row_ref_from_row(
dfield2 = dtuple_get_nth_field(row, dict_col_get_no(col));
dfield_copy(dfield, dfield2);
ut_ad(!dfield_is_ext(dfield));
if (field->prefix_len > 0 && !dfield_is_null(dfield)) {
......
......@@ -485,13 +485,13 @@ sel_pop_prefetched_row(
ut_ad(!column->prefetch_buf);
ut_ad(que_node_get_val_buf_size(column) == 0);
#ifdef UNIV_DEBUG
dfield_set_data(val, NULL, 0);
#endif
ut_d(dfield_set_null(val));
goto next_col;
}
ut_ad(column->prefetch_buf);
ut_ad(!dfield_is_ext(val));
sel_buf = column->prefetch_buf + plan->first_prefetched;
......
......@@ -153,6 +153,7 @@ row_upd_check_references_constraints(
cursor position is lost in this function! */
dict_table_t* table, /* in: table in question */
dict_index_t* index, /* in: index of the cursor */
ulint* offsets,/* in/out: rec_get_offsets(pcur.rec, index) */
que_thr_t* thr, /* in: query thread */
mtr_t* mtr) /* in: mtr */
{
......@@ -160,7 +161,8 @@ row_upd_check_references_constraints(
mem_heap_t* heap;
dtuple_t* entry;
trx_t* trx;
rec_t* rec;
const rec_t* rec;
ulint n_ext;
ulint err;
ibool got_s_lock = FALSE;
......@@ -172,10 +174,12 @@ row_upd_check_references_constraints(
trx = thr_get_trx(thr);
rec = btr_pcur_get_rec(pcur);
ut_ad(rec_offs_validate(rec, index, offsets));
heap = mem_heap_create(500);
entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
entry = row_rec_to_index_entry(ROW_COPY_DATA, rec, index, offsets,
&n_ext, heap);
mtr_commit(mtr);
......@@ -1229,13 +1233,16 @@ row_upd_store_row(
node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
&node->ext, node->heap);
if (UNIV_LIKELY_NULL(node->ext)) {
node->n_ext = btr_push_update_extern_fields(
node->row, clust_index, offsets,
node->is_delete ? NULL : node->update);
node->n_ext = node->ext->n_ext;
} else {
node->n_ext = 0;
}
if (!node->is_delete) {
node->n_ext += btr_push_update_extern_fields(node->row,
node->update);
}
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
......@@ -1310,11 +1317,14 @@ row_upd_sec_index_entry(
thr, &mtr);
if (err == DB_SUCCESS && check_ref) {
ulint* offsets = rec_get_offsets(
rec, index, NULL,
ULINT_UNDEFINED, &heap);
/* NOTE that the following call loses
the position of pcur ! */
err = row_upd_check_references_constraints(
node, &pcur, index->table,
index, thr, &mtr);
index, offsets, thr, &mtr);
}
}
}
......@@ -1402,6 +1412,7 @@ row_upd_clust_rec_by_insert(
rec_t* rec;
dict_index_t* index;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets;
rec_offs_init(offsets_);
err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
......@@ -1418,18 +1429,16 @@ row_upd_clust_rec_by_insert(
rec = btr_cur_get_rec(btr_cur);
index = dict_table_get_first_index(table);
offsets = rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap);
btr_cur_mark_extern_inherited_fields(
btr_cur_get_page_zip(btr_cur),
rec, index,
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
node->update, mtr);
rec, index, offsets, node->update, mtr);
if (check_ref) {
/* NOTE that the following call loses
the position of pcur ! */
err = row_upd_check_references_constraints(
node, pcur, table, index, thr, mtr);
node, pcur, table, index, offsets, thr, mtr);
if (err != DB_SUCCESS) {
mtr_commit(mtr);
if (UNIV_LIKELY_NULL(heap)) {
......@@ -1438,7 +1447,6 @@ row_upd_clust_rec_by_insert(
return(err);
}
}
}
mtr_commit(mtr);
......@@ -1586,6 +1594,8 @@ row_upd_del_mark_clust_rec(
completed, else error code */
upd_node_t* node, /* in: row update node */
dict_index_t* index, /* in: clustered index */
ulint* offsets,/* in/out: rec_get_offsets() for the
record under the cursor */
que_thr_t* thr, /* in: query thread */
ibool check_ref,/* in: TRUE if index may be referenced in
a foreign key constraint */
......@@ -1617,12 +1627,8 @@ row_upd_del_mark_clust_rec(
err = row_upd_check_references_constraints(node,
pcur, index->table,
index, thr, mtr);
if (err != DB_SUCCESS) {
mtr_commit(mtr);
return(err);
}
index, offsets,
thr, mtr);
}
mtr_commit(mtr);
......@@ -1652,7 +1658,7 @@ row_upd_clust_step(
rec_t* rec;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
const ulint* offsets;
ulint* offsets;
rec_offs_init(offsets_);
index = dict_table_get_first_index(node->table);
......@@ -1727,8 +1733,8 @@ row_upd_clust_step(
/* NOTE: the following function calls will also commit mtr */
if (node->is_delete) {
err = row_upd_del_mark_clust_rec(node, index, thr, check_ref,
mtr);
err = row_upd_del_mark_clust_rec(node, index, offsets,
thr, check_ref, mtr);
if (err == DB_SUCCESS) {
node->state = UPD_NODE_UPDATE_ALL_SEC;
node->index = dict_table_get_next_index(index);
......
......@@ -910,13 +910,14 @@ trx_undo_rec_get_partial_row(
ptr = trx_undo_rec_get_col_val(ptr, &field, &len);
if (len >= UNIV_EXTERN_STORAGE_FIELD) {
ext_cols[n_ext_cols++] = col_no;
}
dfield = dtuple_get_nth_field(*row, col_no);
dfield_set_data(dfield, field, len);
if (len >= UNIV_EXTERN_STORAGE_FIELD) {
dfield_set_ext(dfield);
ext_cols[n_ext_cols++] = col_no;
}
}
if (n_ext_cols) {
......@@ -1396,10 +1397,9 @@ trx_undo_prev_version_build(
those fields that update updates to become externally stored
fields. Store the info: */
entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec,
heap);
n_ext = btr_push_update_extern_fields(entry, index, offsets,
update);
entry = row_rec_to_index_entry(ROW_COPY_DATA, rec, index,
offsets, &n_ext, heap);
n_ext += btr_push_update_extern_fields(entry, update);
row_upd_index_replace_new_col_vals(entry, index, update, heap);
buf = mem_heap_alloc(heap, rec_get_converted_size(index, entry,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment