Class: DuckDB::Result

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/duckdb/result.rb,
ext/duckdb/result.c

Overview

The Result class encapsulates a execute result of DuckDB database.

The usage is as follows:

require 'duckdb'

db = DuckDB::Database.open # database in memory
con = db.connect

con.execute('CREATE TABLE users (id INTEGER, name VARCHAR(30))')

con.execute("INSERT into users VALUES(1, 'Alice')")
con.execute("INSERT into users VALUES(2, 'Bob')")
con.execute("INSERT into users VALUES(3, 'Cathy')")

result = con.execute('SELECT * from users')
result.each do |row|
  p row
end

Constant Summary collapse

TO_METHODS =
if Gem::Version.new(DuckDB::LIBRARY_VERSION) == Gem::Version.new('0.10.0')
  Hash.new(:_to_string).merge(
    1 => :_to_boolean,
    3 => :_to_smallint,
    4 => :_to_integer,
    5 => :_to_bigint,
    10 => :_to_float,
    11 => :_to_double,
    16 => :_to_hugeint_internal,
    19 => :_to_blob,
    20 => :_to_decimal_internal
  ).freeze
else
  Hash.new(:_to_string).merge(
    1 => :_to_boolean,
    3 => :_to_smallint,
    4 => :_to_integer,
    5 => :_to_bigint,
    10 => :_to_float,
    11 => :_to_double,
    16 => :_to_hugeint_internal,
    18 => :_to_blob,
    19 => :_to_decimal_internal
  ).freeze
end

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.newObject

Raises:



57
58
59
# File 'lib/duckdb/result.rb', line 57

def new
  raise DuckDB::Error, 'DuckDB::Result cannot be instantiated directly.'
end

.use_chunk_each=(val) ⇒ Object

Raises:



61
62
63
64
65
# File 'lib/duckdb/result.rb', line 61

def use_chunk_each=(val)
  raise DuckDB::Error, 'chunk_each is not available. Install duckdb >= 0.8.0 and rerun `gem install duckdb`.' unless instance_methods.include?(:chunk_each)

  @use_chunk_each = val
end

.use_chunk_each?Boolean

Returns:

  • (Boolean)


67
68
69
# File 'lib/duckdb/result.rb', line 67

def use_chunk_each?
  !!@use_chunk_each
end

Instance Method Details

#chunk_eachObject



263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'ext/duckdb/result.c', line 263

static VALUE duckdb_result_chunk_each(VALUE oDuckDBResult) {
    rubyDuckDBResult *ctx;
    idx_t col_count;
    idx_t chunk_count;
    idx_t chunk_idx;
    duckdb_data_chunk chunk;

    TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);

    col_count = duckdb_column_count(&(ctx->result));
    chunk_count = duckdb_result_chunk_count(ctx->result);

    RETURN_ENUMERATOR(oDuckDBResult, 0, 0);

    for (chunk_idx = 0; chunk_idx < chunk_count; chunk_idx++) {
        chunk = duckdb_result_get_chunk(ctx->result, chunk_idx);
        yield_rows(chunk, col_count);
        duckdb_destroy_data_chunk(&chunk);
    }
    return Qnil;
}

#column_countInteger Also known as: column_size

Returns the column size of the result.

DuckDB::Database.open do |db|
  db.connect do |con|
    r = con.query('CREATE TABLE t2 (id INT, name VARCHAR(128))')
    r = con.query("INSERT INTO t2 VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Catherine')")
    r = con.query('SELECT id FROM t2')
    r.column_count # => 1
    r = con.query('SELECT id, name FROM t2')
    r.column_count # => 2
  end
end

Returns:

  • (Integer)


198
199
200
201
202
# File 'ext/duckdb/result.c', line 198

static VALUE duckdb_result_column_count(VALUE oDuckDBResult) {
    rubyDuckDBResult *ctx;
    TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
    return LL2NUM(duckdb_column_count(&(ctx->result)));
}

#columnsDuckDB::Column[]

Returns the column class Lists.

Returns:



235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'ext/duckdb/result.c', line 235

static VALUE duckdb_result_columns(VALUE oDuckDBResult) {
    rubyDuckDBResult *ctx;
    TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);

    idx_t col_idx;
    idx_t column_count = duckdb_column_count(&(ctx->result));

    VALUE ary = rb_ary_new2(column_count);
    for(col_idx = 0; col_idx < column_count; col_idx++) {
        VALUE column = rbduckdb_create_column(oDuckDBResult, col_idx);
        rb_ary_store(ary, col_idx, column);
    }
    return ary;
}

#eachObject



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/duckdb/result.rb', line 72

def each
  if self.class.use_chunk_each?
    if streaming?
      return _chunk_stream unless block_given?

      _chunk_stream { |row| yield row }
    else
      return chunk_each unless block_given?

      chunk_each { |row| yield row }
    end
  else
    warn('this `each` behavior will be deprecated in the future. set `DuckDB::Result.use_chunk_each = true` to use new `each` behavior.')
    return to_enum { row_size } unless block_given?

    row_count.times do |row_index|
      yield row(row_index)
    end
  end
end

#enum_dictionary_values(col_index) ⇒ Object



105
106
107
108
109
110
111
# File 'lib/duckdb/result.rb', line 105

def enum_dictionary_values(col_index)
  values = []
  _enum_dictionary_size(col_index).times do |i|
    values << _enum_dictionary_value(col_index, i)
  end
  values
end

#row(row_index) ⇒ Object



93
94
95
96
97
98
99
# File 'lib/duckdb/result.rb', line 93

def row(row_index)
  row = []
  column_count.times do |col_index|
    row << (_null?(row_index, col_index) ? nil : to_value(row_index, col_index))
  end
  row
end

#row_countInteger Also known as: row_size

Returns the column size of the result.

DuckDB::Database.open do |db|
  db.connect do |con|
    r = con.query('CREATE TABLE t2 (id INT, name VARCHAR(128))')
    r = con.query("INSERT INTO t2 VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Catherine')")
    r = con.query('SELECT * FROM t2')
    r.row_count # => 3
    r = con.query('SELECT * FROM t2 where id = 1')
    r.row_count # => 1
  end
end

Returns:

  • (Integer)


222
223
224
225
226
# File 'ext/duckdb/result.c', line 222

static VALUE duckdb_result_row_count(VALUE oDuckDBResult) {
    rubyDuckDBResult *ctx;
    TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
    return LL2NUM(duckdb_row_count(&(ctx->result)));
}

#rows_changedInteger

Returns the count of rows changed.

DuckDB::Database.open do |db|
  db.connect do |con|
    r = con.query('CREATE TABLE t2 (id INT)')
    r.rows_changed # => 0
    r = con.query('INSERT INTO t2 VALUES (1), (2), (3)')
    r.rows_changed # => 3
    r = con.query('UPDATE t2 SET id = id + 1 WHERE id > 1')
    r.rows_changed # => 2
    r = con.query('DELETE FROM t2 WHERE id = 0')
    r.rows_changed # => 0
    r = con.query('DELETE FROM t2 WHERE id = 4')
    r.rows_changed # => 1
  end
end

Returns:

  • (Integer)


174
175
176
177
178
# File 'ext/duckdb/result.c', line 174

static VALUE duckdb_result_rows_changed(VALUE oDuckDBResult) {
    rubyDuckDBResult *ctx;
    TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
    return LL2NUM(duckdb_rows_changed(&(ctx->result)));
}

#streaming?Boolean

Returns true if the result is streaming, otherwise false.

Returns:

  • (Boolean)


257
258
259
260
261
# File 'ext/duckdb/result.c', line 257

static VALUE duckdb_result_streaming_p(VALUE oDuckDBResult) {
    rubyDuckDBResult *ctx;
    TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
    return duckdb_result_is_streaming(ctx->result) ? Qtrue : Qfalse;
}

#to_value(row_index, col_index) ⇒ Object



101
102
103
# File 'lib/duckdb/result.rb', line 101

def to_value(row_index, col_index)
  send(TO_METHODS[_column_type(col_index)], row_index, col_index)
end