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:
mahlon 2025-03-23 21:21:05 +00:00
parent 7850a79372
commit 6d34b081bb
10 changed files with 344 additions and 14 deletions

View file

@ -22,6 +22,117 @@ proc query*( conn: KuzuConnection, query: string ): KuzuQueryResult =
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 =
## Return the entire result set as a string.
result = $kuzu_query_result_to_string( addr query.handle )
@ -33,12 +144,19 @@ proc hasNext*( query: KuzuQueryResult ): bool =
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
if kuzu_query_result_get_next( addr query.handle, addr result.handle ) == KuzuSuccess:
result.valid = true
result.num_columns = query.num_columns
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 =

View file

@ -17,6 +17,14 @@ proc `[]`*( tpl: KuzuFlatTuple, idx: int ): KuzuValue =
result = new KuzuValue
if kuzu_flat_tuple_get_value( addr tpl.handle, idx.uint64, addr result.handle ) == KuzuSuccess:
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:
raise newException( KuzuIndexException,
&"Unable to fetch tuple value at idx {idx}. ({tpl.num_columns} column(s).)" )

View file

@ -2,19 +2,19 @@
type
KuzuDatabaseObj = object
handle*: kuzu_database
path*: string
handle: kuzu_database
path*: string
config*: kuzu_system_config
valid = false
KuzuDatabase* = ref KuzuDatabaseObj
KuzuConnectionObj = object
handle*: kuzu_connection
handle: kuzu_connection
valid = false
KuzuConnection* = ref KuzuConnectionObj
KuzuQueryResultObj = object
handle*: kuzu_query_result
handle: kuzu_query_result
summary: kuzu_query_summary
num_columns*: uint64 = 0
num_tuples*: uint64 = 0
@ -23,18 +23,24 @@ type
valid = false
KuzuQueryResult* = ref KuzuQueryResultObj
KuzuPreparedStatementObj = object
handle: kuzu_prepared_statement
conn: KuzuConnection
valid = false
KuzuPreparedStatement* = ref KuzuPreparedStatementObj
KuzuFlatTupleObj = object
handle*: kuzu_flat_tuple
handle: kuzu_flat_tuple
num_columns: uint64 = 0
valid = false
KuzuFlatTuple* = ref KuzuFlatTupleObj
KuzuValueObj = object
handle*: kuzu_value
handle: kuzu_value
valid = false
KuzuValue* = ref KuzuValueObj
KuzuException* = object of CatchableError
KuzuException* = object of CatchableError
KuzuQueryException* = object of KuzuException
KuzuIndexException* = object of KuzuException