diff options
author | unknown <tim@threads.polyesthetic.msg> | 2001-05-14 14:23:45 -0400 |
---|---|---|
committer | unknown <tim@threads.polyesthetic.msg> | 2001-05-14 14:23:45 -0400 |
commit | aa07f65caee02cddd38a9a250ac3024ea70dcb2b (patch) | |
tree | 20d648d337c79f661f35f953b2955e8d5a316b2c /innobase/row/row0sel.c | |
parent | 1115a79126c7031c8ebedae237b02b56af95f1ed (diff) | |
parent | 258a55ff6884b85e06714090947bdb53160811b9 (diff) | |
download | mariadb-git-aa07f65caee02cddd38a9a250ac3024ea70dcb2b.tar.gz |
Merge work.mysql.com:/home/bk/mysql
into threads.polyesthetic.msg:/usr/local/src/my/3
BitKeeper/etc/logging_ok:
auto-union
sql/sql_select.cc:
Auto merged
Diffstat (limited to 'innobase/row/row0sel.c')
-rw-r--r-- | innobase/row/row0sel.c | 97 |
1 files changed, 95 insertions, 2 deletions
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index e6182257581..58e0d053947 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -48,6 +48,52 @@ to que_run_threads: this is to allow canceling runaway queries */ #define SEL_EXHAUSTED 1 #define SEL_RETRY 2 +/************************************************************************ +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. */ +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) +{ + dict_col_t* col; + byte* sec_field; + ulint sec_len; + byte* clust_field; + ulint clust_len; + ulint n; + ulint i; + + n = dict_index_get_n_ordering_defined_by_user(sec_index); + + for (i = 0; i < n; i++) { + col = dict_field_get_col( + dict_index_get_nth_field(sec_index, i)); + + clust_field = rec_get_nth_field(clust_rec, + dict_col_get_clust_pos(col), + &clust_len); + sec_field = rec_get_nth_field(sec_rec, i, &sec_len); + + if (sec_len != clust_len) { + + return(FALSE); + } + + if (sec_len != UNIV_SQL_NULL + && ut_memcmp(sec_field, clust_field, sec_len) != 0) { + + return(FALSE); + } + } + + return(TRUE); +} + /************************************************************************* Creates a select node struct. */ @@ -561,6 +607,8 @@ row_sel_get_clust_rec( /* This is a non-locking consistent read: if necessary, fetch a previous version of the record */ + old_vers = NULL; + if (!lock_clust_rec_cons_read_sees(clust_rec, index, node->read_view)) { @@ -579,6 +627,28 @@ row_sel_get_clust_rec( return(DB_SUCCESS); } } + + /* If we had to go to an earlier version of row or the + secondary index record is delete marked, then it may be that + the secondary index record corresponding to clust_rec + (or old_vers) is not rec; in that case we must ignore + such row because in our snapshot rec would not have existed. + Remember that from rec we cannot see directly which transaction + id corresponds to it: we have to go to the clustered index + record. A query where we want to fetch all rows where + the secondary index value is in some interval would return + a wrong result if we would not drop rows which we come to + visit through secondary index records that would not really + exist in our snapshot. */ + + if ((old_vers || rec_get_deleted_flag(rec)) + && !row_sel_sec_rec_is_for_clust_rec(rec, plan->index, + clust_rec, index)) { + clust_rec = NULL; + *out_rec = clust_rec; + + return(DB_SUCCESS); + } } /* Fetch the columns needed in test conditions */ @@ -2105,6 +2175,8 @@ row_sel_get_clust_rec_for_mysql( a previous version of the record */ trx = thr_get_trx(thr); + + old_vers = NULL; if (!lock_clust_rec_cons_read_sees(clust_rec, clust_index, trx->read_view)) { @@ -2121,6 +2193,25 @@ row_sel_get_clust_rec_for_mysql( clust_rec = old_vers; } + + /* If we had to go to an earlier version of row or the + secondary index record is delete marked, then it may be that + the secondary index record corresponding to clust_rec + (or old_vers) is not rec; in that case we must ignore + such row because in our snapshot rec would not have existed. + Remember that from rec we cannot see directly which transaction + id corrsponds to it: we have to go to the clustered index + record. A query where we want to fetch all rows where + the secondary index value is in some interval would return + a wrong result if we would not drop rows which we come to + visit through secondary index records that would not really + exist in our snapshot. */ + + if ((old_vers || rec_get_deleted_flag(rec)) + && !row_sel_sec_rec_is_for_clust_rec(rec, sec_index, + clust_rec, clust_index)) { + clust_rec = NULL; + } } *out_rec = clust_rec; @@ -2609,8 +2700,10 @@ rec_loop: goto next_rec; } - - rec = clust_rec; + + if (prebuilt->need_to_access_clustered) { + rec = clust_rec; + } } /* We found a qualifying row */ |