diff options
Diffstat (limited to 'storage/xtradb/row/row0sel.c')
-rw-r--r-- | storage/xtradb/row/row0sel.c | 107 |
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; |