[Commits] ddcd3b0: Issue#36: Range in form tbl.key >= const doesn't work in reverse column family

Sergei Petrunia psergey at askmonty.org
Sun Mar 8 23:43:53 EET 2015


revision-id: ddcd3b0848a70b7019990ac264505bd04673c9a3
parent(s): 3172566cf53fa3bf9a05c6a4bb20b4abe1e4b739
committer: Sergei Petrunia
branch nick: mysql-5.6-rocksdb-issue16-splitthefix
timestamp: 2015-03-09 00:43:53 +0300
message:

Issue#36: Range in form tbl.key >= const doesn't work in reverse column family

Fix ha_rocksdb::index_read_map() to correctly handle HA_READ_KEY_OR_NEXT
search flag. (ha_rocksdb::is_ascending already handles HA_READ_KEY_OR_NEXT
correctly)

---
 mysql-test/r/rocksdb_range.result        |   39 +++++++++++++++++-
 mysql-test/t/rocksdb_range.test          |   25 ++++++++++-
 storage/rocksdb/ha_rocksdb.cc            |   29 +++++++++++++
 storage/rocksdb/rocksdb-range-access.txt |   66 ++++++++++++++++++++++++++++++
 4 files changed, 157 insertions(+), 2 deletions(-)

diff --git a/mysql-test/r/rocksdb_range.result b/mysql-test/r/rocksdb_range.result
index 2d6f34b..69dae45 100644
--- a/mysql-test/r/rocksdb_range.result
+++ b/mysql-test/r/rocksdb_range.result
@@ -69,4 +69,41 @@ select * from t2 force index (a) where a=-1 and pk in (101,102);
 pk	a	b
 select * from t2 force index (a) where a=100 and pk in (101,102);
 pk	a	b
-drop table t0,t1,t2;
+#
+# #36: Range in form tbl.key >= const doesn't work in reverse column family
+#
+explain
+select count(*) from t2 force index (a) where a>=0 and a <=1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	range	a	a	4	NULL	10	Using where; Using index
+select count(*) from t2 force index (a) where a>=0 and a <=1;
+count(*)
+20
+explain
+select count(*) from t2 force index (a) where a>=-1 and a <=1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	range	a	a	4	NULL	10	Using where; Using index
+select count(*) from t2 force index (a) where a>=-1 and a <=1;
+count(*)
+20
+explain
+select * from t2 force index (a) where a=0 and pk>=3;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	range	a	a	8	NULL	10	Using where
+select * from t2 force index (a) where a=0 and pk>=3;
+pk	a	b
+3	0	3
+4	0	4
+5	0	5
+6	0	6
+7	0	7
+8	0	8
+9	0	9
+# Try edge cases where we fall over the end of the table
+create table t3 like t2;
+insert into t3 select * from t2;
+select * from t3 where pk>=1000000;
+pk	a	b
+select * from t2 where pk>=1000000;
+pk	a	b
+drop table t0,t1,t2,t3;
diff --git a/mysql-test/t/rocksdb_range.test b/mysql-test/t/rocksdb_range.test
index 61a87d8..4ac4276 100644
--- a/mysql-test/t/rocksdb_range.test
+++ b/mysql-test/t/rocksdb_range.test
@@ -47,5 +47,28 @@ select * from t2 force index (a) where a=-1;
 select * from t2 force index (a) where a=-1 and pk in (101,102);
 select * from t2 force index (a) where a=100 and pk in (101,102);
 
-drop table t0,t1,t2;
+
+--echo #
+--echo # #36: Range in form tbl.key >= const doesn't work in reverse column family
+--echo #
+explain
+select count(*) from t2 force index (a) where a>=0 and a <=1;
+select count(*) from t2 force index (a) where a>=0 and a <=1;
+
+explain
+select count(*) from t2 force index (a) where a>=-1 and a <=1;
+select count(*) from t2 force index (a) where a>=-1 and a <=1;
+
+explain
+select * from t2 force index (a) where a=0 and pk>=3;
+select * from t2 force index (a) where a=0 and pk>=3;
+
+--echo # Try edge cases where we fall over the end of the table
+create table t3 like t2;
+insert into t3 select * from t2;
+
+select * from t3 where pk>=1000000;
+select * from t2 where pk>=1000000;
+
+drop table t0,t1,t2,t3;
 
diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc
index 4dbbe3c..f2167b4 100644
--- a/storage/rocksdb/ha_rocksdb.cc
+++ b/storage/rocksdb/ha_rocksdb.cc
@@ -2662,8 +2662,37 @@ int ha_rocksdb::index_read_map(uchar *buf, const uchar *key,
   }
   case HA_READ_KEY_OR_NEXT:
   {
+    /* 
+      We are looking for the first record such that 
+        index_tuple >= lookup_tuple.
+    */
+    if (key_descr[active_index]->is_reverse_cf)
+    {
+      if (!scan_it->Valid())
+      {
+        scan_it->SeekToLast();
+      }
+      else
+      {
+        /*
+          When using a full extended key tuple: we should not step back if 
+          we've found an exact match.
+        */
+        rkey= scan_it->key();
+        if (!using_full_key || 
+            (!kd->covers_key(rkey.data(), rkey.size()) ||
+             kd->cmp_full_keys(rkey.data(), rkey.size(), 
+                               slice.data(), slice.size(), n_used_parts)))
+        {
+          scan_it->Prev();
+        }
+      }
+    }
+
     if (!scan_it->Valid())
+    {
       rc= HA_ERR_KEY_NOT_FOUND;
+    }
     else
     {
       rkey= scan_it->key();
diff --git a/storage/rocksdb/rocksdb-range-access.txt b/storage/rocksdb/rocksdb-range-access.txt
index d86d5c6..ecddcff 100644
--- a/storage/rocksdb/rocksdb-range-access.txt
+++ b/storage/rocksdb/rocksdb-range-access.txt
@@ -74,3 +74,69 @@ RocksDB calls:
   if (it->Valid() && kd->covers_key(..) && kd->cmp_full_keys(...))
     return record.
 
+== HA_READ_KEY_OR_NEXT, forward CF ==
+
+This is finding min(key) such that key >= lookup_tuple.
+
+If lookup tuple is kv-bbb:
+
+  ( kv )-aaa-pk
+# ( kv )-bbb      <-- "kv-bbb" doesn't exist in the database, but it would be
+                       here.
+  ( kv )-bbb-pk1  <--- Seek("kv-bbb") will put us here on the next record.
+  ( kv )-bbb-pk2       
+  ( kv )-bbb-...
+
+RocksDB calls:
+
+  Seek(kv);
+  if (it->Valid() && kd->covers_key(..) && kd->cmp_full_keys(...))
+    return record.
+
+== HA_READ_KEY_OR_NEXT, backward CF ==
+
+When specified key tuple is a key prefix:
+
+  (kv+1)-xxx-pk
+  ( kv )-ccc-pk 
+  ( kv )-bbb-pk3
+  ( kv )-bbb-pk2
+  ( kv )-bbb-pk1 < -- We need to be here (or above)
+# ( kv )-bbb         <---we call Seek(kv-bbb)
+  ( kv )-aaa-pk      ... and end up here.  Should call it->Prev().  
+
+There is a special case when (kv)-bbb-pk1 is the last record in the CF, and 
+we get invalid iterator. Then, we need to call SeekToLast().
+
+Another kind of special case is when we need to seek to the full value. 
+Suppose, the lookup tuple is kv-bbb-pk1:
+
+  (kv+1)-xxx-pk
+  ( kv )-ccc-pk 
+  ( kv )-bbb-pk3
+  ( kv )-bbb-pk2
+  ( kv )-bbb-pk1 < -- Seek(kv-bbb-pk1)
+  ( kv )-bbb-pk0  
+
+Then, Seek(kv-bbb-pk1) may position us exactly at the tuple we need, and we
+won't need to call it->Prev().
+If we kv-bbb-pk1 is not present in the database, we will be positioned on
+kv-bbb-pk0, and we will need to call it->Prev().
+If we get an invalid iterator, we DO need to call SeekToLast().
+
+RocksDB calls:
+ 
+  Seek(...);
+
+  if (!it->Valid())
+    it->SeekToLast();
+  else
+  {
+    if (!using_full_key ||
+        !(kd->covers_key(...) || kd->cmp_full_keys(...))
+      it->Prev();
+  }
+
+  if (it->Valid() && kd->covers_key(..))
+    return record.
+


More information about the commits mailing list