summaryrefslogtreecommitdiff
path: root/innobase/row/row0sel.c
diff options
context:
space:
mode:
authorunknown <tim@threads.polyesthetic.msg>2001-05-14 14:23:45 -0400
committerunknown <tim@threads.polyesthetic.msg>2001-05-14 14:23:45 -0400
commitaa07f65caee02cddd38a9a250ac3024ea70dcb2b (patch)
tree20d648d337c79f661f35f953b2955e8d5a316b2c /innobase/row/row0sel.c
parent1115a79126c7031c8ebedae237b02b56af95f1ed (diff)
parent258a55ff6884b85e06714090947bdb53160811b9 (diff)
downloadmariadb-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.c97
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 */