
This file describes how MySQL index navigation commands are translated into
RocksDB index navigation commands.

Index tuples are shown as

  ( kv )-aaa-pkN

here
 * '(kv)' is the 4-byte index number.
 * '-' is just for readability
 * everything that follows the '-' is mem-comparable form of the key.
   In ascii encoding,  aaa < bbb < ccc < xxx.

Tuples that start with '#' do not exist in the database. They are only shown
to demonstrate where Seek() calls end up with.

== HA_READ_KEY_EXACT, forward CF ==

  (kv-1)-xxx-pk
# ( kv )-aaa      <-- "kv-aaa" doesn't exist in the database, but it would be
                       here.
  ( kv )-aaa-pk   <--- Seek("kv-aaa") will put us here on the next record.
  ( kv )-aaa-pk2
  ( kv )-bbb-...

RocksDB calls:

  it->Seek(kv);
  if (it->Valid() && kd->covers_key(..) && kd->cmp_full_keys(...))
    return record.

== HA_READ_KEY_EXACT, backward CF ==

When we need to seek to a tuple that is a prefix of a full key:

  (kv+1)-xxx-pk
  ( kv )-ccc-pk
  ( kv )-bbb-pk3
  ( kv )-bbb-pk2
  ( kv )-bbb-pk1  <--- SeekForPrev("kv-bbb") will put us here on the previous
                       record.
# ( kv )-bbb      <--- "kv-bbb" doesn't exist in the database, but it would be
  ( kv )-aaa-pk         here.

Even when (kv)-bbb-pk1 is the last record in the CF, SeekForPrev() will find the
last record before "kv-bbb", so it already takes care of this case for us.

RocksDB calls:

  it->SeekForPrev(kv);
  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(..))
    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  <--- Seek("kv-bbb") will put us here on the previous record.
# ( kv )-bbb      <--- "kv-bbb" doesn't exist in the database, but it would be
                       here.
  ( kv )-aaa-pk

Even when (kv)-bbb-pk1 is the last record in the CF, SeekForPrev() will find the
last record before "kv-bbb", so it already takes care of this case for us.

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 < -- SeekForPrev(kv-bbb-pk1)
  ( kv )-bbb-pk0

Then, SeekForPrev(kv-bbb-pk1) may position us exactly at the tuple we need.
Even If kv-bbb-pk1 is not present in the database, we will be positioned on
kv-bbb-pk2 no matter whether kv-bbb-pk2 is the last key or not.

RocksDB calls:

  SeekForPrev(...);
  if (it->Valid() && kd->covers_key(..))
    return record.

== HA_READ_AFTER_KEY, forward CF ==

This is finding min(key) such that key > lookup_key.

Suppose lookup_key = kv-bbb

  ( kv )-aaa-pk
# ( kv )-bbb
  ( kv )-bbb-pk1  <--- Seek("kv-bbb") will put us here. We need to
  ( kv )-bbb-pk2       get to the value that is next after 'bbb'.
  ( kv )-bbb-pk3
  ( kv )-bbb-pk4
  ( kv )-bbb-pk5
  ( kv )-ccc-pkN  <--- That is, we need to be here.

However, we don't know that the next value is kv-ccc. Instead, we seek to the
first value that strictly greater than 'kv-bbb'. It is Successor(kv-bbb).

It doesn't matter if we're using a full extended key or not.

RocksDB calls:

  Seek(Successor(kv-bbb));
  if (it->Valid() && kd->covers_key(...))
    return record;

Note that the code is the same as with HA_READ_KEY_OR_NEXT, except that
we seek to Successor($lookup_key) instead of $lookup_key itself.

== HA_READ_AFTER_KEY, backward CF ==

Suppose, the lookup key is 'kv-bbb':

  (kv+1)-xxx-pk
  ( kv )-ccc-pk7
  ( kv )-ccc-pk6     <-- We get here when we call Seek(Successor(kv-bbb))
# Successor(kv-bbb)
  ( kv )-bbb-pk5
  ( kv )-bbb-pk4
  ( kv )-bbb-pk3
  ( kv )-bbb-pk2
  ( kv )-bbb-pk1
# ( kv )-bbb         <-- We would get here if we called SeekForPrev(kv-bbb).
  ( kv )-aaa-pk

RocksDB calls:

  SeekForPrev(Successor(kv-bbb));
  if (it->Valid() && kd->covers_key(...))
    return record.

Note that the code is the same as with HA_READ_KEY_OR_NEXT, except that
we seek to Successor($lookup_key) instead of $lookup_key itself.

== HA_READ_BEFORE_KEY, forward CF ==

This is finding max(key) such that key < lookup_tuple.

Suppose, lookup_tuple=kv-bbb.

  ( kv )-aaa-pk1
  ( kv )-aaa-pk2
  ( kv )-aaa-pk3  <-- SeekForPrev("kv-bbb") will put us here.
# ( kv )-bbb
  ( kv )-bbb-pk4
  ( kv )-bbb-pk5
  ( kv )-bbb-pk6

If the lookup tuple is a full key (e.g. kv-bbb-pk3), and the key is present in
the database, the iterator will be positioned on the key. We will need to call
Prev() to get the next key.

RocksDB calls:

  it->SeekForPrev(kv-bbb);
  if (it->Valid() && using_full_key &&
      kd->value_matches_prefix(...))
  {
    /* We are using full key and we've hit an exact match */
    it->Prev();
  }

  if (it->Valid() && kd->covers_key(...))
    return record;

== HA_READ_BEFORE_KEY, backward CF ==

This is finding max(key) such that key < lookup_tuple.
Suppose, lookup_tuple=kv-bbb, a prefix of the full key.

  ( kv )-bbb-pk6
  ( kv )-bbb-pk5
  ( kv )-bbb-pk4
# ( kv )-bbb
  ( kv )-aaa-pk3 <-- Need to be here, and Seek("kv-bbb") will put us here
  ( kv )-aaa-pk2
  ( kv )-aaa-pk1

If the lookup tuple is a full key (e.g. kv-bbb-pk4), and the key is present in
the database, the iterator will be positioned on the key. We will need to call
Next() to get the next key.

RocksDB calls:

  it->Seek(kv-bbb);
  if (it->Valid() && using_full_key &&
      kd->value_matches_prefix(...))
  {
    /* We are using full key and we've hit an exact match */
    it->Next();
  }

  if (it->Valid() && kd->covers_key(...))
    return record;

== HA_READ_PREFIX_LAST, forward CF ==

Find the last record with the specified index prefix lookup_tuple.

Suppose, lookup_tuple='kv-bbb'

  ( kv )-aaa-pk2
  ( kv )-aaa-pk3
# ( kv )-bbb
  ( kv )-bbb-pk4
  ( kv )-bbb-pk5
  ( kv )-bbb-pk6
  ( kv )-bbb-pk7 <--- SeekForPrev(Successor(kv-bbb)) will get us here
# ( kv )-ccc
  ( kv )-ccc-pk8
  ( kv )-ccc-pk9

RocksDB calls:

  SeekForPrev(Successor(kv-bbb));
  if (using_full_key && it->Valid() && !cmp_full_keys(Sucessor(lookup_key)))
    it->Prev();
  if (it->Valid() && kd->covers_key(...))
  {
    if (!cmp_full_keys(lookup_tuple))  // not needed in _OR_PREV
    {
      // the record's prefix matches lookup_tuple.
      return record;
    }
  }

== HA_READ_PREFIX_LAST, backward CF ==

Suppose, lookup_tuple='kv-bbb'

  ( kv )-ccc-pk9
  ( kv )-ccc-pk8
# ( kv )-ccc     <--  2. Seek(Successor(kv-bbb)) will point here
                         and it will fall down to the next row.
  ( kv )-bbb-pk7 <--- 1. Need to be here.
  ( kv )-bbb-pk6
  ( kv )-bbb-pk5
  ( kv )-bbb-pk4
# ( kv )-bbb
  ( kv )-aaa-pk3
  ( kv )-aaa-pk2


RocksDB calls:

  it->Seek(Successor(kv-bbb));

  if (using_full_key && it->Valid() && !cmp_full_keys(Sucessor(lookup_key)))
    it->Next();

  if (it->Valid() && kd->covers_key(..))
  {
    if (!cmp_full_keys(...)) // not needed in _OR_PREV
    {
      // the record's prefix matches lookup_tuple.
      return record;
    }
  }

== HA_READ_PREFIX_LAST_OR_PREV, forward or backward CF ==

This is just like HA_READ_PREFIX_LAST but we don't need to check that the key
we've got is in the search prefix. (search for "not needed in _OR_PREV" above)
