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