From 421cb87e57019f742317f78d6bb82bfe94fc337a Mon Sep 17 00:00:00 2001 From: mahlon <> Date: Thu, 27 Mar 2025 08:09:17 +0000 Subject: [PATCH] Checkpoint. - Add column names and types to KuzuQuery objects. - Start sketching out type conversions. - Add a "kind" method to KuzuValue, that returns its Kuzu type. (type is a reserved word) - Fix some tests for post v0.8.2 behaviors. FossilOrigin-Name: 64c0694e58507ce91f2e0eced106c9fef2a739665ddaa29f60b4ca9fe65678fe --- experiments/prepared-test.c | 7 ++- src/kuzu/queries.nim | 50 ++++++++++++++++--- src/kuzu/tuple.nim | 7 --- src/kuzu/types.nim | 3 +- src/kuzu/value.nim | 30 +++++++++++ tests/constants/t_knows_its_libversion.nim | 2 +- tests/queries/t_can_prepare_a_statement.nim | 4 +- .../t_knows_if_there_are_waiting_tuples.nim | 2 +- 8 files changed, 82 insertions(+), 23 deletions(-) diff --git a/experiments/prepared-test.c b/experiments/prepared-test.c index a103538..ed0149f 100644 --- a/experiments/prepared-test.c +++ b/experiments/prepared-test.c @@ -37,7 +37,7 @@ int main() "CREATE NODE TABLE Test ( id SERIAL, thing STRING, PRIMARY KEY(id) )", &q ) != KuzuSuccess ) { printf( "Couldn't create schema?!\n" ); - return( 1 ); + return 1; } @@ -46,9 +46,9 @@ int main() &conn, "CREATE (t:Test {thing: $thing})", &stmt - ) != KuzuSuccess ) { + ) != KuzuSuccess ) { printf( "Couldn't prepare statement?\n" ); - return( 1 ); + return 1; } @@ -79,4 +79,3 @@ int main() return 0; } - diff --git a/src/kuzu/queries.nim b/src/kuzu/queries.nim index 24f3215..6c4ee60 100644 --- a/src/kuzu/queries.nim +++ b/src/kuzu/queries.nim @@ -4,19 +4,55 @@ proc `=destroy`*( query: KuzuQueryResultObj ) = ## Graceful cleanup for out of scope query objects. if query.valid: kuzu_query_result_destroy( addr query.handle ) - kuzu_query_summary_destroy( addr query.summary ) + + +proc getQueryMetadata( query: KuzuQueryResult ) = + ## Find and retain additional data for the query. + query.num_columns = kuzu_query_result_get_num_columns( addr query.handle ) + query.num_tuples = kuzu_query_result_get_num_tuples( addr query.handle ) + + # Summary information. + var summary: kuzu_query_summary + discard kuzu_query_result_get_query_summary( addr query.handle, addr summary ) + query.compile_time = kuzu_query_summary_get_compiling_time( addr summary ) + query.execution_time = kuzu_query_summary_get_execution_time( addr summary ) + kuzu_query_summary_destroy( addr summary ) + + # Column information. + query.column_types = @[] + query.column_names = @[] + for idx in ( 0 .. query.num_columns-1 ): + + # types + # + var logical_type: kuzu_logical_type + discard kuzu_query_result_get_column_data_type( + addr query.handle, + idx, + addr logical_type + ) + query.column_types.add( kuzu_data_type_get_id( addr logical_type )) + kuzu_data_type_destroy( addr logical_type ) + + # names + # + var name: cstring + discard kuzu_query_result_get_column_name( + addr query.handle, + idx, + addr name + ) + query.column_names.add( $name ) + kuzu_destroy_string( name ) proc query*( conn: KuzuConnection, query: string ): KuzuQueryResult = ## Perform a database +query+ and return the result. result = new KuzuQueryResult + if kuzu_connection_query( addr conn.handle, query, 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 + result.valid = true + result.getQueryMetadata() else: var err = kuzu_query_result_get_error_message( addr result.handle ) raise newException( KuzuQueryException, &"Error running query: {err}" ) diff --git a/src/kuzu/tuple.nim b/src/kuzu/tuple.nim index bc3751a..b584279 100644 --- a/src/kuzu/tuple.nim +++ b/src/kuzu/tuple.nim @@ -18,13 +18,6 @@ proc `[]`*( tpl: KuzuFlatTuple, idx: int ): 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).)" ) diff --git a/src/kuzu/types.nim b/src/kuzu/types.nim index 6bb9f9f..0767417 100644 --- a/src/kuzu/types.nim +++ b/src/kuzu/types.nim @@ -15,11 +15,12 @@ type KuzuQueryResultObj = object handle: kuzu_query_result - summary: kuzu_query_summary num_columns*: uint64 = 0 num_tuples*: uint64 = 0 compile_time*: cdouble = 0 execution_time*: cdouble = 0 + column_types*: seq[ kuzu_data_type_id ] + column_names*: seq[ string ] valid = false KuzuQueryResult* = ref KuzuQueryResultObj diff --git a/src/kuzu/value.nim b/src/kuzu/value.nim index ba2fe97..14d5a01 100644 --- a/src/kuzu/value.nim +++ b/src/kuzu/value.nim @@ -11,3 +11,33 @@ proc `$`*( value: KuzuValue ): string = result = $kuzu_value_to_string( addr value.handle ) +proc kind*( value: KuzuValue ): kuzu_data_type_id = + ## Find and return the native Kuzu type of this value. + var logical_type: kuzu_logical_type + kuzu_value_get_data_type( addr value.handle, addr logical_type ) + result = kuzu_data_type_get_id( addr logical_type ) + # var num: uint64 + # discard kuzu_data_type_get_num_elements_in_array( addr logical_type, addr num ) + # echo "HMMM ", $num + kuzu_data_type_destroy( addr logical_type ) + + # enum_kuzu_data_type_id_570425857* {.size: sizeof(cuint).} = enum + # KUZU_ANY = 0, KUZU_NODE = 10, KUZU_REL = 11, KUZU_RECURSIVE_REL = 12, + # KUZU_SERIAL = 13, KUZU_BOOL = 22, KUZU_INT64 = 23, KUZU_INT32 = 24, + # KUZU_INT16 = 25, KUZU_INT8 = 26, KUZU_UINT64 = 27, KUZU_UINT32 = 28, + # KUZU_UINT16 = 29, KUZU_UINT8 = 30, KUZU_INT128 = 31, KUZU_DOUBLE = 32, + # KUZU_FLOAT = 33, KUZU_DATE = 34, KUZU_TIMESTAMP = 35, + # KUZU_TIMESTAMP_SEC = 36, KUZU_TIMESTAMP_MS = 37, KUZU_TIMESTAMP_NS = 38, + # KUZU_TIMESTAMP_TZ = 39, KUZU_INTERVAL = 40, KUZU_DECIMAL = 41, + # KUZU_INTERNAL_ID = 42, KUZU_STRING = 50, KUZU_BLOB = 51, KUZU_LIST = 52, + # KUZU_ARRAY = 53, KUZU_STRUCT = 54, KUZU_MAP = 55, KUZU_UNION = 56, + # KUZU_POINTER = 58, KUZU_UUID = 59 + +# proc getValue*( value: KuzuValue ): +# +# FIXME: type checks and conversions from supported kuzu +# types to supported Nim types. +# +# Currently the value can only be stringified via `$`. +# + diff --git a/tests/constants/t_knows_its_libversion.nim b/tests/constants/t_knows_its_libversion.nim index 938312b..68dbaa5 100644 --- a/tests/constants/t_knows_its_libversion.nim +++ b/tests/constants/t_knows_its_libversion.nim @@ -3,5 +3,5 @@ import re import kuzu -assert KUZU_LIBVERSION.contains( re"^\d+\.\d+\.\d+$" ) +assert KUZU_LIBVERSION.contains( re"^\d+\.\d+\.\d+(?:\.\d+)?$" ) diff --git a/tests/queries/t_can_prepare_a_statement.nim b/tests/queries/t_can_prepare_a_statement.nim index 06b1fd8..d5e17b9 100644 --- a/tests/queries/t_can_prepare_a_statement.nim +++ b/tests/queries/t_can_prepare_a_statement.nim @@ -18,8 +18,8 @@ for thing in @[ "Camel", "Lampshade", "Delicious Cake" ]: q = p.execute( (thing: thing) ) assert typeOf( q ) is KuzuQueryResult -# This is failing until I can address -# https://github.com/kuzudb/kuzu/issues/5102 +# Fixed post v0.8.2: +# https://github.com/kuzudb/kuzu/issues/5102 q = conn.query( "MATCH (d:Doop) RETURN d.thing" ) echo $q diff --git a/tests/queries/t_knows_if_there_are_waiting_tuples.nim b/tests/queries/t_knows_if_there_are_waiting_tuples.nim index 6a2e76f..5cfdc07 100644 --- a/tests/queries/t_knows_if_there_are_waiting_tuples.nim +++ b/tests/queries/t_knows_if_there_are_waiting_tuples.nim @@ -17,7 +17,7 @@ q = conn.query( "MATCH (d:Doop) RETURN d.thing" ) assert q.num_tuples == 1 assert q.hasNext == true -discard $q # consume the tuple result +discard q.getNext # consume the tuple result assert q.num_tuples == 1 assert q.hasNext == false