summaryrefslogtreecommitdiff
path: root/innobase/row/row0sel.c
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/row/row0sel.c')
-rw-r--r--innobase/row/row0sel.c94
1 files changed, 66 insertions, 28 deletions
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index d041e34a558..e42486f1e17 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -50,15 +50,21 @@ to que_run_threads: this is to allow canceling runaway queries */
/************************************************************************
Returns TRUE if the user-defined column values in a secondary index record
-are the same as the corresponding columns in the clustered index record. */
+are the same as the corresponding columns in the clustered index record.
+NOTE: the comparison is NOT done as a binary comparison, but character
+fields are compared with collation! */
static
ibool
row_sel_sec_rec_is_for_clust_rec(
/*=============================*/
- rec_t* sec_rec,
- dict_index_t* sec_index,
- rec_t* clust_rec,
- dict_index_t* clust_index)
+ /* out: TRUE if the secondary
+ record is equal to the corresponding
+ fields in the clustered record,
+ when compared with collation */
+ rec_t* sec_rec, /* in: secondary index record */
+ dict_index_t* sec_index, /* in: secondary index */
+ rec_t* clust_rec, /* in: clustered index record */
+ dict_index_t* clust_index) /* in: clustered index */
{
dict_col_t* col;
byte* sec_field;
@@ -84,9 +90,9 @@ row_sel_sec_rec_is_for_clust_rec(
return(FALSE);
}
- if (sec_len != UNIV_SQL_NULL
- && ut_memcmp(sec_field, clust_field, sec_len) != 0) {
-
+ if (0 != cmp_data_data(dict_col_get_type(col),
+ clust_field, clust_len,
+ sec_field, sec_len)) {
return(FALSE);
}
}
@@ -763,7 +769,7 @@ row_sel_open_pcur(
/*************************************************************************
Restores a stored pcur position to a table index. */
-UNIV_INLINE
+static
ibool
row_sel_restore_pcur_pos(
/*=====================*/
@@ -813,7 +819,8 @@ row_sel_restore_pcur_pos(
return(TRUE);
}
- ut_ad(relative_position == BTR_PCUR_AFTER);
+ ut_ad(relative_position == BTR_PCUR_AFTER
+ || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE);
return(FALSE);
}
@@ -835,7 +842,8 @@ row_sel_restore_pcur_pos(
plan->stored_cursor_rec_processed is TRUE, we must move to the previous
record, else there is no need to move the cursor. */
- if (relative_position == BTR_PCUR_BEFORE) {
+ if (relative_position == BTR_PCUR_BEFORE
+ || relative_position == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
return(FALSE);
}
@@ -850,7 +858,8 @@ row_sel_restore_pcur_pos(
return(FALSE);
}
- ut_ad(relative_position == BTR_PCUR_AFTER);
+ ut_ad(relative_position == BTR_PCUR_AFTER
+ || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE);
return(TRUE);
}
@@ -1762,7 +1771,7 @@ fetch_step(
if (sel_node->state == SEL_NODE_CLOSED) {
/* SQL error detected */
- printf("SQL error %lu\n", DB_ERROR);
+ printf("SQL error %lu\n", (ulint)DB_ERROR);
que_thr_handle_error(thr, DB_ERROR, NULL, 0);
@@ -2251,7 +2260,7 @@ row_sel_get_clust_rec_for_mysql(
/************************************************************************
Restores cursor position after it has been stored. We have to take into
-account that the record cursor was positioned on can have been deleted.
+account that the record cursor was positioned on may have been deleted.
Then we may have to move the cursor one step up or down. */
static
ibool
@@ -2284,14 +2293,14 @@ sel_restore_position_for_mysql(
if (moves_up) {
btr_pcur_move_to_next(pcur, mtr);
-
- return(TRUE);
}
return(TRUE);
}
- if (relative_position == BTR_PCUR_AFTER) {
+ if (relative_position == BTR_PCUR_AFTER
+ || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE) {
+
if (moves_up) {
return(TRUE);
}
@@ -2303,7 +2312,8 @@ sel_restore_position_for_mysql(
return(TRUE);
}
- ut_ad(relative_position == BTR_PCUR_BEFORE);
+ ut_ad(relative_position == BTR_PCUR_BEFORE
+ || relative_position == BTR_PCUR_BEFORE_FIRST_IN_TREE);
if (moves_up && btr_pcur_is_on_user_rec(pcur, mtr)) {
btr_pcur_move_to_next(pcur, mtr);
@@ -2586,21 +2596,30 @@ row_search_for_mysql(
let us try a search shortcut through the hash
index */
+ if (btr_search_latch.writer != RW_LOCK_NOT_LOCKED) {
+ /* There is an x-latch request: release
+ a possible s-latch to reduce starvation
+ and wait for BTR_SEA_TIMEOUT rounds before
+ trying to keep it again over calls from
+ MySQL */
+
+ if (trx->has_search_latch) {
+ rw_lock_s_unlock(&btr_search_latch);
+ trx->has_search_latch = FALSE;
+ }
+
+ trx->search_latch_timeout = BTR_SEA_TIMEOUT;
+
+ goto no_shortcut;
+ }
+
if (!trx->has_search_latch) {
rw_lock_s_lock(&btr_search_latch);
trx->has_search_latch = TRUE;
-
- } else if (btr_search_latch.writer_is_wait_ex) {
- /* There is an x-latch request waiting:
- release the s-latch for a moment to reduce
- starvation */
-
- rw_lock_s_unlock(&btr_search_latch);
- rw_lock_s_lock(&btr_search_latch);
}
shortcut = row_sel_try_search_shortcut_for_mysql(&rec,
- prebuilt, &mtr);
+ prebuilt, &mtr);
if (shortcut == SEL_FOUND) {
row_sel_store_mysql_rec(buf, prebuilt, rec);
@@ -2609,7 +2628,16 @@ row_search_for_mysql(
/* printf("%s shortcut\n", index->name); */
srv_n_rows_read++;
+
+ if (trx->search_latch_timeout > 0
+ && trx->has_search_latch) {
+ trx->search_latch_timeout--;
+
+ rw_lock_s_unlock(&btr_search_latch);
+ trx->has_search_latch = FALSE;
+ }
+
trx->op_info = "";
return(DB_SUCCESS);
@@ -2619,6 +2647,16 @@ row_search_for_mysql(
/* printf("%s record not found 2\n",
index->name); */
+
+ if (trx->search_latch_timeout > 0
+ && trx->has_search_latch) {
+
+ trx->search_latch_timeout--;
+
+ rw_lock_s_unlock(&btr_search_latch);
+ trx->has_search_latch = FALSE;
+ }
+
trx->op_info = "";
return(DB_RECORD_NOT_FOUND);
}
@@ -2627,7 +2665,7 @@ row_search_for_mysql(
mtr_start(&mtr);
}
}
-
+no_shortcut:
if (trx->has_search_latch) {
rw_lock_s_unlock(&btr_search_latch);
trx->has_search_latch = FALSE;