Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
queries.hpp
Go to the documentation of this file.
1#pragma once
2
6#include "lmdb.h"
7#include <cstdint>
8#include <functional>
9#include <vector>
10
11namespace bb::lmdblib {
12
13class LMDBTransaction;
14class LMDBWriteTransaction;
15class LMDBCursor;
16
17namespace lmdb_queries {
18
19template <typename TKey, typename TValue, typename TxType>
20bool get_value_or_previous(TKey& key, TValue& data, const LMDBDatabase& db, const TxType& tx)
21{
22 std::vector<uint8_t> keyBuffer = serialise_key(key);
23 uint32_t keySize = static_cast<uint32_t>(keyBuffer.size());
24 MDB_cursor* cursor = nullptr;
25 bool success = false;
26 call_lmdb_func("mdb_cursor_open", mdb_cursor_open, tx.underlying(), db.underlying(), &cursor);
27
28 try {
29 MDB_val dbKey;
30 dbKey.mv_size = keySize;
31 dbKey.mv_data = (void*)keyBuffer.data();
32 MDB_val dbVal;
33
34 // Look for the key >= to that provided
35 int code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_SET_RANGE);
36 if (code == 0) {
37 // we found the key, now determine if it is the exact key
38 std::vector<uint8_t> temp = mdb_val_to_vector(dbKey);
39 if (keyBuffer == temp) {
40 // we have the exact key
41 deserialise_key(dbVal.mv_data, data);
42 success = true;
43 } else {
44 // We have a key of the same size but larger value OR a larger size
45 // either way we now need to find the previous key
46 code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_PREV);
47 if (code == 0) {
48 // We have found a previous key. It could be of the same size but smaller value, or smaller size
49 // which is equal to not found
50 if (dbKey.mv_size != keySize) {
51 // There is no previous key, do nothing
52 } else {
53 deserialise_key(dbVal.mv_data, data);
54 deserialise_key(dbKey.mv_data, key);
55 success = true;
56 }
57 } else if (code == MDB_NOTFOUND) {
58 // There is no previous key, do nothing
59 } else {
60 throw_error("get_value_or_previous::mdb_cursor_get", code);
61 }
62 }
63 } else if (code == MDB_NOTFOUND) {
64 // The key was not found, use the last key in the db
65 code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_PREV);
66 if (code == 0) {
67 // We found the last key, but we need to ensure it is the same size
68 if (dbKey.mv_size != keySize) {
69 // The key is not the same size, same as not found, do nothing
70 } else {
71 deserialise_key(dbVal.mv_data, data);
72 deserialise_key(dbKey.mv_data, key);
73 success = true;
74 }
75 } else if (code == MDB_NOTFOUND) {
76 // DB is empty?
77 } else {
78 throw_error("get_value_or_previous::mdb_cursor_get", code);
79 }
80 } else {
81 throw_error("get_value_or_previous::mdb_cursor_get", code);
82 }
83 } catch (std::exception& e) {
84 call_lmdb_func(mdb_cursor_close, cursor);
85 throw;
86 }
87 call_lmdb_func(mdb_cursor_close, cursor);
88 return success;
89}
90
91template <typename TKey, typename TValue, typename TxType>
93 TValue& data,
94 const LMDBDatabase& db,
95 const std::function<bool(const MDB_val&)>& is_valid,
96 const TxType& tx)
97{
98 std::vector<uint8_t> keyBuffer = serialise_key(key);
99 uint32_t keySize = static_cast<uint32_t>(keyBuffer.size());
100 MDB_cursor* cursor = nullptr;
101 bool success = false;
102 call_lmdb_func("mdb_cursor_open", mdb_cursor_open, tx.underlying(), db.underlying(), &cursor);
103
104 try {
105 MDB_val dbKey;
106 dbKey.mv_size = keySize;
107 dbKey.mv_data = (void*)keyBuffer.data();
108
109 MDB_val dbVal;
110 // Look for the key >= to that provided
111 int code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_SET_RANGE);
112 if (code == 0) {
113 bool lower = false;
114 while (!success) {
115 // We found the key, now determine if it is the exact key
116 std::vector<uint8_t> temp = mdb_val_to_vector(dbKey);
117 if (keyBuffer == temp || lower) {
118 // We have the exact key, we need to determine if it is valid
119 if (is_valid(dbVal)) {
120 deserialise_key(dbVal.mv_data, data);
121 deserialise_key(dbKey.mv_data, key);
122 success = true;
123 // It's valid
124 break;
125 }
126 } else if (dbKey.mv_size < keySize) {
127 // We have a key of a smaller size, this means what we are looking for doesn't exist
128 break;
129 }
130 // At this point one of the following is true
131 // 1. We have a key of the same size but larger value
132 // 2. A larger size
133 // 3. The exact key but it is not valid
134 // either way we now need to find the previous key
135 code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_PREV);
136 if (code == 0) {
137 // Success, go round the loop again, this time we will definitely have a lower key
138 lower = true;
139 } else if (code == MDB_NOTFOUND) {
140 // There is no previous key, do nothing
141 break;
142 } else {
143 throw_error("get_value_or_previous::mdb_cursor_get", code);
144 }
145 }
146 } else if (code == MDB_NOTFOUND) {
147 while (!success) {
148 // The key was not found, walk down from the end of the db
149 code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_PREV);
150 if (code == 0) {
151 // We found the last key, but we need to ensure it is the same size
152 if (dbKey.mv_size != keySize) {
153 // The key is not the same size, same as not found, exit
154 break;
155 }
156 if (is_valid(dbVal)) {
157 deserialise_key(dbVal.mv_data, data);
158 deserialise_key(dbKey.mv_data, key);
159 success = true;
160 // It's valid
161 break;
162 }
163 // we will need to go round again
164 } else if (code == MDB_NOTFOUND) {
165 // DB is empty?
166 } else {
167 throw_error("get_value_or_previous::mdb_cursor_get", code);
168 }
169 }
170 } else {
171 throw_error("get_value_or_previous::mdb_cursor_get", code);
172 }
173 } catch (std::exception& e) {
174 call_lmdb_func(mdb_cursor_close, cursor);
175 throw;
176 }
177
178 call_lmdb_func(mdb_cursor_close, cursor);
179 return success;
180}
181
182template <typename TKey, typename TxType>
183bool get_value_or_greater(TKey& key, Value& data, const LMDBDatabase& db, const TxType& tx)
184{
185 bool success = false;
186 Key keyBuffer = serialise_key(key);
187 uint32_t keySize = static_cast<uint32_t>(keyBuffer.size());
188 MDB_cursor* cursor = nullptr;
189 call_lmdb_func("mdb_cursor_open", mdb_cursor_open, tx.underlying(), db.underlying(), &cursor);
190
191 try {
192 MDB_val dbKey;
193 dbKey.mv_size = keySize;
194 dbKey.mv_data = (void*)keyBuffer.data();
195
196 MDB_val dbVal;
197 // Look for the key >= to that provided
198 int code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_SET_RANGE);
199
200 if (code == 0) {
201 // found a key >= our key. if it is not the same size, it must be out of range for what we are looking
202 // for, this means no more data available
203 if (keySize == dbKey.mv_size) {
204 // key is the same size, so this contains the data we are looking for
205 copy_to_vector(dbVal, data);
206 success = true;
207 }
208 } else if (code == MDB_NOTFOUND) {
209 // no key greater than or equal, nothing to extract
210 } else {
211 throw_error("get_value_or_greater::mdb_cursor_get", code);
212 }
213 } catch (std::exception& e) {
214 call_lmdb_func(mdb_cursor_close, cursor);
215 throw;
216 }
217 call_lmdb_func(mdb_cursor_close, cursor);
218 return success;
219}
220
221template <typename TKey, typename TxType>
222void get_all_values_greater_or_equal_key(const TKey& key, ValuesVector& data, const LMDBDatabase& db, const TxType& tx)
223{
224 Key keyBuffer = serialise_key(key);
225 uint32_t keySize = static_cast<uint32_t>(keyBuffer.size());
226 MDB_cursor* cursor = nullptr;
227 call_lmdb_func("mdb_cursor_open", mdb_cursor_open, tx.underlying(), db.underlying(), &cursor);
228
229 try {
230 MDB_val dbKey;
231 dbKey.mv_size = keySize;
232 dbKey.mv_data = (void*)keyBuffer.data();
233
234 MDB_val dbVal;
235 // Look for the key >= to that provided
236 int code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_SET_RANGE);
237 while (true) {
238 if (code == 0) {
239 // found a key >= our key. if it is not the same size, it must be out of range for what we are looking
240 // for, this means no more data available
241 if (keySize != dbKey.mv_size) {
242 break;
243 }
244 // this is data that we need to extract
245 Value temp;
246 copy_to_vector(dbVal, temp);
247 data.emplace_back(temp);
248
249 // move to the next key
250 code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_NEXT);
251 } else if (code == MDB_NOTFOUND) {
252 // no more data to extract
253 break;
254 } else {
255 throw_error("get_all_values_greater_or_equal_key::mdb_cursor_get", code);
256 }
257 }
258 } catch (std::exception& e) {
259 call_lmdb_func(mdb_cursor_close, cursor);
260 throw;
261 }
262 call_lmdb_func(mdb_cursor_close, cursor);
263}
264
265template <typename TKey, typename TxType>
266void delete_all_values_greater_or_equal_key(const TKey& key, const LMDBDatabase& db, const TxType& tx)
267{
268 Key keyBuffer = serialise_key(key);
269 uint32_t keySize = static_cast<uint32_t>(keyBuffer.size());
270 MDB_cursor* cursor = nullptr;
271 call_lmdb_func("mdb_cursor_open", mdb_cursor_open, tx.underlying(), db.underlying(), &cursor);
272
273 try {
274 MDB_val dbKey;
275 dbKey.mv_size = keySize;
276 dbKey.mv_data = (void*)keyBuffer.data();
277
278 MDB_val dbVal;
279 // Look for the key >= to that provided
280 int code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_SET_RANGE);
281 while (true) {
282 if (code == 0) {
283 // found a key >= our key. if it is not the same size, it must be out of range for what we are looking
284 // for, this means no more data available
285 if (keySize != dbKey.mv_size) {
286 break;
287 }
288 // this is data that we need to delete
289 code = mdb_cursor_del(cursor, 0);
290
291 if (code != 0) {
292 throw_error("delete_all_values_greater_or_equal_key::mdb_cursor_del", code);
293 }
294
295 // move to the next key
296 code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_NEXT);
297 } else if (code == MDB_NOTFOUND) {
298 // no more data to extract
299 break;
300 } else {
301 throw_error("delete_all_values_greater_or_equal_key::mdb_cursor_get", code);
302 }
303 }
304 } catch (std::exception& e) {
305 call_lmdb_func(mdb_cursor_close, cursor);
306 throw;
307 }
308 call_lmdb_func(mdb_cursor_close, cursor);
309}
310
311template <typename TKey, typename TxType>
312void get_all_values_lesser_or_equal_key(const TKey& key, ValuesVector& data, const LMDBDatabase& db, const TxType& tx)
313{
314 Key keyBuffer = serialise_key(key);
315 uint32_t keySize = static_cast<uint32_t>(keyBuffer.size());
316 MDB_cursor* cursor = nullptr;
317 call_lmdb_func("mdb_cursor_open", mdb_cursor_open, tx.underlying(), db.underlying(), &cursor);
318
319 try {
320 MDB_val dbKey;
321 dbKey.mv_size = keySize;
322 dbKey.mv_data = (void*)keyBuffer.data();
323
324 MDB_val dbVal;
325 // Look for the key >= to that provided
326 int code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_SET_RANGE);
327 if (code == 0) {
328 // we found the key, now determine if it is the exact key
329 Key temp = mdb_val_to_vector(dbKey);
330 if (keyBuffer == temp) {
331 // we have the exact key, copy it's data
332 Value temp;
333 copy_to_vector(dbVal, temp);
334 data.push_back(temp);
335 } else {
336 // not the exact key, either the same size but greater value or larger key size
337 // either way we just need to move down
338 }
339 } else if (code == MDB_NOTFOUND) {
340 // key not found. no key of greater size or same size and greater value, just move down
341 } else {
342 throw_error("get_all_values_lesser_or_equal_key::mdb_cursor_get", code);
343 }
344
345 // we now iterate down the keys until we run out
346 while (true) {
347 code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_PREV);
348
349 if (code == 0) {
350 // we have found a previous key, if it is a different size then we have reached the end of the data
351 if (dbKey.mv_size != keySize) {
352 break;
353 }
354 // the same size, grab the value and go round again
355 Value temp;
356 copy_to_vector(dbVal, temp);
357 data.push_back(temp);
358
359 } else if (MDB_NOTFOUND) {
360 // we have reached the end of the db
361 break;
362 } else {
363 throw_error("get_all_values_lesser_or_equal_key::mdb_cursor_get", code);
364 }
365 }
366 } catch (std::exception& e) {
367 call_lmdb_func(mdb_cursor_close, cursor);
368 throw;
369 }
370 call_lmdb_func(mdb_cursor_close, cursor);
371}
372
373template <typename TKey, typename TxType>
374void delete_all_values_lesser_or_equal_key(const TKey& key, const LMDBDatabase& db, const TxType& tx)
375{
376 Key keyBuffer = serialise_key(key);
377 uint32_t keySize = static_cast<uint32_t>(keyBuffer.size());
378 MDB_cursor* cursor = nullptr;
379 call_lmdb_func("mdb_cursor_open", mdb_cursor_open, tx.underlying(), db.underlying(), &cursor);
380
381 try {
382 MDB_val dbKey;
383 dbKey.mv_size = keySize;
384 dbKey.mv_data = (void*)keyBuffer.data();
385
386 MDB_val dbVal;
387 // Look for the key >= to that provided
388 int code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_SET_RANGE);
389 if (code == 0) {
390 // we found the key, now determine if it is the exact key
391 Key temp = mdb_val_to_vector(dbKey);
392 if (keyBuffer == temp) {
393 // we have the exact key, delete it's data
394 code = mdb_cursor_del(cursor, 0);
395
396 if (code != 0) {
397 throw_error("delete_all_values_lesser_or_equal_key::mdb_cursor_del", code);
398 }
399 } else {
400 // not the exact key, either the same size but greater value or larger key size
401 // either way we just need to move down
402 }
403 } else if (code == MDB_NOTFOUND) {
404 // key not found. no key of greater size or same size and greater value, just move down
405 } else {
406 throw_error("get_all_values_lesser_or_equal_key::mdb_cursor_get", code);
407 }
408
409 // we now iterate down the keys until we run out
410 while (true) {
411 code = mdb_cursor_get(cursor, &dbKey, &dbVal, MDB_PREV);
412
413 if (code == 0) {
414 // we have found a previous key, if it is a different size then we have reached the end of the data
415 if (dbKey.mv_size != keySize) {
416 break;
417 }
418 // we have the exact key, delete it's data
419 code = mdb_cursor_del(cursor, 0);
420
421 if (code != 0) {
422 throw_error("delete_all_values_lesser_or_equal_key::mdb_cursor_del", code);
423 }
424
425 } else if (MDB_NOTFOUND) {
426 // we have reached the end of the db
427 break;
428 } else {
429 throw_error("get_all_values_lesser_or_equal_key::mdb_cursor_get", code);
430 }
431 }
432 } catch (std::exception& e) {
433 call_lmdb_func(mdb_cursor_close, cursor);
434 throw;
435 }
436 call_lmdb_func(mdb_cursor_close, cursor);
437}
438
439void put_value(
440 Key& key, Value& data, const LMDBDatabase& db, LMDBWriteTransaction& tx, bool duplicatesPermitted = false);
441
442void put_value(
443 Key& key, const uint64_t& data, const LMDBDatabase& db, LMDBWriteTransaction& tx, bool duplicatesPermitted = false);
444
446
448
449bool get_value(Key& key, Value& data, const LMDBDatabase& db, const LMDBTransaction& tx);
450
451bool get_value(Key& key, uint64_t& data, const LMDBDatabase& db, const LMDBTransaction& tx);
452
453bool set_at_key(const LMDBCursor& cursor, Key& key);
454bool set_at_key_gte(const LMDBCursor& cursor, Key& key);
455bool set_at_start(const LMDBCursor& cursor);
456bool set_at_end(const LMDBCursor& cursor);
457
458bool read_next(const LMDBCursor& cursor, KeyDupValuesVector& keyValues, uint64_t numKeysToRead);
459bool read_prev(const LMDBCursor& cursor, KeyDupValuesVector& keyValues, uint64_t numKeysToRead);
460
461bool read_next_dup(const LMDBCursor& cursor, KeyDupValuesVector& keyValues, uint64_t numKeysToRead);
462bool read_prev_dup(const LMDBCursor& cursor, KeyDupValuesVector& keyValues, uint64_t numKeysToRead);
463
464bool count_until_next(const LMDBCursor& cursor, const Key& key, uint64_t& count);
465bool count_until_prev(const LMDBCursor& cursor, const Key& key, uint64_t& count);
466
467bool count_until_next_dup(const LMDBCursor& cursor, const Key& key, uint64_t& count);
468bool count_until_prev_dup(const LMDBCursor& cursor, const Key& key, uint64_t& count);
469
470} // namespace lmdb_queries
471} // namespace bb::lmdblib
const MDB_dbi & underlying() const
const std::vector< FF > data
void delete_value(Key &key, const LMDBDatabase &db, bb::lmdblib::LMDBWriteTransaction &tx)
Definition queries.cpp:59
void get_all_values_greater_or_equal_key(const TKey &key, ValuesVector &data, const LMDBDatabase &db, const TxType &tx)
Definition queries.hpp:222
bool read_prev_dup(const LMDBCursor &cursor, KeyDupValuesVector &keyValues, uint64_t numKeysToRead)
Definition queries.cpp:290
bool read_next(const LMDBCursor &cursor, KeyDupValuesVector &keyValues, uint64_t numKeysToRead, MDB_cursor_op op)
Definition queries.cpp:155
bool set_at_start(const LMDBCursor &cursor)
Definition queries.cpp:139
bool get_value(Key &key, Value &data, const LMDBDatabase &db, const bb::lmdblib::LMDBTransaction &tx)
Definition queries.cpp:88
bool get_value_or_greater(TKey &key, Value &data, const LMDBDatabase &db, const TxType &tx)
Definition queries.hpp:183
bool count_until_next_dup(const LMDBCursor &cursor, const Key &targetKey, uint64_t &count, MDB_cursor_op op)
Definition queries.cpp:237
bool read_next_dup(const LMDBCursor &cursor, KeyDupValuesVector &keyValues, uint64_t numKeysToRead, MDB_cursor_op op)
Definition queries.cpp:198
void delete_all_values_lesser_or_equal_key(const TKey &key, const LMDBDatabase &db, const TxType &tx)
Definition queries.hpp:374
bool set_at_key_gte(const LMDBCursor &cursor, Key &key)
Definition queries.cpp:128
bool count_until_prev(const LMDBCursor &cursor, const Key &key, uint64_t &count)
Definition queries.cpp:300
void put_value(Key &key, Value &data, const LMDBDatabase &db, bb::lmdblib::LMDBWriteTransaction &tx, bool duplicatesPermitted)
Definition queries.cpp:12
bool set_at_key(const LMDBCursor &cursor, Key &key)
Definition queries.cpp:117
bool read_prev(const LMDBCursor &cursor, KeyDupValuesVector &keyValues, uint64_t numKeysToRead)
Definition queries.cpp:281
void delete_all_values_greater_or_equal_key(const TKey &key, const LMDBDatabase &db, const TxType &tx)
Definition queries.hpp:266
bool set_at_end(const LMDBCursor &cursor)
Definition queries.cpp:147
bool get_value_or_previous(TKey &key, TValue &data, const LMDBDatabase &db, const TxType &tx)
Definition queries.hpp:20
void get_all_values_lesser_or_equal_key(const TKey &key, ValuesVector &data, const LMDBDatabase &db, const TxType &tx)
Definition queries.hpp:312
bool count_until_next(const LMDBCursor &cursor, const Key &targetKey, uint64_t &count, MDB_cursor_op op)
Definition queries.cpp:178
bool count_until_prev_dup(const LMDBCursor &cursor, const Key &key, uint64_t &count)
Definition queries.cpp:310
std::vector< uint8_t > Key
Definition types.hpp:11
void deserialise_key(void *data, uint8_t &key)
std::vector< uint8_t > serialise_key(uint8_t key)
std::vector< uint8_t > Value
Definition types.hpp:12
std::vector< uint8_t > mdb_val_to_vector(const MDB_val &dbVal)
void throw_error(const std::string &errorString, int error)
std::vector< KeyValuesPair > KeyDupValuesVector
Definition types.hpp:18
void copy_to_vector(const MDB_val &dbVal, std::vector< uint8_t > &target)
std::vector< Value > ValuesVector
Definition types.hpp:14
bool call_lmdb_func(int(*f)(TArgs...), TArgs... args)