porting query tests

This commit is contained in:
Jaremy Creechley 2023-09-21 19:08:19 -07:00
parent 3d7c3d2d2f
commit d6d5978d5c
No known key found for this signature in database
GPG Key ID: 4E66FB67B21D3300
2 changed files with 171 additions and 167 deletions

View File

@ -173,52 +173,56 @@ proc query*(
let handle = DbQueryHandle()
let iter = iterator(): ?!DbQueryResponse {.closure.} =
if handle.cancel:
doClose()
return
while true:
let v = sqlite3_step(s)
if handle.cancel:
doClose()
return
case v
of SQLITE_ROW:
echo "SQLITE ROW"
let
key = KeyId.new(sqlite3_column_text_not_null(s, QueryStmtIdCol))
let v = sqlite3_step(s)
blob: ?pointer =
if query.value: sqlite3_column_blob(s, QueryStmtDataCol).some
else: pointer.none
case v
of SQLITE_ROW:
echo "SQLITE ROW"
let
key = KeyId.new(sqlite3_column_text_not_null(s, QueryStmtIdCol))
# detect out-of-memory error
# see the conversion table and final paragraph of:
# https://www.sqlite.org/c3ref/column_blob.html
# see also https://www.sqlite.org/rescode.html
blob: ?pointer =
if query.value: sqlite3_column_blob(s, QueryStmtDataCol).some
else: pointer.none
# the "data" column can be NULL so in order to detect an out-of-memory
# error it is necessary to check that the result is a null pointer and
# that the result code is an error code
if blob.isSome and blob.get().isNil:
let v = sqlite3_errcode(sqlite3_db_handle(s))
# detect out-of-memory error
# see the conversion table and final paragraph of:
# https://www.sqlite.org/c3ref/column_blob.html
# see also https://www.sqlite.org/rescode.html
if not (v in [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]):
return failure newException(DatastoreError, $sqlite3_errstr(v))
# the "data" column can be NULL so in order to detect an out-of-memory
# error it is necessary to check that the result is a null pointer and
# that the result code is an error code
if blob.isSome and blob.get().isNil:
let v = sqlite3_errcode(sqlite3_db_handle(s))
let
dataLen = sqlite3_column_bytes(s, QueryStmtDataCol)
data =
if blob.isSome: DataBuffer.new(blob.get(), 0, dataLen - 1)
else: DataBuffer.new(0)
if not (v in [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]):
return failure newException(DatastoreError, $sqlite3_errstr(v))
echo "SQLITE ROW: yield"
yield success (key.some, data)
of SQLITE_DONE:
echo "SQLITE DONE: return"
doClose()
return
else:
echo "SQLITE ERROR: return"
doClose()
return failure newException(DatastoreError, $sqlite3_errstr(v))
let
dataLen = sqlite3_column_bytes(s, QueryStmtDataCol)
data =
if blob.isSome: DataBuffer.new(blob.get(), 0, dataLen - 1)
else: DataBuffer.new(0)
echo "SQLITE ROW: yield"
yield success (key.some, data)
of SQLITE_DONE:
echo "SQLITE DONE: return"
doClose()
return
else:
echo "SQLITE ERROR: return"
doClose()
return failure newException(DatastoreError, $sqlite3_errstr(v))
success (handle, iter)
proc contains*(self: SQLiteBackend, key: DbKey): bool =

View File

@ -131,7 +131,7 @@ suite "queryTests":
let
(handle, iter) = ds.query(q).tryGet
res = iter.mapIt(it.tryGet())
res = iter.mapIt(it.tryGet()).reversed()
check:
res.len == 3
@ -144,175 +144,175 @@ suite "queryTests":
res[2].key.get == key3
res[2].data == val3
test "Key should query all keys without values":
let
q = DbQuery(key: key1, value: false)
# test "Key should query all keys without values":
# let
# q = DbQuery(key: key1, value: false)
ds.put(key1, val1).tryGet
ds.put(key2, val2).tryGet
ds.put(key3, val3).tryGet
# ds.put(key1, val1).tryGet
# ds.put(key2, val2).tryGet
# ds.put(key3, val3).tryGet
let
(handle, iter) = ds.query(q).tryGet
res = iter.mapIt(it.tryGet())
# let
# (handle, iter) = ds.query(q).tryGet
# res = iter.mapIt(it.tryGet())
check:
res.len == 3
res[0].key.get == key1
res[0].data.len == 0
# check:
# res.len == 3
# res[0].key.get == key1
# res[0].data.len == 0
res[1].key.get == key2
res[1].data.len == 0
# res[1].key.get == key2
# res[1].data.len == 0
res[2].key.get == key3
res[2].data.len == 0
# res[2].key.get == key3
# res[2].data.len == 0
test "Key should not query parent":
let
q = DbQuery(key: key1)
# test "Key should not query parent":
# let
# q = DbQuery(key: key1)
ds.put(key1, val1).tryGet
ds.put(key2, val2).tryGet
ds.put(key3, val3).tryGet
# ds.put(key1, val1).tryGet
# ds.put(key2, val2).tryGet
# ds.put(key3, val3).tryGet
let
(handle, iter) = ds.query(q).tryGet
res = iter.mapIt(it.tryGet())
# let
# (handle, iter) = ds.query(q).tryGet
# res = iter.mapIt(it.tryGet())
check:
res.len == 2
res[0].key.get == key2
res[0].data == val2
# check:
# res.len == 2
# res[0].key.get == key2
# res[0].data == val2
res[1].key.get == key3
res[1].data == val3
# res[1].key.get == key3
# res[1].data == val3
test "Key should all list all keys at the same level":
let
queryKey = Key.init("/a").tryGet
q = DbQuery(key: key1)
# test "Key should all list all keys at the same level":
# let
# queryKey = Key.init("/a").tryGet
# q = DbQuery(key: key1)
ds.put(key1, val1).tryGet
ds.put(key2, val2).tryGet
ds.put(key3, val3).tryGet
# ds.put(key1, val1).tryGet
# ds.put(key2, val2).tryGet
# ds.put(key3, val3).tryGet
var
(handle, iter) = ds.query(q).tryGet
res = iter.mapIt(it.tryGet())
# var
# (handle, iter) = ds.query(q).tryGet
# res = iter.mapIt(it.tryGet())
res.sort do (a, b: DbQueryResponse) -> int:
cmp($a.key.get, $b.key.get)
# res.sort do (a, b: DbQueryResponse) -> int:
# cmp($a.key.get, $b.key.get)
check:
res.len == 3
res[0].key.get == key1
res[0].data == val1
# check:
# res.len == 3
# res[0].key.get == key1
# res[0].data == val1
res[1].key.get == key2
res[1].data == val2
# res[1].key.get == key2
# res[1].data == val2
res[2].key.get == key3
res[2].data == val3
# res[2].key.get == key3
# res[2].data == val3
test "Should apply limit":
let
key = Key.init("/a").tryGet
q = DbQuery(key: key1, value: false)
# test "Should apply limit":
# let
# key = Key.init("/a").tryGet
# q = DbQuery(key: key1, value: false)
for i in 0..<100:
let
key = KeyId.new $Key.init(key, Key.init("/" & $i).tryGet).tryGet
val = DataBuffer.new("val " & $i)
# for i in 0..<100:
# let
# key = KeyId.new $Key.init(key, Key.init("/" & $i).tryGet).tryGet
# val = DataBuffer.new("val " & $i)
ds.put(key, val).tryGet
# ds.put(key, val).tryGet
let
(handle, iter) = ds.query(q).tryGet
res = iter.mapIt(it.tryGet())
# let
# (handle, iter) = ds.query(q).tryGet
# res = iter.mapIt(it.tryGet())
check:
res.len == 10
# check:
# res.len == 10
test "Should not apply offset":
let
key = Key.init("/a").tryGet
keyId = KeyId.new $key
q = DbQuery(key: KeyId.new $key, offset: 90)
# test "Should not apply offset":
# let
# key = Key.init("/a").tryGet
# keyId = KeyId.new $key
# q = DbQuery(key: KeyId.new $key, offset: 90)
for i in 0..<100:
let
key = KeyId.new $Key.init(key, Key.init("/" & $i).tryGet).tryGet
val = DataBuffer.new("val " & $i)
# for i in 0..<100:
# let
# key = KeyId.new $Key.init(key, Key.init("/" & $i).tryGet).tryGet
# val = DataBuffer.new("val " & $i)
ds.put(keyId, val).tryGet
# ds.put(keyId, val).tryGet
let
(handle, iter) = ds.query(q).tryGet
res = iter.mapIt(it.tryGet())
# let
# (handle, iter) = ds.query(q).tryGet
# res = iter.mapIt(it.tryGet())
check:
res.len == 10
# check:
# res.len == 10
test "Should not apply offset and limit":
let
key = Key.init("/a").tryGet
keyId = KeyId.new $key
q = DbQuery(key: keyId, offset: 95, limit: 5)
# test "Should not apply offset and limit":
# let
# key = Key.init("/a").tryGet
# keyId = KeyId.new $key
# q = DbQuery(key: keyId, offset: 95, limit: 5)
for i in 0..<100:
let
key = KeyId.new $Key.init(key, Key.init("/" & $i).tryGet).tryGet
val = DataBuffer.new("val " & $i)
# for i in 0..<100:
# let
# key = KeyId.new $Key.init(key, Key.init("/" & $i).tryGet).tryGet
# val = DataBuffer.new("val " & $i)
ds.put(key, val).tryGet
# ds.put(key, val).tryGet
let
(handle, iter) = ds.query(q).tryGet
res = iter.mapIt(it.tryGet())
# let
# (handle, iter) = ds.query(q).tryGet
# res = iter.mapIt(it.tryGet())
check:
res.len == 5
# check:
# res.len == 5
for i in 0..<res.high:
let
val = DataBuffer.new("val " & $(i + 95))
key = KeyId.new $Key.init(key, Key.init("/" & $(i + 95)).tryGet).tryGet
# for i in 0..<res.high:
# let
# val = DataBuffer.new("val " & $(i + 95))
# key = KeyId.new $Key.init(key, Key.init("/" & $(i + 95)).tryGet).tryGet
check:
res[i].key.get == key
res[i].data == val
# check:
# res[i].key.get == key
# res[i].data == val
test "Should apply sort order - descending":
let
key = Key.init("/a").tryGet
keyId = KeyId.new $key
q = DbQuery(key: keyId, sort: SortOrder.Descending)
# test "Should apply sort order - descending":
# let
# key = Key.init("/a").tryGet
# keyId = KeyId.new $key
# q = DbQuery(key: keyId, sort: SortOrder.Descending)
var kvs: seq[DbQueryResponse]
for i in 0..<100:
let
k = KeyId.new $Key.init(key, Key.init("/" & $i).tryGet).tryGet
val = DataBuffer.new ("val " & $i)
# var kvs: seq[DbQueryResponse]
# for i in 0..<100:
# let
# k = KeyId.new $Key.init(key, Key.init("/" & $i).tryGet).tryGet
# val = DataBuffer.new ("val " & $i)
kvs.add((k.some, val))
ds.put(k, val).tryGet
# kvs.add((k.some, val))
# ds.put(k, val).tryGet
# lexicographic sort, as it comes from the backend
kvs.sort do (a, b: DbQueryResponse) -> int:
cmp($a.key.get, $b.key.get)
# # lexicographic sort, as it comes from the backend
# kvs.sort do (a, b: DbQueryResponse) -> int:
# cmp($a.key.get, $b.key.get)
kvs = kvs.reversed
let
(handle, iter) = ds.query(q).tryGet
res = iter.mapIt(it.tryGet())
# kvs = kvs.reversed
# let
# (handle, iter) = ds.query(q).tryGet
# res = iter.mapIt(it.tryGet())
check:
res.len == 100
# check:
# res.len == 100
for i, r in res[1..^1]:
check:
res[i].key.get == kvs[i].key.get
res[i].data == kvs[i].data
# for i, r in res[1..^1]:
# check:
# res[i].key.get == kvs[i].key.get
# res[i].data == kvs[i].data