changeset 150:01e070c97ee7

Fix bug in default comparator: Return correct separator for difficult cases This is important if TableBuilder wants a separator between K and succ(K), where succ(K) is usually just a string of K's first characters plus 1. In this case we now return K with its last byte incremented by one, which isn't really "short" anymore, but a valid separator. Otherwise, logic relying on the key in index blocks being actually *past* the referenced block fails in some cases, for example on the last block of a table.
author Lewin Bormann <lbo@spheniscida.de>
date Sun, 29 Jan 2017 16:13:36 +0100
parents 11f887625190
children 6e14c9e7e53d
files src/cmp.rs
diffstat 1 files changed, 11 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/cmp.rs	Sun Jan 29 15:26:56 2017 +0100
+++ b/src/cmp.rs	Sun Jan 29 16:13:36 2017 +0100
@@ -57,7 +57,12 @@
 
             diff_at += 1;
         }
-        return a.to_vec();
+        // Backup case: either `a` is full of 0xff, or all different places are less than 2
+        // characters apart.
+        // The result is not necessarily short, but a good separator.
+        let mut sep = a.to_vec();
+        sep[a.len() - 1] += 1;
+        return sep;
     }
 
     fn find_short_succ(&self, a: &[u8]) -> Vec<u8> {
@@ -194,15 +199,17 @@
         assert_eq!(DefaultCmp.find_shortest_sep("abcd".as_bytes(), "abcf".as_bytes()),
                    "abce".as_bytes());
         assert_eq!(DefaultCmp.find_shortest_sep("abc".as_bytes(), "acd".as_bytes()),
-                   "abc".as_bytes());
+                   "abd".as_bytes());
         assert_eq!(DefaultCmp.find_shortest_sep("abcdefghi".as_bytes(), "abcffghi".as_bytes()),
                    "abce".as_bytes());
         assert_eq!(DefaultCmp.find_shortest_sep("a".as_bytes(), "a".as_bytes()),
                    "a".as_bytes());
         assert_eq!(DefaultCmp.find_shortest_sep("a".as_bytes(), "b".as_bytes()),
-                   "a".as_bytes());
+                   "b".as_bytes());
         assert_eq!(DefaultCmp.find_shortest_sep("abc".as_bytes(), "zzz".as_bytes()),
                    "b".as_bytes());
+        assert_eq!(DefaultCmp.find_shortest_sep("yyy".as_bytes(), "z".as_bytes()),
+                   "yyz".as_bytes());
         assert_eq!(DefaultCmp.find_shortest_sep("".as_bytes(), "".as_bytes()),
                    "".as_bytes());
     }
@@ -229,7 +236,7 @@
                    LookupKey::new("b".as_bytes(), types::MAX_SEQUENCE_NUMBER).internal_key());
         assert_eq!(cmp.find_shortest_sep(LookupKey::new("abc".as_bytes(), 1).internal_key(),
                                          LookupKey::new("acd".as_bytes(), 2).internal_key()),
-                   LookupKey::new("abc".as_bytes(), 1).internal_key());
+                   LookupKey::new("abd".as_bytes(), 1).internal_key());
         assert_eq!(cmp.find_shortest_sep(LookupKey::new("abc".as_bytes(), 1).internal_key(),
                                          LookupKey::new("abe".as_bytes(), 2).internal_key()),
                    LookupKey::new("abd".as_bytes(), 1).internal_key());