summaryrefslogtreecommitdiff
path: root/storage/xtradb/row/row0sel.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/xtradb/row/row0sel.c')
-rw-r--r--storage/xtradb/row/row0sel.c107
1 files changed, 90 insertions, 17 deletions
diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c
index fb1523d3370..95df05c8ff0 100644
--- a/storage/xtradb/row/row0sel.c
+++ b/storage/xtradb/row/row0sel.c
@@ -2682,8 +2682,10 @@ row_sel_store_mysql_rec(
which was described in prebuilt's
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() */
+ ulint start_field_no, /* in: start from this field */
+ ulint end_field_no) /* in: end at this field */
{
mysql_row_templ_t* templ;
mem_heap_t* extern_field_heap = NULL;
@@ -2701,7 +2703,7 @@ row_sel_store_mysql_rec(
prebuilt->blob_heap = NULL;
}
- for (i = 0; i < prebuilt->n_template; i++) {
+ for (i = start_field_no; i < end_field_no /* prebuilt->n_template */ ; i++) {
templ = prebuilt->mysql_template + i;
@@ -3143,7 +3145,10 @@ row_sel_push_cache_row_for_mysql(
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
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() */
+ ulint start_field_no, /* in: start from this field */
+ byte* remainder_buf) /* in: if start_field_no !=0,
+ where to take prev fields */
{
byte* buf;
ulint i;
@@ -3174,12 +3179,43 @@ row_sel_push_cache_row_for_mysql(
ut_ad(prebuilt->fetch_cache_first == 0);
if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
- prebuilt->fetch_cache[
+ prebuilt->fetch_cache[
prebuilt->n_fetch_cached],
- prebuilt, rec, offsets))) {
+ prebuilt,
+ rec,
+ offsets,
+ start_field_no,
+ prebuilt->n_template))) {
ut_error;
}
+ if (start_field_no) {
+
+ for (i=0; i < start_field_no; i++) {
+ register ulint offs;
+ mysql_row_templ_t* templ;
+ register byte * null_byte;
+
+ templ = prebuilt->mysql_template + i;
+
+ if (templ->mysql_null_bit_mask) {
+ offs = templ->mysql_null_byte_offset;
+
+ null_byte= prebuilt->fetch_cache[
+ prebuilt->n_fetch_cached]+offs;
+ (*null_byte)&= ~templ->mysql_null_bit_mask;
+ (*null_byte)|= (*(remainder_buf + offs) &
+ templ->mysql_null_bit_mask);
+ }
+
+ offs = templ->mysql_col_offset;
+ memcpy(prebuilt->fetch_cache[prebuilt->n_fetch_cached]
+ + offs,
+ remainder_buf + offs,
+ templ->mysql_col_len);
+ }
+ }
+
prebuilt->n_fetch_cached++;
}
@@ -3318,6 +3354,10 @@ row_search_for_mysql(
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
+ /*psergey-mrr:*/
+ ibool some_fields_in_buffer;
+ ibool get_clust_rec = 0;
+ /*:psergey-mrr*/
rec_offs_init(offsets_);
@@ -3570,7 +3610,8 @@ row_search_for_mysql(
mtr_commit(&mtr). */
if (!row_sel_store_mysql_rec(buf, prebuilt,
- rec, offsets)) {
+ rec, offsets, 0,
+ prebuilt->n_template)) {
err = DB_TOO_BIG_RECORD;
/* We let the main loop to do the
@@ -4169,8 +4210,11 @@ no_gap_lock:
information via the clustered index record. */
ut_ad(index != clust_index);
-
- goto requires_clust_rec;
+ /*psergey-mrr:*/
+ get_clust_rec = TRUE;
+ goto idx_cond_check;
+ /**goto requires_clust_rec;**/
+ /*:psergey-mrr*/
}
}
@@ -4214,12 +4258,30 @@ no_gap_lock:
goto next_rec;
}
+
+idx_cond_check:
+ if (prebuilt->idx_cond_func)
+ {
+ int res;
+ ut_ad(prebuilt->template_type != ROW_MYSQL_DUMMY_TEMPLATE);
+ offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
+ row_sel_store_mysql_rec(buf, prebuilt, rec,
+ offsets, 0, prebuilt->n_index_fields);
+ res= prebuilt->idx_cond_func(prebuilt->idx_cond_func_arg);
+ if (res == 0)
+ goto next_rec;
+ if (res == 2)
+ {
+ err = DB_RECORD_NOT_FOUND;
+ goto idx_cond_failed;
+ }
+ }
+
/* Get the clustered index record if needed, if we did not do the
search using the clustered index. */
+ if (get_clust_rec || (index != clust_index
+ && prebuilt->need_to_access_clustered)) {
- if (index != clust_index && prebuilt->need_to_access_clustered) {
-
-requires_clust_rec:
/* We use a 'goto' to the preceding label if a consistent
read of a secondary index record requires us to look up old
versions of the associated clustered index record. */
@@ -4322,9 +4384,15 @@ requires_clust_rec:
are BLOBs in the fields to be fetched. In HANDLER we do
not cache rows because there the cursor is a scrollable
cursor. */
-
- row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
- offsets);
+ some_fields_in_buffer = (index != clust_index
+ && prebuilt->idx_cond_func);
+
+ row_sel_push_cache_row_for_mysql(prebuilt,
+ result_rec,
+ offsets,
+ some_fields_in_buffer?
+ prebuilt->n_index_fields : 0,
+ buf);
if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
goto got_row;
@@ -4340,7 +4408,10 @@ requires_clust_rec:
rec_offs_extra_size(offsets) + 4);
} else {
if (!row_sel_store_mysql_rec(buf, prebuilt,
- result_rec, offsets)) {
+ result_rec, offsets,
+ prebuilt->idx_cond_func?
+ prebuilt->n_index_fields: 0,
+ prebuilt->n_template)) {
err = DB_TOO_BIG_RECORD;
goto lock_wait_or_error;
@@ -4368,6 +4439,9 @@ got_row:
HANDLER command where the user can move the cursor with PREV or NEXT
even after a unique search. */
+ err = DB_SUCCESS;
+
+idx_cond_failed:
if (!unique_search_from_clust_index
|| prebuilt->select_lock_type != LOCK_NONE
|| prebuilt->used_in_HANDLER) {
@@ -4377,12 +4451,11 @@ got_row:
btr_pcur_store_position(pcur, &mtr);
}
- err = DB_SUCCESS;
-
goto normal_return;
next_rec:
/* Reset the old and new "did semi-consistent read" flags. */
+ get_clust_rec = FALSE;
if (UNIV_UNLIKELY(prebuilt->row_read_type
== ROW_READ_DID_SEMI_CONSISTENT)) {
prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;