1 // Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 package org.rocksdb;
6 
7 import org.junit.ClassRule;
8 import org.junit.Rule;
9 import org.junit.Test;
10 import org.junit.rules.TemporaryFolder;
11 
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.List;
15 
16 import static java.nio.charset.StandardCharsets.UTF_8;
17 import static org.assertj.core.api.Assertions.assertThat;
18 
19 public class KeyMayExistTest {
20 
21   @ClassRule
22   public static final RocksNativeLibraryResource ROCKS_NATIVE_LIBRARY_RESOURCE =
23       new RocksNativeLibraryResource();
24 
25   @Rule
26   public TemporaryFolder dbFolder = new TemporaryFolder();
27 
28   @Test
keyMayExist()29   public void keyMayExist() throws RocksDBException {
30     final List<ColumnFamilyDescriptor> cfDescriptors = Arrays.asList(
31         new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
32         new ColumnFamilyDescriptor("new_cf".getBytes())
33     );
34 
35     final List<ColumnFamilyHandle> columnFamilyHandleList = new ArrayList<>();
36     try (final DBOptions options = new DBOptions()
37         .setCreateIfMissing(true)
38         .setCreateMissingColumnFamilies(true);
39          final RocksDB db = RocksDB.open(options,
40              dbFolder.getRoot().getAbsolutePath(),
41              cfDescriptors, columnFamilyHandleList)) {
42       try {
43         assertThat(columnFamilyHandleList.size()).
44             isEqualTo(2);
45         db.put("key".getBytes(UTF_8), "value".getBytes(UTF_8));
46         // Test without column family
47         final Holder<byte[]> holder = new Holder<>();
48         boolean exists = db.keyMayExist("key".getBytes(UTF_8), holder);
49         assertThat(exists).isTrue();
50         assertThat(holder.getValue()).isNotNull();
51         assertThat(new String(holder.getValue(), UTF_8)).isEqualTo("value");
52 
53         exists = db.keyMayExist("key".getBytes(UTF_8), null);
54         assertThat(exists).isTrue();
55 
56         // Slice key
57         final StringBuilder builder = new StringBuilder("prefix");
58         final int offset = builder.toString().length();
59         builder.append("slice key 0");
60         final int len = builder.toString().length() - offset;
61         builder.append("suffix");
62 
63         final byte[] sliceKey = builder.toString().getBytes(UTF_8);
64         final byte[] sliceValue = "slice value 0".getBytes(UTF_8);
65         db.put(sliceKey, offset, len, sliceValue, 0, sliceValue.length);
66 
67         exists = db.keyMayExist(sliceKey, offset, len, holder);
68         assertThat(exists).isTrue();
69         assertThat(holder.getValue()).isNotNull();
70         assertThat(holder.getValue()).isEqualTo(sliceValue);
71 
72         exists = db.keyMayExist(sliceKey, offset, len, null);
73         assertThat(exists).isTrue();
74 
75         // Test without column family but with readOptions
76         try (final ReadOptions readOptions = new ReadOptions()) {
77           exists = db.keyMayExist(readOptions, "key".getBytes(UTF_8), holder);
78           assertThat(exists).isTrue();
79           assertThat(holder.getValue()).isNotNull();
80           assertThat(new String(holder.getValue(), UTF_8)).isEqualTo("value");
81 
82           exists = db.keyMayExist(readOptions, "key".getBytes(UTF_8), null);
83           assertThat(exists).isTrue();
84 
85           exists = db.keyMayExist(readOptions, sliceKey, offset, len, holder);
86           assertThat(exists).isTrue();
87           assertThat(holder.getValue()).isNotNull();
88           assertThat(holder.getValue()).isEqualTo(sliceValue);
89 
90           exists = db.keyMayExist(readOptions, sliceKey, offset, len, null);
91           assertThat(exists).isTrue();
92         }
93 
94         // Test with column family
95         exists = db.keyMayExist(columnFamilyHandleList.get(0), "key".getBytes(UTF_8),
96             holder);
97         assertThat(exists).isTrue();
98         assertThat(holder.getValue()).isNotNull();
99         assertThat(new String(holder.getValue(), UTF_8)).isEqualTo("value");
100 
101         exists = db.keyMayExist(columnFamilyHandleList.get(0), "key".getBytes(UTF_8),
102             null);
103         assertThat(exists).isTrue();
104 
105         // Test slice sky with column family
106         exists = db.keyMayExist(columnFamilyHandleList.get(0), sliceKey, offset, len,
107             holder);
108         assertThat(exists).isTrue();
109         assertThat(holder.getValue()).isNotNull();
110         assertThat(holder.getValue()).isEqualTo(sliceValue);
111 
112         exists = db.keyMayExist(columnFamilyHandleList.get(0), sliceKey, offset, len,
113             null);
114         assertThat(exists).isTrue();
115 
116         // Test with column family and readOptions
117         try (final ReadOptions readOptions = new ReadOptions()) {
118           exists = db.keyMayExist(columnFamilyHandleList.get(0), readOptions,
119               "key".getBytes(UTF_8), holder);
120           assertThat(exists).isTrue();
121           assertThat(holder.getValue()).isNotNull();
122           assertThat(new String(holder.getValue(), UTF_8)).isEqualTo("value");
123 
124           exists = db.keyMayExist(columnFamilyHandleList.get(0), readOptions,
125               "key".getBytes(UTF_8), null);
126           assertThat(exists).isTrue();
127 
128           // Test slice key with column family and read options
129           exists = db.keyMayExist(columnFamilyHandleList.get(0), readOptions,
130               sliceKey, offset, len, holder);
131           assertThat(exists).isTrue();
132           assertThat(holder.getValue()).isNotNull();
133           assertThat(holder.getValue()).isEqualTo(sliceValue);
134 
135           exists = db.keyMayExist(columnFamilyHandleList.get(0), readOptions,
136               sliceKey, offset, len, null);
137           assertThat(exists).isTrue();
138         }
139 
140         // KeyMayExist in CF1 must return null value
141         exists = db.keyMayExist(columnFamilyHandleList.get(1),
142             "key".getBytes(UTF_8), holder);
143         assertThat(exists).isFalse();
144         assertThat(holder.getValue()).isNull();
145         exists = db.keyMayExist(columnFamilyHandleList.get(1),
146             "key".getBytes(UTF_8), null);
147         assertThat(exists).isFalse();
148 
149         // slice key
150         exists = db.keyMayExist(columnFamilyHandleList.get(1),
151             sliceKey, 1, 3, holder);
152         assertThat(exists).isFalse();
153         assertThat(holder.getValue()).isNull();
154         exists = db.keyMayExist(columnFamilyHandleList.get(1),
155             sliceKey, 1, 3, null);
156         assertThat(exists).isFalse();
157       } finally {
158         for (final ColumnFamilyHandle columnFamilyHandle :
159             columnFamilyHandleList) {
160           columnFamilyHandle.close();
161         }
162       }
163     }
164   }
165 
166   @Test
keyMayExistNonUnicodeString()167   public void keyMayExistNonUnicodeString() throws RocksDBException {
168     try (final Options options = new Options()
169         .setCreateIfMissing(true)
170         .setCreateMissingColumnFamilies(true);
171          final RocksDB db = RocksDB.open(options,
172              dbFolder.getRoot().getAbsolutePath())) {
173       final byte key[] = "key".getBytes(UTF_8);
174       final byte value[] = { (byte)0x80 };  // invalid unicode code-point
175       db.put(key, value);
176 
177       final byte buf[] = new byte[10];
178       final int read = db.get(key, buf);
179       assertThat(read).isEqualTo(1);
180       assertThat(buf).startsWith(value);
181 
182       final Holder<byte[]> holder = new Holder<>();
183       boolean exists = db.keyMayExist("key".getBytes(UTF_8), holder);
184       assertThat(exists).isTrue();
185       assertThat(holder.getValue()).isNotNull();
186       assertThat(holder.getValue()).isEqualTo(value);
187 
188       exists = db.keyMayExist("key".getBytes(UTF_8), null);
189       assertThat(exists).isTrue();
190     }
191   }
192 }
193