Kuzu::

Result class

Kùzu query result class

These objects contain one result set from either a Kuzu::Connection#query call or Kuzu::PreparedStatement#execute. If there are multiple result sets, you can fetch the next one by calling Kuzu::Result#next_set. You can use has_next_set? to test for a following set.

Tuple values are converted to corresponding Ruby objects:

Kuzu Type Ruby Type
INT8 Integer
INT16 Integer
INT32 Integer
INT64 Integer
INT128 Integer
UINT8 Integer
UINT16 Integer
UINT32 Integer
UINT64 Integer
FLOAT Float
DOUBLE Float
DECIMAL Float
BOOLEAN TrueClass or FalseClass
UUID String (UTF-8 encoding)
STRING String (UTF-8 encoding)
NULL NilClass
DATE Date
TIMESTAMP Time
INTERVAL Float (interval in seconds)
STRUCT OpenStruct via the ostruct standard library
MAP Hash
UNION (not yet handled)
BLOB String (ASCII_8BIT encoding)
SERIAL Integer
NODE Kuzu::Node
REL Kuzu::Rel
RECURSIVE_REL Kuzu::RecursiveRel
LIST Array
ARRAY Array

Public Class Methods

Kuzu::Result.from_next_set( result ) → result2

Return a Kuzu::Result for the next result set after the specified result. Returns nil if there is no next result set..

static VALUE
rkuzu_result_s_from_next_set( VALUE klass, VALUE result )
{
        rkuzu_query_result *start_result = rkuzu_get_result( result );
        rkuzu_query_result *next_result;
        VALUE result_obj;

        if ( RTEST(start_result->next_result) ) {
                return start_result->next_result;
        }

        if ( !kuzu_query_result_has_next_query_result(&start_result->result) ) {
                return Qnil;
        }

        next_result = rkuzu_result_alloc();

        if ( kuzu_query_result_get_next_query_result(&start_result->result, &next_result->result) != KuzuSuccess ) {
                char *err_detail = kuzu_query_result_get_error_message( &next_result->result );
                char errmsg[ 4096 ] = "\0";

                snprintf( errmsg, 4096, "Could not fetch next query result set: %s.", err_detail );

                xfree( next_result );
                next_result = NULL;
                kuzu_destroy_string( err_detail );

                rb_raise( rkuzu_eQueryError, "%s", errmsg );
        }

        DEBUG_GC( ">>> allocated result %p\n", next_result );

        result_obj = rb_class_new_instance( 0, 0, klass );
        RTYPEDDATA_DATA( result_obj ) = next_result;

        next_result->connection = start_result->connection;
        next_result->previous_result = result;

        start_result->next_result = result_obj;

        return result_obj;
}
from_prepared_statement( statement, &block )

Execute the given statement and return the Kuzu::Result. If a block is given, the result will instead be yielded to it, finished when it returns, and the return value of the block will be returned instead.

# File lib/kuzu/result.rb, line 69
def self::from_prepared_statement( statement, &block )
        return statement.execute( &block )
end
from_query( connection, query, &block )

Execute the given query via the specified connection and return the Kuzu::Result. If a block is given, the result will instead be yielded to it, finished when it returns, and the return value of the block will be returned instead.

# File lib/kuzu/result.rb, line 61
def self::from_query( connection, query, &block )
        return connection.query( query, &block )
end
wrap_block_result( result, &block )

If the block is provided, yield result to it and then call finish on it, returning the block result. If block is not given, just return result.

# File lib/kuzu/result.rb, line 76
def self::wrap_block_result( result, &block )
        return result unless block

        begin
                rval = block.call( result )
        ensure
                result.finish
        end

        return rval
end

Public Instance Methods

[]( index )

Index operator: fetch the tuple at index of the current result set.

# File lib/kuzu/result.rb, line 126
def []( index )
        return self.tuples[ index ]
end
column_names()

Fetch the names of the columns in the result as an Array of Strings.

# File lib/kuzu/result.rb, line 90
def    column_names
        return @column_names ||= self.get_column_names
end
each( &block )

Iterate over each tuple of the result, yielding it to the block. If no block is given, return an Enumerator that will yield them instead.

# File lib/kuzu/result.rb, line 111
def    each( &block )
        enum = self.tuple_enum
        return enum.each( &block ) if block
        return enum
end
each_set( &block )

Iterate over each result set in the results, yielding it to the block. If no block is given, return an Enumerator tht will yield each set as its own Result.

# File lib/kuzu/result.rb, line 142
def each_set( &block )
        enum = self.next_set_enum
        return enum.each( &block ) if block
        return enum
end
finish

Discard a result and free up its memory. An exception is raised if the result is used after this call.

static VALUE
rkuzu_result_finish( VALUE self )
{
        rkuzu_query_result *result = CHECK_RESULT( self );
        kuzu_query_result *i_result = &result->result;
        VALUE related_res;

        if ( !result->finished ) {
                DEBUG_GC( ">>> Finishing %p\n", result );
                result->finished = true;
                if ( i_result->_query_result != NULL ) {
                        kuzu_query_result_destroy( i_result );
                }

                if ( RTEST(result->previous_result) ) {
                        related_res = result->previous_result;
                        result->previous_result = Qnil;
                        rb_funcall( related_res, rb_intern("finish"), 0 );
                }
                if ( RTEST(result->next_result) ) {
                        related_res = result->next_result;
                        result->next_result = Qnil;
                        rb_funcall( related_res, rb_intern("finish"), 0 );
                }
        }

        return Qtrue;
}
finished? → true or false

Returns true if the receiver has been finished.

static VALUE
rkuzu_result_finished_p( VALUE self )
{
        rkuzu_query_result *result = CHECK_RESULT( self );
        if ( result->finished ) {
                return Qtrue;
        } else {
                return Qfalse;
        }
}
get_column_names

Returns the names of the columns of the results as an Array of Strings.

static VALUE
rkuzu_result_get_column_names( VALUE self )
{
        rkuzu_query_result *result = rkuzu_get_result( self );
        uint64_t col_count = kuzu_query_result_get_num_columns( &result->result );
        char *name;
        VALUE rval = rb_ary_new();

        for ( uint64_t i = 0 ; i < col_count ; i++ ) {
                if ( kuzu_query_result_get_column_name(&result->result, i, &name) != KuzuSuccess ) {
                        rb_raise( rkuzu_eError, "couldn't fetch name of column %lu", i );
                }
                rb_ary_push( rval, rb_str_new2(name) );
        }

        return rval;
}
get_next_values

Returns the next tuple of the query result values if there is one, otherwise returns nil.

static VALUE
rkuzu_result_get_next_values( VALUE self )
{
        rkuzu_query_result *result = rkuzu_get_result( self );
        kuzu_flat_tuple tuple;
        kuzu_logical_type column_type;
        kuzu_value column_value;
        uint64_t column_count = kuzu_query_result_get_num_columns( &result->result );
        VALUE current_value = Qnil,
              rval = rb_ary_new();

        if ( !kuzu_query_result_has_next(&result->result) ) {
                return Qnil;
        }

        if ( kuzu_query_result_get_next(&result->result, &tuple) != KuzuSuccess ) {
                char *err_detail = kuzu_query_result_get_error_message( &result->result );
                char errmsg[ 4096 ] = "\0";

                snprintf( errmsg, 4096, "Could not fetch next tuple: %s.", err_detail );

                kuzu_destroy_string( err_detail );

                rb_raise( rkuzu_eQueryError, "%s", errmsg );
        }

        for ( uint64_t i = 0 ; i < column_count ; i++ ) {
                kuzu_query_result_get_column_data_type( &result->result, i, &column_type );
                kuzu_flat_tuple_get_value( &tuple, i, &column_value );

                current_value = rkuzu_convert_logical_kuzu_value_to_ruby( &column_type, &column_value );
                rb_ary_push( rval, current_value );
        }

        kuzu_flat_tuple_destroy( &tuple );

        return rval;
}
has_next? → true or false

Returns true if we have not consumed all tuples in the query result, false otherwise.

static VALUE
rkuzu_result_has_next_p( VALUE self )
{
        rkuzu_query_result *result = rkuzu_get_result( self );

        if ( kuzu_query_result_has_next(&result->result) ) {
                return Qtrue;
        } else {
                return Qfalse;
        }
}
has_next_set? → true or false

Returns true if there was more than one result set in the results, and the current set is not the last one. You can call next_set to move on to the next result set.

static VALUE
rkuzu_result_has_next_set_p( VALUE self )
{
        rkuzu_query_result *result = rkuzu_get_result( self );

        if ( kuzu_query_result_has_next_query_result(&result->result) ) {
                return Qtrue;
        } else {
                return Qfalse;
        }
}
inspect()

Return a string representation of the receiver suitable for debugging.

# File lib/kuzu/result.rb, line 150
def inspect
        if self.finished?
                details = " (finished)"
        else
                details = " success: %p (%d tuples of %d columns)" % [
                        self.success?,
                        self.num_tuples,
                        self.num_columns,
                ]
        end

        default = super
        return default.sub( />/, details + '>' )
end
next()

Get the next tuple of the result as a Hash.

# File lib/kuzu/result.rb, line 102
def next
        values = self.get_next_values or return nil
        pairs = self.column_names.zip( values )
        return Hash[ pairs ]
end
next_set()

Return the next result set after this one as a Kuzu::Result, or nilif there is no next set.

# File lib/kuzu/result.rb, line 133
def next_set
        return nil unless self.has_next_set?
        return self.class.from_next_set( self )
end
num_columns → integer

Returns the number of columns in the query result.

static VALUE
rkuzu_result_num_columns( VALUE self )
{
        rkuzu_query_result *result = rkuzu_get_result( self );
        const uint64_t count = kuzu_query_result_get_num_columns( &result->result );

        return ULONG2NUM( count );
}
num_tuples → integer

Returns the number of tuples in the query result.

static VALUE
rkuzu_result_num_tuples( VALUE self )
{
        rkuzu_query_result *result = rkuzu_get_result( self );
        const uint64_t count = kuzu_query_result_get_num_tuples( &result->result );

        return ULONG2NUM( count );
}
query_summary()

Return a Kuzu::QuerySummary for the query that generated the Result.

# File lib/kuzu/result.rb, line 96
def query_summary
        return Kuzu::QuerySummary.from_result( self )
end
reset_iterator

Resets the iterator of the query result to the beginning.

static VALUE
rkuzu_result_reset_iterator( VALUE self )
{
        rkuzu_query_result *result = rkuzu_get_result( self );
        kuzu_query_result_reset_iterator( &result->result );
        return Qtrue;
}
success? → true or false

Returns true if the query is executed successful, false otherwise.

static VALUE
rkuzu_result_success_p( VALUE self )
{
        rkuzu_query_result *result = rkuzu_get_result( self );

        if ( kuzu_query_result_is_success(&result->result) ) {
                return Qtrue;
        } else {
                return Qfalse;
        }
}
to_s → string

Returns the result as a String.

static VALUE
rkuzu_result_to_s( VALUE self )
{
        rkuzu_query_result *result = rkuzu_get_result( self );
        char *string = kuzu_query_result_to_string( &result->result );

        VALUE rval = rb_str_new2( string );
        kuzu_destroy_string( string );

        return rval;
}
tuples()

Return the tuples from the current result set. This method is memoized for efficiency.

# File lib/kuzu/result.rb, line 120
def tuples
        return @_tuples ||= self.to_a
end

Protected Instance Methods

next_set_enum()

Return an Enumerator that yields a Result for each set.

# File lib/kuzu/result.rb, line 184
def next_set_enum
        self.log.debug "Fetching a result set Enumerator"
        result = self
        return Enumerator.new do |yielder|
                while result
                        yielder.yield( result )
                        result = result.next_set
                end
        end
end
tuple_enum()

Return an Enumerator that yields result tuples as Hashes.

# File lib/kuzu/result.rb, line 171
def tuple_enum
        self.log.debug "Fetching a tuple Enumerator"
        return Enumerator.new do |yielder|
                self.reset_iterator
                while self.has_next?
                        tuple = self.next
                        yielder.yield( tuple )
                end
        end
end