Commit aaccf926 authored by marko's avatar marko

branches/zip: Clarify why certain calls of

btr_rec_copy_externally_stored_field() are safe.

row_merge_copy_blobs(): Note that the table is locked during index creation.
Therefore, none of its BLOBs can be freed.

row_sel_fetch_columns(): Note that rec must be protected by a page latch.
Add const qualifier to rec.

row_sel_get_clust_rec(): Note that the clustered index record is protected
by a page latch that was acquired when the persistent cursor was positioned
and that the latch will be freed by mini-transaction commit.

row_sel_try_search_shortcut(): Check the delete-mark flag before fetching
the columns.  Note that the clustered index record is protected
by a page latch that was acquired when the persistent cursor was positioned
and that the latch will be freed by mini-transaction commit.

row_sel(), row_search_for_mysql(): Note that the clustered index record
is protected by a page latch that was acquired when the persistent cursor
was positioned and that the latch will be freed by mini-transaction commit.

row_sel_field_store_in_mysql_format(): Add const qualifier to data.

row_sel_store_mysql_rec(), row_sel_push_cache_row_for_mysql():
Add const qualifier to rec.  Note that rec must be protected by a page latch.
parent d837c204
...@@ -1511,6 +1511,11 @@ row_merge_copy_blobs( ...@@ -1511,6 +1511,11 @@ row_merge_copy_blobs(
ut_ad(!dfield_is_null(field)); ut_ad(!dfield_is_null(field));
/* The table is locked during index creation.
Therefore, externally stored columns cannot possibly
be freed between the time the BLOB pointers are read
(row_merge_read_clustered_index()) and dereferenced
(below). */
data = btr_rec_copy_externally_stored_field( data = btr_rec_copy_externally_stored_field(
mrec, offsets, zip_size, i, &len, heap); mrec, offsets, zip_size, i, &len, heap);
......
...@@ -344,8 +344,8 @@ void ...@@ -344,8 +344,8 @@ void
row_sel_fetch_columns( row_sel_fetch_columns(
/*==================*/ /*==================*/
dict_index_t* index, /* in: record index */ dict_index_t* index, /* in: record index */
rec_t* rec, /* in: record in a clustered or non-clustered const rec_t* rec, /* in: record in a clustered or non-clustered
index */ index; must be protected by a page latch */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
sym_node_t* column) /* in: first column in a column list, or sym_node_t* column) /* in: first column in a column list, or
NULL */ NULL */
...@@ -353,7 +353,7 @@ row_sel_fetch_columns( ...@@ -353,7 +353,7 @@ row_sel_fetch_columns(
dfield_t* val; dfield_t* val;
ulint index_type; ulint index_type;
ulint field_no; ulint field_no;
byte* data; const byte* data;
ulint len; ulint len;
ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_validate(rec, index, offsets));
...@@ -879,7 +879,10 @@ row_sel_get_clust_rec( ...@@ -879,7 +879,10 @@ row_sel_get_clust_rec(
} }
} }
/* Fetch the columns needed in test conditions */ /* Fetch the columns needed in test conditions. The clustered
index record is protected by a page latch that was acquired
when plan->clust_pcur was positioned. The latch will not be
released until mtr_commit(mtr). */
row_sel_fetch_columns(index, clust_rec, offsets, row_sel_fetch_columns(index, clust_rec, offsets,
UT_LIST_GET_FIRST(plan->columns)); UT_LIST_GET_FIRST(plan->columns));
...@@ -1186,10 +1189,7 @@ row_sel_try_search_shortcut( ...@@ -1186,10 +1189,7 @@ row_sel_try_search_shortcut(
goto func_exit; goto func_exit;
} }
/* Test deleted flag. Fetch the columns needed in test conditions. */ /* Test the deleted flag. */
row_sel_fetch_columns(index, rec, offsets,
UT_LIST_GET_FIRST(plan->columns));
if (rec_get_deleted_flag(rec, dict_table_is_comp(plan->table))) { if (rec_get_deleted_flag(rec, dict_table_is_comp(plan->table))) {
...@@ -1197,6 +1197,14 @@ row_sel_try_search_shortcut( ...@@ -1197,6 +1197,14 @@ row_sel_try_search_shortcut(
goto func_exit; goto func_exit;
} }
/* Fetch the columns needed in test conditions. The index
record is protected by a page latch that was acquired when
plan->pcur was positioned. The latch will not be released
until mtr_commit(mtr). */
row_sel_fetch_columns(index, rec, offsets,
UT_LIST_GET_FIRST(plan->columns));
/* Test the rest of search conditions */ /* Test the rest of search conditions */
if (!row_sel_test_other_conds(plan)) { if (!row_sel_test_other_conds(plan)) {
...@@ -1584,6 +1592,16 @@ skip_lock: ...@@ -1584,6 +1592,16 @@ skip_lock:
offsets = rec_get_offsets( offsets = rec_get_offsets(
rec, index, offsets, rec, index, offsets,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
/* Fetch the columns needed in
test conditions. The clustered
index record is protected by a
page latch that was acquired
by row_sel_open_pcur() or
row_sel_restore_pcur_pos().
The latch will not be released
until mtr_commit(mtr). */
row_sel_fetch_columns( row_sel_fetch_columns(
index, rec, offsets, index, rec, offsets,
UT_LIST_GET_FIRST( UT_LIST_GET_FIRST(
...@@ -1607,7 +1625,10 @@ skip_lock: ...@@ -1607,7 +1625,10 @@ skip_lock:
/* PHASE 4: Test search end conditions and deleted flag */ /* PHASE 4: Test search end conditions and deleted flag */
/* Fetch the columns needed in test conditions */ /* Fetch the columns needed in test conditions. The record is
protected by a page latch that was acquired by
row_sel_open_pcur() or row_sel_restore_pcur_pos(). The latch
will not be released until mtr_commit(mtr). */
row_sel_fetch_columns(index, rec, offsets, row_sel_fetch_columns(index, rec, offsets,
UT_LIST_GET_FIRST(plan->columns)); UT_LIST_GET_FIRST(plan->columns));
...@@ -2502,14 +2523,18 @@ static ...@@ -2502,14 +2523,18 @@ static
void void
row_sel_field_store_in_mysql_format( row_sel_field_store_in_mysql_format(
/*================================*/ /*================================*/
byte* dest, /* in/out: buffer where to store; NOTE that BLOBs byte* dest, /* in/out: buffer where to store; NOTE
are not in themselves stored here: the caller must that BLOBs are not in themselves
allocate and copy the BLOB into buffer before, and pass stored here: the caller must allocate
the pointer to the BLOB in 'data' */ and copy the BLOB into buffer before,
const mysql_row_templ_t* templ, /* in: MySQL column template. and pass the pointer to the BLOB in
'data' */
const mysql_row_templ_t* templ,
/* in: MySQL column template.
Its following fields are referenced: Its following fields are referenced:
type, is_unsigned, mysql_col_len, mbminlen, mbmaxlen */ type, is_unsigned, mysql_col_len,
byte* data, /* in: data to store */ mbminlen, mbmaxlen */
const byte* data, /* in: data to store */
ulint len) /* in: length of the data */ ulint len) /* in: length of the data */
{ {
byte* ptr; byte* ptr;
...@@ -2661,16 +2686,17 @@ row_sel_store_mysql_rec( ...@@ -2661,16 +2686,17 @@ row_sel_store_mysql_rec(
case) */ case) */
byte* mysql_rec, /* out: row in the MySQL format */ byte* mysql_rec, /* out: row in the MySQL format */
row_prebuilt_t* prebuilt, /* in: prebuilt struct */ row_prebuilt_t* prebuilt, /* in: prebuilt struct */
rec_t* rec, /* in: Innobase record in the index const rec_t* rec, /* in: Innobase record in the index
which was described in prebuilt's which was described in prebuilt's
template */ template; must be protected by
a page latch */
const ulint* offsets) /* in: array returned by const ulint* offsets) /* in: array returned by
rec_get_offsets() */ rec_get_offsets() */
{ {
mysql_row_templ_t* templ; mysql_row_templ_t* templ;
mem_heap_t* extern_field_heap = NULL; mem_heap_t* extern_field_heap = NULL;
mem_heap_t* heap; mem_heap_t* heap;
byte* data; const byte* data;
ulint len; ulint len;
ulint i; ulint i;
...@@ -2771,7 +2797,7 @@ row_sel_store_mysql_rec( ...@@ -2771,7 +2797,7 @@ row_sel_store_mysql_rec(
BLOB, TEXT and true VARCHAR) with space. */ BLOB, TEXT and true VARCHAR) with space. */
if (UNIV_UNLIKELY(templ->mbminlen == 2)) { if (UNIV_UNLIKELY(templ->mbminlen == 2)) {
/* Treat UCS2 as a special case. */ /* Treat UCS2 as a special case. */
data = mysql_rec byte* d = mysql_rec
+ templ->mysql_col_offset; + templ->mysql_col_offset;
len = templ->mysql_col_len; len = templ->mysql_col_len;
/* There are two UCS2 bytes per char, /* There are two UCS2 bytes per char,
...@@ -2779,8 +2805,8 @@ row_sel_store_mysql_rec( ...@@ -2779,8 +2805,8 @@ row_sel_store_mysql_rec(
ut_a(!(len & 1)); ut_a(!(len & 1));
/* Pad with 0x0020. */ /* Pad with 0x0020. */
while (len) { while (len) {
*data++ = 0x00; *d++ = 0x00;
*data++ = 0x20; *d++ = 0x20;
len -= 2; len -= 2;
} }
continue; continue;
...@@ -3146,7 +3172,8 @@ void ...@@ -3146,7 +3172,8 @@ void
row_sel_push_cache_row_for_mysql( row_sel_push_cache_row_for_mysql(
/*=============================*/ /*=============================*/
row_prebuilt_t* prebuilt, /* in: prebuilt struct */ row_prebuilt_t* prebuilt, /* in: prebuilt struct */
rec_t* rec, /* in: record to push */ const rec_t* rec, /* in: record to push; must
be protected by a page latch */
const ulint* offsets) /* in: rec_get_offsets() */ const ulint* offsets) /* in: rec_get_offsets() */
{ {
byte* buf; byte* buf;
...@@ -3573,6 +3600,12 @@ row_search_for_mysql( ...@@ -3573,6 +3600,12 @@ row_search_for_mysql(
ut_a(0 == cmp_dtuple_rec(search_tuple, ut_a(0 == cmp_dtuple_rec(search_tuple,
rec, offsets)); rec, offsets));
#endif #endif
/* At this point, rec is protected by
a page latch that was acquired by
row_sel_try_search_shortcut_for_mysql().
The latch will not be released until
mtr_commit(&mtr). */
if (!row_sel_store_mysql_rec(buf, prebuilt, if (!row_sel_store_mysql_rec(buf, prebuilt,
rec, offsets)) { rec, offsets)) {
err = DB_TOO_BIG_RECORD; err = DB_TOO_BIG_RECORD;
...@@ -4294,6 +4327,10 @@ requires_clust_rec: ...@@ -4294,6 +4327,10 @@ requires_clust_rec:
result_rec != rec ? clust_index : index, result_rec != rec ? clust_index : index,
offsets)); offsets));
/* At this point, the clustered index record is protected
by a page latch that was acquired when pcur was positioned.
The latch will not be released until mtr_commit(&mtr). */
if ((match_mode == ROW_SEL_EXACT if ((match_mode == ROW_SEL_EXACT
|| prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD) || prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD)
&& prebuilt->select_lock_type == LOCK_NONE && prebuilt->select_lock_type == LOCK_NONE
......
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