mirror of
https://github.com/status-im/nim-rocksdb.git
synced 2026-08-27 09:51:06 +00:00
Support deleteRange, compactRange and multiGet on column families (#93)
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
packageName = "rocksdb"
|
||||
version = "10.4.2.0"
|
||||
version = "10.4.2.1"
|
||||
author = "Status Research & Development GmbH"
|
||||
description =
|
||||
"A wrapper for Facebook's RocksDB, an embeddable, persistent key-value store for fast storage"
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ proc openBackupEngine*(
|
||||
BackupEngineRef(cPtr: backupEnginePtr, path: path, backupOpts: backupOpts)
|
||||
ok(engine)
|
||||
|
||||
proc isClosed*(backupEngine: BackupEngineRef): bool {.inline.} =
|
||||
template isClosed*(backupEngine: BackupEngineRef): bool =
|
||||
## Returns `true` if the `BackupEngineRef` has been closed.
|
||||
backupEngine.cPtr.isNil()
|
||||
|
||||
|
||||
+45
-24
@@ -53,70 +53,91 @@ proc getColFamily*(
|
||||
|
||||
ok(ColFamilyReadWrite(db: db, name: name, handle: ?db.getColFamilyHandle(name)))
|
||||
|
||||
proc db*(cf: ColFamilyReadOnly | ColFamilyReadWrite): auto {.inline.} =
|
||||
template db*(cf: ColFamilyReadOnly | ColFamilyReadWrite): auto =
|
||||
## Returns the underlying `RocksDbReadOnlyRef` or `RocksDbReadWriteRef`.
|
||||
cf.db
|
||||
|
||||
proc name*(cf: ColFamilyReadOnly | ColFamilyReadWrite): string {.inline.} =
|
||||
template name*(cf: ColFamilyReadOnly | ColFamilyReadWrite): string =
|
||||
## Returns the name of the column family.
|
||||
cf.name
|
||||
|
||||
proc handle*(
|
||||
cf: ColFamilyReadOnly | ColFamilyReadWrite
|
||||
): ColFamilyHandleRef {.inline.} =
|
||||
template handle*(cf: ColFamilyReadOnly | ColFamilyReadWrite): ColFamilyHandleRef =
|
||||
## Returns the name of the column family.
|
||||
cf.handle
|
||||
|
||||
proc get*(
|
||||
template get*(
|
||||
cf: ColFamilyReadOnly | ColFamilyReadWrite, key: openArray[byte], onData: DataProc
|
||||
): RocksDBResult[bool] {.inline.} =
|
||||
): RocksDBResult[bool] =
|
||||
## Gets the value of the given key from the column family using the `onData`
|
||||
## callback.
|
||||
cf.db.get(key, onData, cf.handle)
|
||||
|
||||
proc get*(
|
||||
template get*(
|
||||
cf: ColFamilyReadOnly | ColFamilyReadWrite, key: openArray[byte]
|
||||
): RocksDBResult[seq[byte]] {.inline.} =
|
||||
): RocksDBResult[seq[byte]] =
|
||||
## Gets the value of the given key from the column family.
|
||||
cf.db.get(key, cf.handle)
|
||||
|
||||
proc put*(
|
||||
cf: ColFamilyReadWrite, key, val: openArray[byte]
|
||||
): RocksDBResult[void] {.inline.} =
|
||||
template multiGet*(
|
||||
cf: ColFamilyReadOnly | ColFamilyReadWrite,
|
||||
keys: openArray[seq[byte]],
|
||||
sortedInput = false,
|
||||
): RocksDBResult[seq[seq[byte]]] =
|
||||
## Get a batch of values for the given set of keys.
|
||||
cf.db.multiGet(keys, sortedInput, cf.handle)
|
||||
|
||||
template put*(cf: ColFamilyReadWrite, key, val: openArray[byte]): RocksDBResult[void] =
|
||||
## Puts a value for the given key into the column family.
|
||||
cf.db.put(key, val, cf.handle)
|
||||
|
||||
proc keyExists*(
|
||||
template keyExists*(
|
||||
cf: ColFamilyReadOnly | ColFamilyReadWrite, key: openArray[byte]
|
||||
): RocksDBResult[bool] {.inline.} =
|
||||
): RocksDBResult[bool] =
|
||||
## Checks if the given key exists in the column family.
|
||||
cf.db.keyExists(key, cf.handle)
|
||||
|
||||
proc delete*(
|
||||
cf: ColFamilyReadWrite, key: openArray[byte]
|
||||
): RocksDBResult[void] {.inline.} =
|
||||
template delete*(cf: ColFamilyReadWrite, key: openArray[byte]): RocksDBResult[void] =
|
||||
## Deletes the given key from the column family.
|
||||
cf.db.delete(key, cf.handle)
|
||||
|
||||
proc openIterator*(
|
||||
template deleteRange*(
|
||||
cf: ColFamilyReadWrite, startKey, endKey: openArray[byte]
|
||||
): RocksDBResult[void] =
|
||||
## Deletes the given key range from the column family including startKey and
|
||||
## excluding endKey.
|
||||
cf.db.deleteRange(startKey, endKey, cf.handle)
|
||||
|
||||
template compactRange*(
|
||||
cf: ColFamilyReadWrite, startKey, endKey: openArray[byte]
|
||||
): RocksDBResult[void] =
|
||||
## Trigger range compaction for the given key range.
|
||||
cf.db.compactRange(startKey, endKey, cf.handle)
|
||||
|
||||
template suggestCompactRange*(
|
||||
cf: ColFamilyReadWrite, startKey, endKey: openArray[byte]
|
||||
): RocksDBResult[void] =
|
||||
## Suggest the range to compact.
|
||||
cf.db.suggestCompactRange(startKey, endKey, cf.handle)
|
||||
|
||||
template openIterator*(
|
||||
cf: ColFamilyReadOnly | ColFamilyReadWrite,
|
||||
readOpts = defaultReadOptions(autoClose = true),
|
||||
): RocksDBResult[RocksIteratorRef] {.inline.} =
|
||||
): RocksDBResult[RocksIteratorRef] =
|
||||
## Opens an `RocksIteratorRef` for the given column family.
|
||||
cf.db.openIterator(readOpts, cf.handle)
|
||||
|
||||
proc openWriteBatch*(cf: ColFamilyReadWrite): WriteBatchRef {.inline.} =
|
||||
template openWriteBatch*(cf: ColFamilyReadWrite): WriteBatchRef =
|
||||
## Opens a `WriteBatchRef` for the given column family.
|
||||
cf.db.openWriteBatch(cf.handle)
|
||||
|
||||
proc openWriteBatchWithIndex*(
|
||||
template openWriteBatchWithIndex*(
|
||||
cf: ColFamilyReadWrite, reservedBytes = 0, overwriteKey = false
|
||||
): WriteBatchWIRef {.inline.} =
|
||||
): WriteBatchWIRef =
|
||||
## Opens a `WriteBatchRef` for the given column family.
|
||||
cf.db.openWriteBatchWithIndex(reservedBytes, overwriteKey, cf.handle)
|
||||
|
||||
proc write*(
|
||||
template write*(
|
||||
cf: ColFamilyReadWrite, updates: WriteBatchRef | WriteBatchWIRef
|
||||
): RocksDBResult[void] {.inline.} =
|
||||
): RocksDBResult[void] =
|
||||
## Writes the updates in the `WriteBatchRef` to the column family.
|
||||
cf.db.write(updates)
|
||||
|
||||
@@ -24,25 +24,25 @@ proc initColFamilyDescriptor*(
|
||||
): ColFamilyDescriptor =
|
||||
ColFamilyDescriptor(name: name, options: options)
|
||||
|
||||
proc name*(descriptor: ColFamilyDescriptor): string {.inline.} =
|
||||
template name*(descriptor: ColFamilyDescriptor): string =
|
||||
descriptor.name
|
||||
|
||||
proc options*(descriptor: ColFamilyDescriptor): ColFamilyOptionsRef {.inline.} =
|
||||
template options*(descriptor: ColFamilyDescriptor): ColFamilyOptionsRef =
|
||||
descriptor.options
|
||||
|
||||
proc autoClose*(descriptor: ColFamilyDescriptor): bool {.inline.} =
|
||||
template autoClose*(descriptor: ColFamilyDescriptor): bool =
|
||||
descriptor.options.autoClose
|
||||
|
||||
proc isDefault*(descriptor: ColFamilyDescriptor): bool {.inline.} =
|
||||
template isDefault*(descriptor: ColFamilyDescriptor): bool =
|
||||
descriptor.name == DEFAULT_COLUMN_FAMILY_NAME
|
||||
|
||||
proc defaultColFamilyDescriptor*(autoClose = false): ColFamilyDescriptor {.inline.} =
|
||||
proc defaultColFamilyDescriptor*(autoClose = false): ColFamilyDescriptor =
|
||||
initColFamilyDescriptor(
|
||||
DEFAULT_COLUMN_FAMILY_NAME, defaultColFamilyOptions(autoClose = autoClose)
|
||||
)
|
||||
|
||||
proc isClosed*(descriptor: ColFamilyDescriptor): bool {.inline.} =
|
||||
template isClosed*(descriptor: ColFamilyDescriptor): bool =
|
||||
descriptor.options.isClosed()
|
||||
|
||||
proc close*(descriptor: ColFamilyDescriptor) {.inline.} =
|
||||
template close*(descriptor: ColFamilyDescriptor) =
|
||||
descriptor.options.close()
|
||||
|
||||
@@ -20,7 +20,7 @@ type
|
||||
proc newColFamilyHandle*(cPtr: ColFamilyHandlePtr): ColFamilyHandleRef =
|
||||
ColFamilyHandleRef(cPtr: cPtr)
|
||||
|
||||
proc isClosed*(handle: ColFamilyHandleRef): bool {.inline.} =
|
||||
template isClosed*(handle: ColFamilyHandleRef): bool =
|
||||
handle.cPtr.isNil()
|
||||
|
||||
proc cPtr*(handle: ColFamilyHandleRef): ColFamilyHandlePtr =
|
||||
|
||||
@@ -43,7 +43,7 @@ type
|
||||
proc createFixedPrefix*(value: int): SlicetransformRef =
|
||||
SlicetransformRef(cPtr: rocksdb_slicetransform_create_fixed_prefix(value.csize_t))
|
||||
|
||||
proc isClosed*(s: SlicetransformRef): bool {.inline.} =
|
||||
template isClosed*(s: SlicetransformRef): bool =
|
||||
s.cPtr.isNil()
|
||||
|
||||
proc cPtr*(s: SlicetransformRef): SlicetransformPtr =
|
||||
@@ -58,7 +58,7 @@ proc close*(s: SlicetransformRef) =
|
||||
proc createColFamilyOptions*(autoClose = false): ColFamilyOptionsRef =
|
||||
ColFamilyOptionsRef(cPtr: rocksdb_options_create(), autoClose: autoClose)
|
||||
|
||||
proc isClosed*(cfOpts: ColFamilyOptionsRef): bool {.inline.} =
|
||||
template isClosed*(cfOpts: ColFamilyOptionsRef): bool =
|
||||
cfOpts.cPtr.isNil()
|
||||
|
||||
proc cPtr*(cfOpts: ColFamilyOptionsRef): ColFamilyOptionsPtr =
|
||||
|
||||
@@ -27,10 +27,10 @@ proc newColFamilyTable*(
|
||||
|
||||
ColFamilyTableRef(columnFamilies: cfTable)
|
||||
|
||||
proc isClosed*(table: ColFamilyTableRef): bool {.inline.} =
|
||||
template isClosed*(table: ColFamilyTableRef): bool =
|
||||
table.columnFamilies.isNil()
|
||||
|
||||
proc get*(table: ColFamilyTableRef, name: string): ColFamilyHandleRef {.inline.} =
|
||||
template get*(table: ColFamilyTableRef, name: string): ColFamilyHandleRef =
|
||||
table.columnFamilies.getOrDefault(name)
|
||||
|
||||
proc close*(table: ColFamilyTableRef) =
|
||||
|
||||
@@ -94,7 +94,7 @@ proc getColFamilyHandle*(
|
||||
else:
|
||||
ok(cfHandle)
|
||||
|
||||
proc isClosed*(db: OptimisticTxDbRef): bool {.inline.} =
|
||||
template isClosed*(db: OptimisticTxDbRef): bool =
|
||||
## Returns `true` if the `OptimisticTxDbRef` has been closed.
|
||||
db.cPtr.isNil()
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ proc createBackupEngineOptions*(
|
||||
cPtr: rocksdb_backup_engine_options_create(backupDir.cstring), autoClose: autoClose
|
||||
)
|
||||
|
||||
proc isClosed*(backupOpts: BackupEngineOptionsRef): bool {.inline.} =
|
||||
template isClosed*(backupOpts: BackupEngineOptionsRef): bool =
|
||||
backupOpts.cPtr.isNil()
|
||||
|
||||
proc cPtr*(backupOpts: BackupEngineOptionsRef): BackupEngineOptionsPtr =
|
||||
@@ -53,7 +53,7 @@ opt callbackTriggerIntervalSize, int, uint64
|
||||
|
||||
proc defaultBackupEngineOptions*(
|
||||
backupDir: string, autoClose = false
|
||||
): BackupEngineOptionsRef {.inline.} =
|
||||
): BackupEngineOptionsRef =
|
||||
let backupOpts = createBackupEngineOptions(backupDir, autoClose)
|
||||
|
||||
# TODO: set defaults here
|
||||
|
||||
@@ -24,7 +24,7 @@ type
|
||||
proc createDbOptions*(autoClose = false): DbOptionsRef =
|
||||
DbOptionsRef(cPtr: rocksdb_options_create(), autoClose: autoClose)
|
||||
|
||||
proc isClosed*(dbOpts: DbOptionsRef): bool {.inline.} =
|
||||
template isClosed*(dbOpts: DbOptionsRef): bool =
|
||||
dbOpts.cPtr.isNil()
|
||||
|
||||
proc cPtr*(dbOpts: DbOptionsRef): DbOptionsPtr =
|
||||
|
||||
@@ -23,7 +23,7 @@ type
|
||||
proc createReadOptions*(autoClose = false): ReadOptionsRef =
|
||||
ReadOptionsRef(cPtr: rocksdb_readoptions_create(), autoClose: autoClose)
|
||||
|
||||
proc isClosed*(readOpts: ReadOptionsRef): bool {.inline.} =
|
||||
template isClosed*(readOpts: ReadOptionsRef): bool =
|
||||
readOpts.cPtr.isNil()
|
||||
|
||||
proc cPtr*(readOpts: ReadOptionsRef): ReadOptionsPtr =
|
||||
@@ -52,12 +52,13 @@ opt maxSkippableInternalKeys, int, csize_t
|
||||
opt ignoreRangeDeletions, bool, uint8
|
||||
opt deadline, int, uint64
|
||||
opt ioTimeout, int, uint64
|
||||
opt asyncIo, bool, uint8
|
||||
|
||||
proc setSnapshot*(readOpts: ReadOptionsRef, snapshot: SnapshotRef) =
|
||||
doAssert not readOpts.isClosed()
|
||||
rocksdb_readoptions_set_snapshot(readOpts.cPtr, snapshot.cPtr)
|
||||
|
||||
proc defaultReadOptions*(autoClose = false): ReadOptionsRef {.inline.} =
|
||||
proc defaultReadOptions*(autoClose = false): ReadOptionsRef =
|
||||
let readOpts = createReadOptions(autoClose)
|
||||
|
||||
# TODO: set prefered defaults
|
||||
|
||||
@@ -21,7 +21,7 @@ type
|
||||
proc createWriteOptions*(autoClose = false): WriteOptionsRef =
|
||||
WriteOptionsRef(cPtr: rocksdb_writeoptions_create(), autoClose: autoClose)
|
||||
|
||||
proc isClosed*(writeOpts: WriteOptionsRef): bool {.inline.} =
|
||||
template isClosed*(writeOpts: WriteOptionsRef): bool =
|
||||
writeOpts.cPtr.isNil()
|
||||
|
||||
proc cPtr*(writeOpts: WriteOptionsRef): WriteOptionsPtr =
|
||||
@@ -51,7 +51,7 @@ proc disableWAL*(writeOpts: WriteOptionsRef): bool =
|
||||
doAssert not writeOpts.isClosed()
|
||||
rocksdb_writeoptions_get_disable_WAL(writeOpts.cPtr).bool
|
||||
|
||||
proc defaultWriteOptions*(autoClose = false): WriteOptionsRef {.inline.} =
|
||||
proc defaultWriteOptions*(autoClose = false): WriteOptionsRef =
|
||||
let writeOpts = createWriteOptions(autoClose)
|
||||
|
||||
# TODO: set prefered defaults
|
||||
|
||||
+133
-2
@@ -221,11 +221,11 @@ proc getColFamilyHandle*(
|
||||
else:
|
||||
ok(cfHandle)
|
||||
|
||||
proc isClosed*(db: RocksDbRef): bool {.inline.} =
|
||||
template isClosed*(db: RocksDbRef): bool =
|
||||
## Returns `true` if the database has been closed and `false` otherwise.
|
||||
db.cPtr.isNil()
|
||||
|
||||
proc cPtr*(db: RocksDbRef): RocksDbPtr {.inline.} =
|
||||
proc cPtr*(db: RocksDbRef): RocksDbPtr =
|
||||
## Get the underlying database pointer.
|
||||
doAssert not db.isClosed()
|
||||
db.cPtr
|
||||
@@ -282,6 +282,74 @@ proc get*(
|
||||
|
||||
dataRes.err(res.error())
|
||||
|
||||
proc multiGet*(
|
||||
db: RocksDbRef,
|
||||
keys: openArray[seq[byte]],
|
||||
sortedInput = false,
|
||||
cfHandle = db.defaultCfHandle,
|
||||
): RocksDBResult[seq[seq[byte]]] =
|
||||
## Get a batch of values for the given set of keys.
|
||||
##
|
||||
## The multiGet API improves performance by batching operations
|
||||
## in the read path for greater efficiency. Currently, only the block based
|
||||
## table format with full filters are supported. Other table formats such
|
||||
## as plain table, block based table with block based filters and
|
||||
## partitioned indexes will still work, but will not get any performance
|
||||
## benefits.
|
||||
##
|
||||
## sortedInput - If true, it means the input keys are already sorted by key
|
||||
## order, so the MultiGet() API doesn't have to sort them again. If false,
|
||||
## the keys will be copied and sorted internally by the API - the input
|
||||
## array will not be modified.
|
||||
assert keys.len() > 0
|
||||
|
||||
var
|
||||
keysList = keys.mapIt(cast[cstring](it[0].addr))
|
||||
keysListSizes = keys.mapIt(csize_t(it.len))
|
||||
errors = newSeq[cstring](keys.len())
|
||||
|
||||
var values =
|
||||
when NimMajor >= 2 and NimMinor >= 2:
|
||||
newSeqUninit[ptr rocksdb_pinnableslice_t](keys.len)
|
||||
else:
|
||||
newSeq[ptr rocksdb_pinnableslice_t](keys.len)
|
||||
|
||||
rocksdb_batched_multi_get_cf(
|
||||
db.cPtr,
|
||||
db.readOpts.cPtr,
|
||||
cfHandle.cPtr,
|
||||
csize_t(keys.len),
|
||||
cast[cstringArray](keysList[0].addr),
|
||||
keysListSizes[0].addr,
|
||||
values[0].addr,
|
||||
cast[cstringArray](errors[0].addr),
|
||||
sortedInput,
|
||||
)
|
||||
|
||||
for e in errors:
|
||||
if not e.isNil:
|
||||
let res = err($(e))
|
||||
rocksdb_free(e)
|
||||
return res
|
||||
|
||||
var data = newSeq[seq[byte]](keys.len())
|
||||
for i, v in values:
|
||||
var vLen: csize_t
|
||||
let src = rocksdb_pinnableslice_value(v, vLen.addr)
|
||||
|
||||
if vLen > 0:
|
||||
var dest =
|
||||
when NimMajor >= 2 and NimMinor >= 2:
|
||||
newSeqUninit[byte](vLen.int)
|
||||
else:
|
||||
newSeq[byte](vLen.int)
|
||||
copyMem(dest[0].addr, src, vLen)
|
||||
data[i] = dest
|
||||
|
||||
rocksdb_pinnableslice_destroy(v)
|
||||
|
||||
ok(data)
|
||||
|
||||
proc put*(
|
||||
db: RocksDbReadWriteRef, key, val: openArray[byte], cfHandle = db.defaultCfHandle
|
||||
): RocksDBResult[void] =
|
||||
@@ -360,6 +428,69 @@ proc delete*(
|
||||
|
||||
ok()
|
||||
|
||||
proc deleteRange*(
|
||||
db: RocksDbReadWriteRef,
|
||||
startKey, endKey: openArray[byte],
|
||||
cfHandle = db.defaultCfHandle,
|
||||
): RocksDBResult[void] =
|
||||
## Removes the database entries in the range [startKey, endKey), i.e. including
|
||||
## startKey and excluding endKey. It is not an error if no keys exist in the
|
||||
## range ["beginKey", "endKey").
|
||||
|
||||
var errors: cstring
|
||||
rocksdb_delete_range_cf(
|
||||
db.cPtr,
|
||||
db.writeOpts.cPtr,
|
||||
cfHandle.cPtr,
|
||||
cast[cstring](startKey.unsafeAddrOrNil()),
|
||||
csize_t(startKey.len),
|
||||
cast[cstring](endKey.unsafeAddrOrNil()),
|
||||
csize_t(endKey.len),
|
||||
cast[cstringArray](errors.addr),
|
||||
)
|
||||
bailOnErrors(errors)
|
||||
|
||||
ok()
|
||||
|
||||
proc compactRange*(
|
||||
db: RocksDbReadWriteRef,
|
||||
startKey, endKey: openArray[byte],
|
||||
cfHandle = db.defaultCfHandle,
|
||||
): RocksDBResult[void] =
|
||||
## Trigger range compaction for the given key range.
|
||||
|
||||
rocksdb_compact_range_cf(
|
||||
db.cPtr,
|
||||
cfHandle.cPtr,
|
||||
cast[cstring](startKey.unsafeAddrOrNil()),
|
||||
csize_t(startKey.len),
|
||||
cast[cstring](endKey.unsafeAddrOrNil()),
|
||||
csize_t(endKey.len),
|
||||
)
|
||||
|
||||
ok()
|
||||
|
||||
proc suggestCompactRange*(
|
||||
db: RocksDbReadWriteRef,
|
||||
startKey, endKey: openArray[byte],
|
||||
cfHandle = db.defaultCfHandle,
|
||||
): RocksDBResult[void] =
|
||||
## Suggest the range to compact.
|
||||
|
||||
var errors: cstring
|
||||
rocksdb_suggest_compact_range_cf(
|
||||
db.cPtr,
|
||||
cfHandle.cPtr,
|
||||
cast[cstring](startKey.unsafeAddrOrNil()),
|
||||
csize_t(startKey.len),
|
||||
cast[cstring](endKey.unsafeAddrOrNil()),
|
||||
csize_t(endKey.len),
|
||||
cast[cstringArray](errors.addr),
|
||||
)
|
||||
bailOnErrors(errors)
|
||||
|
||||
ok()
|
||||
|
||||
proc openIterator*(
|
||||
db: RocksDbRef,
|
||||
readOpts = defaultReadOptions(autoClose = true),
|
||||
|
||||
@@ -29,7 +29,7 @@ proc newRocksIterator*(
|
||||
doAssert not cPtr.isNil()
|
||||
RocksIteratorRef(cPtr: cPtr, readOpts: readOpts)
|
||||
|
||||
proc isClosed*(iter: RocksIteratorRef): bool {.inline.} =
|
||||
template isClosed*(iter: RocksIteratorRef): bool =
|
||||
## Returns `true` if the iterator is closed and `false` otherwise.
|
||||
iter.cPtr.isNil()
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ proc newSnapshot*(cPtr: SnapshotPtr, kind: SnapshotType): SnapshotRef =
|
||||
doAssert not cPtr.isNil()
|
||||
SnapshotRef(cPtr: cPtr, kind: kind)
|
||||
|
||||
proc isClosed*(snapshot: SnapshotRef): bool {.inline.} =
|
||||
template isClosed*(snapshot: SnapshotRef): bool =
|
||||
## Returns `true` if the `SnapshotRef` has been closed and `false` otherwise.
|
||||
snapshot.cPtr.isNil()
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ proc openSstFileWriter*(
|
||||
|
||||
ok(writer)
|
||||
|
||||
proc isClosed*(writer: SstFileWriterRef): bool {.inline.} =
|
||||
template isClosed*(writer: SstFileWriterRef): bool =
|
||||
## Returns `true` if the `SstFileWriterRef` is closed and `false` otherwise.
|
||||
writer.cPtr.isNil()
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ proc getColFamilyHandle*(
|
||||
else:
|
||||
ok(cfHandle)
|
||||
|
||||
proc isClosed*(db: TransactionDbRef): bool {.inline.} =
|
||||
template isClosed*(db: TransactionDbRef): bool =
|
||||
## Returns `true` if the `TransactionDbRef` has been closed.
|
||||
db.cPtr.isNil()
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ proc createOptimisticTxOptions*(autoClose = false): OptimisticTxOptionsRef =
|
||||
cPtr: rocksdb_optimistictransaction_options_create(), autoClose: autoClose
|
||||
)
|
||||
|
||||
proc isClosed*(txOpts: OptimisticTxOptionsRef): bool {.inline.} =
|
||||
template isClosed*(txOpts: OptimisticTxOptionsRef): bool =
|
||||
txOpts.cPtr.isNil()
|
||||
|
||||
proc cPtr*(txOpts: OptimisticTxOptionsRef): OptimisticTxOptionsPtr =
|
||||
@@ -37,7 +37,7 @@ template setOpt(nname, ntyp, ctyp: untyped) =
|
||||
|
||||
setOpt setSnapshot, bool, uint8
|
||||
|
||||
proc defaultOptimisticTxOptions*(autoClose = false): OptimisticTxOptionsRef {.inline.} =
|
||||
proc defaultOptimisticTxOptions*(autoClose = false): OptimisticTxOptionsRef =
|
||||
let txOpts = createOptimisticTxOptions(autoClose)
|
||||
|
||||
# TODO: set prefered defaults
|
||||
|
||||
@@ -56,7 +56,7 @@ proc newTransaction*(
|
||||
defaultCfHandle: defaultCfHandle,
|
||||
)
|
||||
|
||||
proc isClosed*(tx: TransactionRef): bool {.inline.} =
|
||||
template isClosed*(tx: TransactionRef): bool =
|
||||
## Returns `true` if the `TransactionRef` has been closed.
|
||||
tx.cPtr.isNil()
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ proc createTransactionDbOptions*(autoClose = false): TransactionDbOptionsRef =
|
||||
cPtr: rocksdb_transactiondb_options_create(), autoClose: autoClose
|
||||
)
|
||||
|
||||
proc isClosed*(txDbOpts: TransactionDbOptionsRef): bool {.inline.} =
|
||||
template isClosed*(txDbOpts: TransactionDbOptionsRef): bool =
|
||||
txDbOpts.cPtr.isNil()
|
||||
|
||||
proc cPtr*(txDbOpts: TransactionDbOptionsRef): TransactionDbOptionsPtr =
|
||||
@@ -40,9 +40,7 @@ setOpt numStripes, int, csize_t
|
||||
setOpt transactionLockTimeout, int, int64
|
||||
setOpt defaultLockTimeout, int, int64
|
||||
|
||||
proc defaultTransactionDbOptions*(
|
||||
autoClose = false
|
||||
): TransactionDbOptionsRef {.inline.} =
|
||||
proc defaultTransactionDbOptions*(autoClose = false): TransactionDbOptionsRef =
|
||||
let txDbOpts = createTransactionDbOptions(autoClose)
|
||||
|
||||
# TODO: set prefered defaults
|
||||
|
||||
@@ -23,7 +23,7 @@ proc createTransactionOptions*(autoClose = false): TransactionOptionsRef =
|
||||
cPtr: rocksdb_transaction_options_create(), autoClose: autoClose
|
||||
)
|
||||
|
||||
proc isClosed*(txOpts: TransactionOptionsRef): bool {.inline.} =
|
||||
template isClosed*(txOpts: TransactionOptionsRef): bool =
|
||||
txOpts.cPtr.isNil()
|
||||
|
||||
proc cPtr*(txOpts: TransactionOptionsRef): TransactionOptionsPtr =
|
||||
@@ -42,7 +42,7 @@ setOpt deadlockDetectDepth, int, int64
|
||||
setOpt maxWriteBatchSize, int, csize_t
|
||||
setOpt skipPrepare, bool, uint8
|
||||
|
||||
proc defaultTransactionOptions*(autoClose = false): TransactionOptionsRef {.inline.} =
|
||||
proc defaultTransactionOptions*(autoClose = false): TransactionOptionsRef =
|
||||
let txOpts = createTransactionOptions(autoClose)
|
||||
|
||||
# TODO: set prefered defaults
|
||||
|
||||
+19
-1
@@ -27,7 +27,7 @@ type
|
||||
proc createWriteBatch*(defaultCfHandle: ColFamilyHandleRef): WriteBatchRef =
|
||||
WriteBatchRef(cPtr: rocksdb_writebatch_create(), defaultCfHandle: defaultCfHandle)
|
||||
|
||||
proc isClosed*(batch: WriteBatchRef): bool {.inline.} =
|
||||
template isClosed*(batch: WriteBatchRef): bool =
|
||||
## Returns `true` if the `WriteBatchRef` has been closed and `false` otherwise.
|
||||
batch.cPtr.isNil()
|
||||
|
||||
@@ -73,6 +73,24 @@ proc delete*(
|
||||
|
||||
ok()
|
||||
|
||||
proc deleteRange*(
|
||||
batch: WriteBatchRef,
|
||||
startKey, endKey: openArray[byte],
|
||||
cfHandle = batch.defaultCfHandle,
|
||||
): RocksDBResult[void] =
|
||||
## Add a delete range operation to the write batch.
|
||||
|
||||
rocksdb_writebatch_delete_range_cf(
|
||||
batch.cPtr,
|
||||
cfHandle.cPtr,
|
||||
cast[cstring](startKey.unsafeAddrOrNil()),
|
||||
csize_t(startKey.len),
|
||||
cast[cstring](endKey.unsafeAddrOrNil()),
|
||||
csize_t(endKey.len),
|
||||
)
|
||||
|
||||
ok()
|
||||
|
||||
proc close*(batch: WriteBatchRef) =
|
||||
## Close the `WriteBatchRef`.
|
||||
if not batch.isClosed():
|
||||
|
||||
@@ -41,7 +41,7 @@ proc createWriteBatch*(
|
||||
defaultCfHandle: defaultCfHandle,
|
||||
)
|
||||
|
||||
proc isClosed*(batch: WriteBatchWIRef): bool {.inline.} =
|
||||
template isClosed*(batch: WriteBatchWIRef): bool =
|
||||
## Returns `true` if the `WriteBatchWIRef` has been closed and `false` otherwise.
|
||||
batch.cPtr.isNil()
|
||||
|
||||
|
||||
@@ -101,3 +101,49 @@ suite "ColFamily Tests":
|
||||
iter.value() == val
|
||||
iter.seekToKey(otherKey)
|
||||
check iter.isValid() == false
|
||||
|
||||
test "Test deleteRange":
|
||||
let cf = db.getColFamily(CF_OTHER).get()
|
||||
|
||||
let
|
||||
keyValue1 = @[1.byte]
|
||||
keyValue2 = @[2.byte]
|
||||
keyValue3 = @[3.byte]
|
||||
|
||||
check:
|
||||
cf.put(keyValue1, keyValue1).isOk()
|
||||
cf.put(keyValue2, keyValue2).isOk()
|
||||
cf.put(keyValue3, keyValue3).isOk()
|
||||
cf.keyExists(keyValue1).get() == true
|
||||
cf.keyExists(keyValue2).get() == true
|
||||
cf.keyExists(keyValue3).get() == true
|
||||
|
||||
cf.suggestCompactRange(keyValue1, keyValue3).isOk()
|
||||
cf.deleteRange(keyValue1, keyValue3).isOk()
|
||||
cf.compactRange(keyValue1, keyValue3).isOk()
|
||||
|
||||
cf.keyExists(keyValue1).get() == false
|
||||
cf.keyExists(keyValue2).get() == false
|
||||
cf.keyExists(keyValue3).get() == true
|
||||
|
||||
test "Test multiget":
|
||||
let cf = db.getColFamily(CF_OTHER).get()
|
||||
|
||||
let
|
||||
keyValue1 = @[100.byte]
|
||||
keyValue2 = @[300.byte]
|
||||
keyValue3 = @[200.byte]
|
||||
|
||||
check:
|
||||
cf.put(keyValue1, keyValue1).isOk()
|
||||
cf.put(keyValue2, keyValue2).isOk()
|
||||
cf.keyExists(keyValue1).get() == true
|
||||
cf.keyExists(keyValue2).get() == true
|
||||
cf.keyExists(keyValue3).get() == false
|
||||
|
||||
let dataRes = cf.multiGet(@[keyValue1, keyValue2, keyValue3]).expect("ok")
|
||||
check:
|
||||
dataRes.len() == 3
|
||||
dataRes[0] == keyValue1
|
||||
dataRes[1] == keyValue2
|
||||
dataRes[2] == default(seq[byte])
|
||||
|
||||
@@ -514,3 +514,117 @@ suite "RocksDbRef Tests":
|
||||
db.put(otherKey, val, defaultCfHandle).isOk()
|
||||
db.put(key, val, otherCfHandle).isOk()
|
||||
db.flush(cfHandles).isOk()
|
||||
|
||||
test "Test deleteRange":
|
||||
let
|
||||
keyValue1 = @[1.byte]
|
||||
keyValue2 = @[2.byte]
|
||||
keyValue3 = @[3.byte]
|
||||
|
||||
check:
|
||||
db.put(keyValue1, keyValue1).isOk()
|
||||
db.put(keyValue2, keyValue2).isOk()
|
||||
db.put(keyValue3, keyValue3).isOk()
|
||||
db.keyExists(keyValue1).get() == true
|
||||
db.keyExists(keyValue2).get() == true
|
||||
db.keyExists(keyValue3).get() == true
|
||||
|
||||
db.deleteRange(keyValue1, keyValue3).isOk()
|
||||
db.compactRange(keyValue1, keyValue3).isOk()
|
||||
|
||||
db.keyExists(keyValue1).get() == false
|
||||
db.keyExists(keyValue2).get() == false
|
||||
db.keyExists(keyValue3).get() == true
|
||||
|
||||
check:
|
||||
db.put(keyValue1, keyValue1, otherCfHandle).isOk()
|
||||
db.put(keyValue2, keyValue2, otherCfHandle).isOk()
|
||||
db.keyExists(keyValue1, otherCfHandle).get() == true
|
||||
db.keyExists(keyValue2, otherCfHandle).get() == true
|
||||
db.keyExists(keyValue3, otherCfHandle).get() == false
|
||||
|
||||
db.deleteRange(keyValue1, keyValue2, otherCfHandle).isOk()
|
||||
db.suggestCompactRange(keyValue1, keyValue3, otherCfHandle).isOk()
|
||||
|
||||
db.keyExists(keyValue1, otherCfHandle).get() == false
|
||||
db.keyExists(keyValue2, otherCfHandle).get() == true
|
||||
db.keyExists(keyValue3, otherCfHandle).get() == false
|
||||
|
||||
test "Test multiget":
|
||||
let
|
||||
keyValue1 = @[1.byte]
|
||||
keyValue2 = @[2.byte]
|
||||
keyValue3 = @[3.byte]
|
||||
keyValue4 = @[4.byte]
|
||||
keyValue5 = @[5.byte]
|
||||
keyValue6 = @[6.byte]
|
||||
keyValue7 = @[7.byte]
|
||||
keyValue8 = @[8.byte]
|
||||
keyValue9 = @[9.byte]
|
||||
|
||||
check:
|
||||
db.put(keyValue1, keyValue1).isOk()
|
||||
db.put(keyValue2, keyValue2).isOk()
|
||||
db.put(keyValue5, keyValue5).isOk()
|
||||
db.put(keyValue7, keyValue7).isOk()
|
||||
db.put(keyValue9, keyValue9).isOk()
|
||||
db.keyExists(keyValue1).get() == true
|
||||
db.keyExists(keyValue2).get() == true
|
||||
db.keyExists(keyValue3).get() == false
|
||||
|
||||
block:
|
||||
let dataRes = db.multiGet(@[keyValue1]).expect("ok")
|
||||
check:
|
||||
dataRes.len() == 1
|
||||
dataRes[0] == keyValue1
|
||||
|
||||
block:
|
||||
let dataRes = db.multiGet(@[keyValue1, keyValue2]).expect("ok")
|
||||
check:
|
||||
dataRes.len() == 2
|
||||
dataRes[0] == keyValue1
|
||||
dataRes[1] == keyValue2
|
||||
|
||||
block:
|
||||
let dataRes = db.multiGet(@[keyValue2, keyValue3]).expect("ok")
|
||||
check:
|
||||
dataRes.len() == 2
|
||||
dataRes[0] == keyValue2
|
||||
dataRes[1] == default(seq[byte])
|
||||
|
||||
block:
|
||||
let dataRes = db.multiGet(@[keyValue1, keyValue2, keyValue3]).expect("ok")
|
||||
check:
|
||||
dataRes.len() == 3
|
||||
dataRes[0] == keyValue1
|
||||
dataRes[1] == keyValue2
|
||||
dataRes[2] == default(seq[byte])
|
||||
|
||||
block:
|
||||
let dataRes =
|
||||
db.multiGet(@[keyValue1, keyValue2, keyValue3], sortedInput = true).expect("ok")
|
||||
check:
|
||||
dataRes.len() == 3
|
||||
dataRes[0] == keyValue1
|
||||
dataRes[1] == keyValue2
|
||||
dataRes[2] == default(seq[byte])
|
||||
|
||||
block:
|
||||
let
|
||||
keys =
|
||||
@[
|
||||
keyValue1, keyValue2, keyValue3, keyValue4, keyValue5, keyValue6, keyValue7,
|
||||
keyValue8, keyValue9,
|
||||
]
|
||||
dataRes = db.multiGet(keys).expect("ok")
|
||||
check:
|
||||
dataRes.len() == 9
|
||||
dataRes[0] == keyValue1
|
||||
dataRes[1] == keyValue2
|
||||
dataRes[2] == default(seq[byte])
|
||||
dataRes[3] == default(seq[byte])
|
||||
dataRes[4] == keyValue5
|
||||
dataRes[5] == default(seq[byte])
|
||||
dataRes[6] == keyValue7
|
||||
dataRes[7] == default(seq[byte])
|
||||
dataRes[8] == keyValue9
|
||||
|
||||
@@ -195,3 +195,27 @@ suite "WriteBatchRef Tests":
|
||||
check batch.isClosed()
|
||||
batch.close()
|
||||
check batch.isClosed()
|
||||
|
||||
test "Test deleteRange":
|
||||
let batch = db.openWriteBatch()
|
||||
defer:
|
||||
batch.close()
|
||||
|
||||
let
|
||||
keyValue1 = @[1.byte]
|
||||
keyValue2 = @[2.byte]
|
||||
keyValue3 = @[3.byte]
|
||||
|
||||
check:
|
||||
batch.put(keyValue1, keyValue1).isOk()
|
||||
batch.put(keyValue2, keyValue2).isOk()
|
||||
batch.put(keyValue3, keyValue3).isOk()
|
||||
batch.deleteRange(keyValue1, keyValue3).isOk()
|
||||
batch.count() == 4
|
||||
|
||||
let res1 = db.write(batch)
|
||||
check:
|
||||
res1.isOk()
|
||||
db.keyExists(keyValue1).get() == false
|
||||
db.keyExists(keyValue2).get() == false
|
||||
db.keyExists(keyValue3).get() == true
|
||||
|
||||
Reference in New Issue
Block a user