Work on prepared statements.
(Still not working 100%, but getting close.) Additionally, start on the README, fix some type member visibility, add some additional tests, tag some FIXMEs for where type conversions will take place, and add `#rewind` for the query iterator. FossilOrigin-Name: 490f27a4792d5243d82d90dcb12be1074c945c74d7fa63dd5baaf942ac42d7c9
This commit is contained in:
parent
7850a79372
commit
6d34b081bb
10 changed files with 344 additions and 14 deletions
110
README.md
110
README.md
|
|
@ -1 +1,109 @@
|
||||||
**TBD**
|
|
||||||
|
# Nim Kuzu
|
||||||
|
|
||||||
|
home
|
||||||
|
: https://code.martini.nu/fossil/nim-kuzu
|
||||||
|
|
||||||
|
github_mirror
|
||||||
|
: https://github.com/mahlonsmith/nim-kuzu
|
||||||
|
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
This is a Nim binding for the Kuzu graph database library.
|
||||||
|
|
||||||
|
Kuzu is an embedded graph database built for query speed and scalability. It is
|
||||||
|
optimized for handling complex join-heavy analytical workloads on very large
|
||||||
|
graphs, with the following core feature set:
|
||||||
|
|
||||||
|
- Property Graph data model and Cypher query language
|
||||||
|
- Embedded (in-process) integration with applications
|
||||||
|
- Columnar disk-based storage
|
||||||
|
- Columnar, compressed sparse row-based (CSR) adjacency list/join indices
|
||||||
|
- Vectorized and factorized query processor
|
||||||
|
- Novel and very fast join algorithms
|
||||||
|
- Multi-core query parallelism
|
||||||
|
- Serializable ACID transactions
|
||||||
|
|
||||||
|
For more information about Kuzu itself, see its
|
||||||
|
[documentation](https://docs.kuzudb.com/).
|
||||||
|
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
* A functioning Nim >= 2 installation
|
||||||
|
- [KuzuDB](https://kuzudb.com)
|
||||||
|
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
$ nimble install kuzu
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
|
||||||
|
> [!TODO]- Human readable usage docs!
|
||||||
|
>
|
||||||
|
> ... The nim generated source isn't great when pulling in
|
||||||
|
> the C wrapper auto-gen stuff.
|
||||||
|
>
|
||||||
|
> If you're here and reading this before I have proper docs written, see the
|
||||||
|
> tests/ for some working examples.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
You can check out the current development source with Fossil via its [home
|
||||||
|
repo](https://code.martini.nu/fossil/nim-kuzu), or with Git/Jujutsu at its
|
||||||
|
[project mirror](https://github.com/mahlonsmith/nim-kuzu)
|
||||||
|
|
||||||
|
After checking out the source, uncomment the development dependencies
|
||||||
|
from the `kuzu.nimble` file, and run:
|
||||||
|
|
||||||
|
$ nimble setup
|
||||||
|
|
||||||
|
This will install dependencies, and do any other necessary setup for
|
||||||
|
development.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
- Mahlon E. Smith <mahlon@martini.nu>
|
||||||
|
|
||||||
|
A note of thanks to @mantielero on Github, who has a Kuzu binding for an early
|
||||||
|
KuzuDB (0.4.x) that I found after starting this project.
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Copyright (c) 2025 Mahlon E. Smith
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the author/s, nor the names of the project's
|
||||||
|
contributors may be used to endorse or promote products derived from this
|
||||||
|
software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
|
||||||
10
kuzu.nimble
10
kuzu.nimble
|
|
@ -16,9 +16,13 @@ task makewrapper, "Generate the C wrapper using Futhark":
|
||||||
exec "nim c -d:futharkWrap --outdir=. src/kuzu.nim"
|
exec "nim c -d:futharkWrap --outdir=. src/kuzu.nim"
|
||||||
|
|
||||||
task test, "Run the test suite.":
|
task test, "Run the test suite.":
|
||||||
exec "testament all"
|
exec "testament --megatest:off all"
|
||||||
exec "testament html"
|
exec "testament html"
|
||||||
|
|
||||||
task clean, "Remove all non-critical artifacts.":
|
task clean, "Remove all non-repository artifacts.":
|
||||||
exec "fossil clean --disable-undo --dotfiles --emptydirs -f -v"
|
exec "fossil clean -x"
|
||||||
|
|
||||||
|
task docs, "Generate automated documentation.":
|
||||||
|
exec "nim doc --project --outdir:docs src/kuzu.nim"
|
||||||
|
exec "nim md2html --project --outdir:docs README.md"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,117 @@ proc query*( conn: KuzuConnection, query: string ): KuzuQueryResult =
|
||||||
raise newException( KuzuQueryException, &"Error running query: {err}" )
|
raise newException( KuzuQueryException, &"Error running query: {err}" )
|
||||||
|
|
||||||
|
|
||||||
|
proc `=destroy`*( prepared: KuzuPreparedStatementObj ) =
|
||||||
|
## Graceful cleanup for out of scope prepared objects.
|
||||||
|
if prepared.valid:
|
||||||
|
kuzu_prepared_statement_destroy( addr prepared.handle )
|
||||||
|
|
||||||
|
|
||||||
|
proc prepare*( conn: KuzuConnection, query: string ): KuzuPreparedStatement =
|
||||||
|
## Return a prepared statement that can avoid planning for repeat calls,
|
||||||
|
## with optional variable binding via #execute.
|
||||||
|
result = new KuzuPreparedStatement
|
||||||
|
if kuzu_connection_prepare( addr conn.handle, query, addr result.handle ) == KuzuSuccess:
|
||||||
|
result.conn = conn
|
||||||
|
result.valid = true
|
||||||
|
else:
|
||||||
|
var err = kuzu_prepared_statement_get_error_message( addr result.handle )
|
||||||
|
raise newException( KuzuQueryException, &"Error preparing statement: {err}" )
|
||||||
|
|
||||||
|
|
||||||
|
proc execute*(
|
||||||
|
prepared: KuzuPreparedStatement,
|
||||||
|
params: tuple = ()
|
||||||
|
): KuzuQueryResult =
|
||||||
|
## Bind variables in *params* to the statement, and return
|
||||||
|
## a KuzuQueryResult.
|
||||||
|
|
||||||
|
result = new KuzuQueryResult
|
||||||
|
|
||||||
|
for key, val in params.fieldPairs:
|
||||||
|
#
|
||||||
|
# FIXME: type checks and conversions for all bound variables
|
||||||
|
# from nim types to supported Kuzu types.
|
||||||
|
#
|
||||||
|
discard kuzu_prepared_statement_bind_string( addr prepared.handle, key.cstring, val.cstring )
|
||||||
|
|
||||||
|
#[
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_bool (kuzu_prepared_statement *prepared_statement, const char *param_name, bool value)
|
||||||
|
Binds the given boolean value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_int64 (kuzu_prepared_statement *prepared_statement, const char *param_name, int64_t value)
|
||||||
|
Binds the given int64_t value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_int32 (kuzu_prepared_statement *prepared_statement, const char *param_name, int32_t value)
|
||||||
|
Binds the given int32_t value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_int16 (kuzu_prepared_statement *prepared_statement, const char *param_name, int16_t value)
|
||||||
|
Binds the given int16_t value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_int8 (kuzu_prepared_statement *prepared_statement, const char *param_name, int8_t value)
|
||||||
|
Binds the given int8_t value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_uint64 (kuzu_prepared_statement *prepared_statement, const char *param_name, uint64_t value)
|
||||||
|
Binds the given uint64_t value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_uint32 (kuzu_prepared_statement *prepared_statement, const char *param_name, uint32_t value)
|
||||||
|
Binds the given uint32_t value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_uint16 (kuzu_prepared_statement *prepared_statement, const char *param_name, uint16_t value)
|
||||||
|
Binds the given uint16_t value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_uint8 (kuzu_prepared_statement *prepared_statement, const char *param_name, uint8_t value)
|
||||||
|
Binds the given int8_t value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_double (kuzu_prepared_statement *prepared_statement, const char *param_name, double value)
|
||||||
|
Binds the given double value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_float (kuzu_prepared_statement *prepared_statement, const char *param_name, float value)
|
||||||
|
Binds the given float value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_date (kuzu_prepared_statement *prepared_statement, const char *param_name, kuzu_date_t value)
|
||||||
|
Binds the given date value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_timestamp_ns (kuzu_prepared_statement *prepared_statement, const char *param_name, kuzu_timestamp_ns_t value)
|
||||||
|
Binds the given timestamp_ns value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_timestamp_sec (kuzu_prepared_statement *prepared_statement, const char *param_name, kuzu_timestamp_sec_t value)
|
||||||
|
Binds the given timestamp_sec value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_timestamp_tz (kuzu_prepared_statement *prepared_statement, const char *param_name, kuzu_timestamp_tz_t value)
|
||||||
|
Binds the given timestamp_tz value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_timestamp_ms (kuzu_prepared_statement *prepared_statement, const char *param_name, kuzu_timestamp_ms_t value)
|
||||||
|
Binds the given timestamp_ms value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_timestamp (kuzu_prepared_statement *prepared_statement, const char *param_name, kuzu_timestamp_t value)
|
||||||
|
Binds the given timestamp value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_interval (kuzu_prepared_statement *prepared_statement, const char *param_name, kuzu_interval_t value)
|
||||||
|
Binds the given interval value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_string (kuzu_prepared_statement *prepared_statement, const char *param_name, const char *value)
|
||||||
|
Binds the given string value to the given parameter name in the prepared statement.
|
||||||
|
|
||||||
|
KUZU_C_API kuzu_state kuzu_prepared_statement_bind_value (kuzu_prepared_statement *prepared_statement, const char *param_name, kuzu_value *value)
|
||||||
|
]#
|
||||||
|
|
||||||
|
if kuzu_connection_execute(
|
||||||
|
addr prepared.conn.handle,
|
||||||
|
addr prepared.handle,
|
||||||
|
addr result.handle
|
||||||
|
) == KuzuSuccess:
|
||||||
|
discard kuzu_query_result_get_query_summary( addr result.handle, addr result.summary )
|
||||||
|
result.num_columns = kuzu_query_result_get_num_columns( addr result.handle )
|
||||||
|
result.num_tuples = kuzu_query_result_get_num_tuples( addr result.handle )
|
||||||
|
result.compile_time = kuzu_query_summary_get_compiling_time( addr result.summary )
|
||||||
|
result.execution_time = kuzu_query_summary_get_execution_time( addr result.summary )
|
||||||
|
result.valid = true
|
||||||
|
else:
|
||||||
|
var err = kuzu_query_result_get_error_message( addr result.handle )
|
||||||
|
raise newException( KuzuQueryException, &"Error executing prepared statement: {err}" )
|
||||||
|
|
||||||
|
|
||||||
proc `$`*( query: KuzuQueryResult ): string =
|
proc `$`*( query: KuzuQueryResult ): string =
|
||||||
## Return the entire result set as a string.
|
## Return the entire result set as a string.
|
||||||
result = $kuzu_query_result_to_string( addr query.handle )
|
result = $kuzu_query_result_to_string( addr query.handle )
|
||||||
|
|
@ -33,12 +144,19 @@ proc hasNext*( query: KuzuQueryResult ): bool =
|
||||||
|
|
||||||
|
|
||||||
proc getNext*( query: KuzuQueryResult ): KuzuFlatTuple =
|
proc getNext*( query: KuzuQueryResult ): KuzuFlatTuple =
|
||||||
|
## Consume and return the next tuple result, or raise a KuzuIndexException
|
||||||
|
## if at the end of the result set.
|
||||||
result = new KuzuFlatTuple
|
result = new KuzuFlatTuple
|
||||||
if kuzu_query_result_get_next( addr query.handle, addr result.handle ) == KuzuSuccess:
|
if kuzu_query_result_get_next( addr query.handle, addr result.handle ) == KuzuSuccess:
|
||||||
result.valid = true
|
result.valid = true
|
||||||
result.num_columns = query.num_columns
|
result.num_columns = query.num_columns
|
||||||
else:
|
else:
|
||||||
raise newException( KuzuQueryException, &"Unable to fetch next tuple." )
|
raise newException( KuzuIndexException, &"Query iteration past end." )
|
||||||
|
|
||||||
|
|
||||||
|
proc rewind*( query: KuzuQueryResult ) =
|
||||||
|
## Reset query iteration back to the beginning.
|
||||||
|
kuzu_query_result_reset_iterator( addr query.handle )
|
||||||
|
|
||||||
|
|
||||||
iterator items*( query: KuzuQueryResult ): KuzuFlatTuple =
|
iterator items*( query: KuzuQueryResult ): KuzuFlatTuple =
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,14 @@ proc `[]`*( tpl: KuzuFlatTuple, idx: int ): KuzuValue =
|
||||||
result = new KuzuValue
|
result = new KuzuValue
|
||||||
if kuzu_flat_tuple_get_value( addr tpl.handle, idx.uint64, addr result.handle ) == KuzuSuccess:
|
if kuzu_flat_tuple_get_value( addr tpl.handle, idx.uint64, addr result.handle ) == KuzuSuccess:
|
||||||
result.valid = true
|
result.valid = true
|
||||||
|
|
||||||
|
#
|
||||||
|
# FIXME: type checks and conversions from supported kuzu
|
||||||
|
# types to supported Nim types.
|
||||||
|
#
|
||||||
|
# Currently the value can only be stringified via `$`.
|
||||||
|
#
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise newException( KuzuIndexException,
|
raise newException( KuzuIndexException,
|
||||||
&"Unable to fetch tuple value at idx {idx}. ({tpl.num_columns} column(s).)" )
|
&"Unable to fetch tuple value at idx {idx}. ({tpl.num_columns} column(s).)" )
|
||||||
|
|
|
||||||
|
|
@ -2,19 +2,19 @@
|
||||||
|
|
||||||
type
|
type
|
||||||
KuzuDatabaseObj = object
|
KuzuDatabaseObj = object
|
||||||
handle*: kuzu_database
|
handle: kuzu_database
|
||||||
path*: string
|
path*: string
|
||||||
config*: kuzu_system_config
|
config*: kuzu_system_config
|
||||||
valid = false
|
valid = false
|
||||||
KuzuDatabase* = ref KuzuDatabaseObj
|
KuzuDatabase* = ref KuzuDatabaseObj
|
||||||
|
|
||||||
KuzuConnectionObj = object
|
KuzuConnectionObj = object
|
||||||
handle*: kuzu_connection
|
handle: kuzu_connection
|
||||||
valid = false
|
valid = false
|
||||||
KuzuConnection* = ref KuzuConnectionObj
|
KuzuConnection* = ref KuzuConnectionObj
|
||||||
|
|
||||||
KuzuQueryResultObj = object
|
KuzuQueryResultObj = object
|
||||||
handle*: kuzu_query_result
|
handle: kuzu_query_result
|
||||||
summary: kuzu_query_summary
|
summary: kuzu_query_summary
|
||||||
num_columns*: uint64 = 0
|
num_columns*: uint64 = 0
|
||||||
num_tuples*: uint64 = 0
|
num_tuples*: uint64 = 0
|
||||||
|
|
@ -23,14 +23,20 @@ type
|
||||||
valid = false
|
valid = false
|
||||||
KuzuQueryResult* = ref KuzuQueryResultObj
|
KuzuQueryResult* = ref KuzuQueryResultObj
|
||||||
|
|
||||||
|
KuzuPreparedStatementObj = object
|
||||||
|
handle: kuzu_prepared_statement
|
||||||
|
conn: KuzuConnection
|
||||||
|
valid = false
|
||||||
|
KuzuPreparedStatement* = ref KuzuPreparedStatementObj
|
||||||
|
|
||||||
KuzuFlatTupleObj = object
|
KuzuFlatTupleObj = object
|
||||||
handle*: kuzu_flat_tuple
|
handle: kuzu_flat_tuple
|
||||||
num_columns: uint64 = 0
|
num_columns: uint64 = 0
|
||||||
valid = false
|
valid = false
|
||||||
KuzuFlatTuple* = ref KuzuFlatTupleObj
|
KuzuFlatTuple* = ref KuzuFlatTupleObj
|
||||||
|
|
||||||
KuzuValueObj = object
|
KuzuValueObj = object
|
||||||
handle*: kuzu_value
|
handle: kuzu_value
|
||||||
valid = false
|
valid = false
|
||||||
KuzuValue* = ref KuzuValueObj
|
KuzuValue* = ref KuzuValueObj
|
||||||
|
|
||||||
|
|
|
||||||
23
tests/queries/t_can_prepare_a_statement.nim
Normal file
23
tests/queries/t_can_prepare_a_statement.nim
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
# vim: set et sta sw=4 ts=4 :
|
||||||
|
|
||||||
|
discard """
|
||||||
|
output: "d.thing\nCamel\nLampshade\nDelicious Cake\n"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import kuzu
|
||||||
|
|
||||||
|
let db = newKuzuDatabase()
|
||||||
|
let conn = db.connect
|
||||||
|
|
||||||
|
var q = conn.query( "CREATE NODE TABLE Doop ( id SERIAL, thing STRING, PRIMARY KEY(id) )" )
|
||||||
|
|
||||||
|
var p = conn.prepare( "CREATE (d:Doop {thing: $thing})" )
|
||||||
|
assert typeOf( p ) is KuzuPreparedStatement
|
||||||
|
|
||||||
|
for thing in @[ "Camel", "Lampshade", "Delicious Cake" ]:
|
||||||
|
q = p.execute( (thing: thing) )
|
||||||
|
assert typeOf( q ) is KuzuQueryResult
|
||||||
|
|
||||||
|
q = conn.query( "MATCH (d:Doop) RETURN d.thing" )
|
||||||
|
echo $q
|
||||||
|
|
||||||
23
tests/queries/t_can_rewind_iteration.nim
Normal file
23
tests/queries/t_can_rewind_iteration.nim
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
# vim: set et sta sw=4 ts=4 :
|
||||||
|
|
||||||
|
discard """
|
||||||
|
output: "Camel\nLampshade\nCamel\nLampshade\n"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import kuzu
|
||||||
|
|
||||||
|
let db = newKuzuDatabase()
|
||||||
|
let conn = db.connect
|
||||||
|
|
||||||
|
var q = conn.query( "CREATE NODE TABLE Doop ( id SERIAL, thing STRING, PRIMARY KEY(id) )" )
|
||||||
|
|
||||||
|
for thing in @[ "Camel", "Lampshade" ]:
|
||||||
|
q = conn.query( "CREATE (d:Doop {thing: '" & thing & "'})" )
|
||||||
|
|
||||||
|
for tpl in conn.query( "MATCH (d:Doop) RETURN d.thing" ):
|
||||||
|
echo $tpl
|
||||||
|
|
||||||
|
q.rewind
|
||||||
|
|
||||||
|
for tpl in conn.query( "MATCH (d:Doop) RETURN d.thing" ):
|
||||||
|
echo $tpl
|
||||||
20
tests/queries/t_raises_on_unknown_varbind.nim
Normal file
20
tests/queries/t_raises_on_unknown_varbind.nim
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
# vim: set et sta sw=4 ts=4 :
|
||||||
|
|
||||||
|
import
|
||||||
|
std/re
|
||||||
|
import kuzu
|
||||||
|
|
||||||
|
let db = newKuzuDatabase()
|
||||||
|
let conn = db.connect
|
||||||
|
|
||||||
|
var q = conn.query( "CREATE NODE TABLE Doop ( id SERIAL, thing STRING, PRIMARY KEY(id) )" )
|
||||||
|
|
||||||
|
var p = conn.prepare( "CREATE (d:Doop {thing: $thing})" )
|
||||||
|
assert typeOf( p ) is KuzuPreparedStatement
|
||||||
|
|
||||||
|
try:
|
||||||
|
discard p.execute( (nope: "undefined var in statement!") )
|
||||||
|
except KuzuQueryException as err:
|
||||||
|
assert err.msg.contains( re"""Parameter nope not found.""" )
|
||||||
|
|
||||||
|
|
||||||
20
tests/queries/t_raises_with_invalid_prepared_statement.nim
Normal file
20
tests/queries/t_raises_with_invalid_prepared_statement.nim
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
# vim: set et sta sw=4 ts=4 :
|
||||||
|
|
||||||
|
import
|
||||||
|
std/re
|
||||||
|
import kuzu
|
||||||
|
|
||||||
|
let db = newKuzuDatabase()
|
||||||
|
let conn = db.connect
|
||||||
|
|
||||||
|
var q = conn.query( "CREATE NODE TABLE Doop ( id SERIAL, thing STRING, PRIMARY KEY(id) )" )
|
||||||
|
|
||||||
|
var p = conn.prepare( "CREAET (d:Doop {thing: $thing})" )
|
||||||
|
assert typeOf( p ) is KuzuPreparedStatement
|
||||||
|
|
||||||
|
try:
|
||||||
|
discard p.execute
|
||||||
|
except KuzuQueryException as err:
|
||||||
|
assert err.msg.contains( re""".*Error executing prepared statement:.*CREAET""" )
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -12,6 +12,6 @@ q = conn.query( "MATCH (d:Doop) RETURN d.thing" )
|
||||||
|
|
||||||
try:
|
try:
|
||||||
discard q.getNext
|
discard q.getNext
|
||||||
except KuzuQueryException as err:
|
except KuzuIndexException as err:
|
||||||
assert err.msg.contains( re"""Unable to fetch next tuple.""" )
|
assert err.msg.contains( re"""Query iteration past end.""" )
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue