ha_innodb.cc, row0sel.c, row0mysql.c, row0mysql.h:

  Allow HANDLER PREV and NEXT also after positioning the cursor with a unique search on the primary key
parent 5112674d
...@@ -419,13 +419,21 @@ struct row_prebuilt_struct { ...@@ -419,13 +419,21 @@ struct row_prebuilt_struct {
index where the ordering column is index where the ordering column is
the row id: in this case this flag the row id: in this case this flag
is set to TRUE */ is set to TRUE */
dict_index_t* index; /* current index for a search, if any */ dict_index_t* index; /* current index for a search, if
any */
ulint read_just_key; /* set to 1 when MySQL calls ulint read_just_key; /* set to 1 when MySQL calls
ha_innobase::extra with the ha_innobase::extra with the
argument HA_EXTRA_KEYREAD; it is enough argument HA_EXTRA_KEYREAD; it is enough
to read just columns defined in to read just columns defined in
the index (i.e., no read of the the index (i.e., no read of the
clustered index record necessary) */ clustered index record necessary) */
ibool used_in_HANDLER;/* TRUE if we have been using this
handle in a MySQL HANDLER low level
index cursor command: then we must
store the pcur position even in a
unique search from a clustered index,
because HANDLER allows NEXT and PREV
in such a situation */
ulint template_type; /* ROW_MYSQL_WHOLE_ROW, ulint template_type; /* ROW_MYSQL_WHOLE_ROW,
ROW_MYSQL_REC_FIELDS, ROW_MYSQL_REC_FIELDS,
ROW_MYSQL_DUMMY_TEMPLATE, or ROW_MYSQL_DUMMY_TEMPLATE, or
......
...@@ -324,6 +324,9 @@ row_create_prebuilt( ...@@ -324,6 +324,9 @@ row_create_prebuilt(
prebuilt->mysql_has_locked = FALSE; prebuilt->mysql_has_locked = FALSE;
prebuilt->index = NULL; prebuilt->index = NULL;
prebuilt->used_in_HANDLER = FALSE;
prebuilt->n_template = 0; prebuilt->n_template = 0;
prebuilt->mysql_template = NULL; prebuilt->mysql_template = NULL;
......
...@@ -2690,9 +2690,9 @@ row_search_for_mysql( ...@@ -2690,9 +2690,9 @@ row_search_for_mysql(
/* MySQL sometimes seems to do fetch next or fetch prev even /* MySQL sometimes seems to do fetch next or fetch prev even
if the search condition is unique; this can, for example, if the search condition is unique; this can, for example,
happen with the HANDLER commands; we do not store pcur position happen with the HANDLER commands; we do not always store the
in this case, so we cannot restore cursor position, and must pcur position in this case, so we cannot restore cursor
return immediately */ position, and must return immediately */
/* printf("%s record not found 1\n", index->name); */ /* printf("%s record not found 1\n", index->name); */
...@@ -2703,13 +2703,13 @@ row_search_for_mysql( ...@@ -2703,13 +2703,13 @@ row_search_for_mysql(
mtr_start(&mtr); mtr_start(&mtr);
/* In a search where at most one record in the index may match, we /* In a search where at most one record in the index may match, we
can use a LOCK_REC_NOT_GAP type record lock when locking a non-delete can use a LOCK_REC_NOT_GAP type record lock when locking a non-delete-
marked matching record. marked matching record.
Note that in a unique secondary index there may be different delete Note that in a unique secondary index there may be different delete-
marked versions of a record where only the primary key values differ: marked versions of a record where only the primary key values differ:
thus in a secondary index we must use next-key locks when locking thus in a secondary index we must use next-key locks when locking
delete marked records. */ delete-marked records. */
if (match_mode == ROW_SEL_EXACT if (match_mode == ROW_SEL_EXACT
&& index->type & DICT_UNIQUE && index->type & DICT_UNIQUE
...@@ -2730,10 +2730,9 @@ row_search_for_mysql( ...@@ -2730,10 +2730,9 @@ row_search_for_mysql(
if (unique_search if (unique_search
&& index->type & DICT_CLUSTERED && index->type & DICT_CLUSTERED
&& !prebuilt->templ_contains_blob && !prebuilt->templ_contains_blob
&& !prebuilt->used_in_HANDLER
&& (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) { && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
ut_a(direction == 0); /* We cannot do fetch prev, as we have
not stored the cursor position */
mode = PAGE_CUR_GE; mode = PAGE_CUR_GE;
unique_search_from_clust_index = TRUE; unique_search_from_clust_index = TRUE;
...@@ -3217,11 +3216,16 @@ row_search_for_mysql( ...@@ -3217,11 +3216,16 @@ row_search_for_mysql(
} }
} }
got_row: got_row:
/* TODO: should we in every case store the cursor position, even /* We have an optimization to save CPU time: if this is a consistent
if this is just a join, for example? */ read on a unique condition on the clustered index, then we do not
store the pcur position, because any fetch next or prev will anyway
return 'end of file'. An exception is the MySQL HANDLER command
where the user can move the cursor with PREV or NEXT even after
a unique search. */
if (!unique_search_from_clust_index if (!unique_search_from_clust_index
|| prebuilt->select_lock_type == LOCK_X) { || prebuilt->select_lock_type == LOCK_X
|| prebuilt->used_in_HANDLER) {
/* Inside an update always store the cursor position */ /* Inside an update always store the cursor position */
......
...@@ -601,7 +601,7 @@ innobase_invalidate_query_cache( ...@@ -601,7 +601,7 @@ innobase_invalidate_query_cache(
Call this when you have opened a new table handle in HANDLER, before you Call this when you have opened a new table handle in HANDLER, before you
call index_read_idx() etc. Actually, we can let the cursor stay open even call index_read_idx() etc. Actually, we can let the cursor stay open even
over a transaction commit! Then you should call this before every operation, over a transaction commit! Then you should call this before every operation,
fecth next etc. This function inits the necessary things even after a fetch next etc. This function inits the necessary things even after a
transaction commit. */ transaction commit. */
void void
...@@ -648,6 +648,8 @@ ha_innobase::init_table_handle_for_HANDLER(void) ...@@ -648,6 +648,8 @@ ha_innobase::init_table_handle_for_HANDLER(void)
we???? */ we???? */
prebuilt->read_just_key = FALSE; prebuilt->read_just_key = FALSE;
prebuilt->used_in_HANDLER = TRUE;
} }
/************************************************************************* /*************************************************************************
...@@ -4048,6 +4050,8 @@ ha_innobase::external_lock( ...@@ -4048,6 +4050,8 @@ ha_innobase::external_lock(
trx->mysql_n_tables_locked = 0; trx->mysql_n_tables_locked = 0;
prebuilt->used_in_HANDLER = FALSE;
/* Here we release the search latch and InnoDB /* Here we release the search latch and InnoDB
thread FIFO ticket if they were reserved. */ thread FIFO ticket if they were reserved. */
......
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