class DuckDB::Appender
The DuckDB::Appender encapsulates DuckDB Appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, name VARCHAR)') appender = con.appender('users') appender.append_row(1, 'Alice')
Public Class Methods
Source
static VALUE appender_s_create_query(VALUE klass, VALUE con, VALUE query, VALUE types, VALUE table, VALUE columns) {
rubyDuckDBConnection *ctxcon;
rubyDuckDBAppender *ctx;
char *query_str = StringValuePtr(query);
char *table_name = NULL;
const char **column_names = NULL;
idx_t column_count = 0;
duckdb_logical_type *type_array = NULL;
VALUE appender = Qnil;
if (!rb_obj_is_kind_of(con, cDuckDBConnection)) {
rb_raise(rb_eTypeError, "1st argument should be instance of DackDB::Connection");
}
if (rb_obj_is_kind_of(types, rb_cArray) == Qfalse) {
rb_raise(rb_eTypeError, "2nd argument should be an Array");
}
column_count = RARRAY_LEN(types);
type_array = ALLOCA_N(duckdb_logical_type, (size_t)column_count);
for (idx_t i = 0; i < column_count; i++) {
VALUE type_val = rb_ary_entry(types, i);
rubyDuckDBLogicalType *type_ctx = get_struct_logical_type(type_val);
type_array[i] = type_ctx->logical_type;
}
if (table != Qnil) {
table_name = StringValuePtr(table);
}
if (columns != Qnil) {
if (rb_obj_is_kind_of(columns, rb_cArray) == Qfalse) {
rb_raise(rb_eTypeError, "4th argument should be an Array or nil");
}
idx_t col_count = RARRAY_LEN(columns);
column_names = ALLOCA_N(const char *, (size_t)col_count);
for (idx_t i = 0; i < col_count; i++) {
VALUE col_name_val = rb_ary_entry(columns, i);
column_names[i] = StringValuePtr(col_name_val);
}
}
ctxcon = get_struct_connection(con);
appender = allocate(klass);
TypedData_Get_Struct(appender, rubyDuckDBAppender, &appender_data_type, ctx);
if (duckdb_appender_create_query(ctxcon->con, query_str, column_count, type_array, table_name, column_names, &ctx->appender) == DuckDBError) {
rb_raise(eDuckDBError, "failed to create appender from query");
}
return appender;
}
Returns a new Appender instance created from a query.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, name VARCHAR)') query = 'INSERT OR REPLACE INTO users SELECT i, val FROM my_appended_data' types = [DuckDB::LogicalType::INTEGER, DuckDB::LogicalType::VARCHAR] appender = DuckDB::Appender.create_query(con, query, types, 'my_appended_data', %w[i val])
Source
endif
static VALUE appender_initialize(VALUE self, VALUE con, VALUE schema, VALUE table) {
rubyDuckDBConnection *ctxcon;
rubyDuckDBAppender *ctx;
char *pschema = 0;
if (!rb_obj_is_kind_of(con, cDuckDBConnection)) {
rb_raise(rb_eTypeError, "1st argument should be instance of DackDB::Connection");
}
TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
ctxcon = get_struct_connection(con);
if (schema != Qnil) {
pschema = StringValuePtr(schema);
}
if (duckdb_appender_create(ctxcon->con, pschema, StringValuePtr(table), &(ctx->appender)) == DuckDBError) {
rb_raise(eDuckDBError, "failed to create appender");
}
return self;
}
Public Instance Methods
Source
# File lib/duckdb/appender.rb, line 583 def append(value) case value when NilClass append_null when Float append_double(value) when Integer case value when RANGE_INT16 append_int16(value) when RANGE_INT32 append_int32(value) when RANGE_INT64 append_int64(value) else append_hugeint(value) end when String blob?(value) ? append_blob(value) : append_varchar(value) when TrueClass, FalseClass append_bool(value) when Time append_timestamp(value) when Date append_date(value) when DuckDB::Interval append_interval(value) else raise(DuckDB::Error, "not supported type #{value} (#{value.class})") end end
appends value.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, name VARCHAR)') appender = con.appender('users') appender.append(1) appender.append('Alice') appender.end_row
Source
# File lib/duckdb/appender.rb, line 387 def append_blob(value) return self if _append_blob(value) raise_appender_error('failed to append_blob') end
Appends a varchar value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE values (value BLOB)') appender = con.appender('values') appender .append('\0\1\2\3\4\5'.encode(Encoding::BINARY)) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 118 def append_bool(value) return self if _append_bool(value) raise_appender_error('failed to append_bool') end
Appends a boolean value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, active BOOLEAN)') appender = con.appender('users') appender .append_int32(1) .append_bool(true) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 495 def append_date(value) date = _parse_date(value) return self if _append_date(date.year, date.month, date.day) raise_appender_error('failed to append_date') end
Appends a date value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE dates (date_value DATE)') appender = con.appender('dates') appender.append_date(Date.today) # or # appender.append_date(Time.now) # appender.append_date('2021-10-10') appender.end_row appender.flush
Source
# File lib/duckdb/appender.rb, line 429 def append_default return self if _append_default raise_appender_error('failed to append_default') end
Appends a default value to the current row in the appender. If the column does not have a default value, this method appends a NULL value.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE values (value INTEGER DEFAULT 1)') appender = con.appender('values') appender .append_default .end_row .flush
Source
# File lib/duckdb/appender.rb, line 327 def append_double(value) return self if _append_double(value) raise_appender_error('failed to append_double') end
Appends a double value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE numbers (num DOUBLE)') appender = con.appender('numbers') appender .append_double(1.23) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 307 def append_float(value) return self if _append_float(value) raise_appender_error('failed to append_float') end
Appends a float value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE numbers (num FLOAT)') appender = con.appender('numbers') appender .append_float(1.23) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 449 def append_hugeint(value) lower, upper = integer_to_hugeint(value) return self if _append_hugeint(lower, upper) raise_appender_error('failed to append_hugeint') end
Appends a huge int value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE numbers (num HUGEINT)') appender = con.appender('numbers') appender .append_hugeint(-170_141_183_460_469_231_731_687_303_715_884_105_727) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 161 def append_int16(value) return self if _append_int16(value) raise_appender_error('failed to append_int16') end
Appends an int16(SMALLINT) value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, age SMALLINT)') appender = con.appender('users') appender .append_int32(1) .append_int16(20) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 182 def append_int32(value) return self if _append_int32(value) raise_appender_error('failed to append_int32') end
Appends an int32(INTEGER) value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, age INTEGER)') appender = con.appender('users') appender .append_int32(1) .append_int32(20) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 203 def append_int64(value) return self if _append_int64(value) raise_appender_error('failed to append_int64') end
Appends an int64(BIGINT) value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, age BIGINT)') appender = con.appender('users') appender .append_int32(1) .append_int64(20) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 140 def append_int8(value) return self if _append_int8(value) raise_appender_error('failed to append_int8') end
Appends an int8(TINYINT) value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, age TINYINT)') appender = con.appender('users') appender .append_int32(1) .append_int8(20) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 565 def append_interval(value) value = Interval.to_interval(value) return self if _append_interval(value.interval_months, value.interval_days, value.interval_micros) raise_appender_error('failed to append_interval') end
Appends an interval value to the current row in the appender. The argument must be ISO8601 duration format.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE intervals (interval_value INTERVAL)') appender = con.appender('intervals') appender .append_interval('P1Y2D') # => append 1 year 2 days interval. .end_row .flush
Source
# File lib/duckdb/appender.rb, line 407 def append_null return self if _append_null raise_appender_error('failed to append_null') end
Appends a NULL value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE values (value INTEGER)') appender = con.appender('values') appender .append_null .end_row .flush
Source
# File lib/duckdb/appender.rb, line 624 def append_row(*args) args.each do |arg| append(arg) end end_row end
append a row.
appender.append_row(1, 'Alice')
is same as:
appender.append(2) appender.append('Alice') appender.end_row
Source
# File lib/duckdb/appender.rb, line 518 def append_time(value) time = _parse_time(value) return self if _append_time(time.hour, time.min, time.sec, time.usec) raise_appender_error('failed to append_time') end
Appends a time value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE times (time_value TIME)') appender = con.appender('times') appender.append_time(Time.now) # or # appender.append_time('01:01:01') appender.end_row appender.flush
Source
# File lib/duckdb/appender.rb, line 542 def append_timestamp(value) time = to_time(value) return self if _append_timestamp(time.year, time.month, time.day, time.hour, time.min, time.sec, time.nsec / 1000) raise_appender_error('failed to append_timestamp') end
Appends a timestamp value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE timestamps (timestamp_value TIMESTAMP)') appender = con.appender('timestamps') appender.append_time(Time.now) # or # appender.append_time(Date.today) # appender.append_time('2021-08-01 01:01:01') appender.end_row appender.flush
Source
# File lib/duckdb/appender.rb, line 471 def append_uhugeint(value) lower, upper = integer_to_hugeint(value) return self if _append_uhugeint(lower, upper) raise_appender_error('failed to append_uhugeint') end
Appends an unsigned huge int value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE numbers (num UHUGEINT)') appender = con.appender('numbers') appender .append_hugeint(340_282_366_920_938_463_463_374_607_431_768_211_455) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 245 def append_uint16(value) return self if _append_uint16(value) raise_appender_error('failed to append_uint16') end
Appends an uint16 value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, age USMALLINT)') appender = con.appender('users') appender .append_int32(1) .append_uint16(20) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 266 def append_uint32(value) return self if _append_uint32(value) raise_appender_error('failed to append_uint32') end
Appends an uint32 value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, age UINTEGER)') appender = con.appender('users') appender .append_int32(1) .append_uint32(20) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 287 def append_uint64(value) return self if _append_uint64(value) raise_appender_error('failed to append_uint64') end
Appends an uint64 value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, age UBIGINT)') appender = con.appender('users') Appender .append_int32(1) .append_uint64(20) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 224 def append_uint8(value) return self if _append_uint8(value) raise_appender_error('failed to append_uint8') end
Appends an uint8 value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, age UTINYINT)') appender = con.appender('users') appender .append_int32(1) .append_uint8(20) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 347 def append_varchar(value) return self if _append_varchar(value) raise_appender_error('failed to append_varchar') end
Appends a varchar value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE names (name VARCHAR)') appender = con.appender('names') appender .append_varchar('Alice') .end_row .flush
Source
# File lib/duckdb/appender.rb, line 367 def append_varchar_length(value, length) return self if _append_varchar_length(value, length) raise_appender_error('failed to append_varchar_length') end
Appends a varchar value to the current row in the appender.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE names (name VARCHAR)') appender = con.appender('names') appender .append_varchar_length('Alice', 5) .end_row .flush
Source
# File lib/duckdb/appender.rb, line 34 def begin_row self end
Source
# File lib/duckdb/appender.rb, line 97 def close return self if _close raise_appender_error('failed to close') end
Closes the appender by flushing all intermediate states and closing it for further appends. If flushing the data triggers a constraint violation or any other error, then all data is invalidated, and this method raises DuckDB::Error.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, name VARCHAR)') appender = con.appender('users') appender .append_int32(1) .append_varchar('Alice') .end_row .close
Source
# File lib/duckdb/appender.rb, line 51 def end_row return self if _end_row raise_appender_error('failed to end_row') end
Finish the current row of appends. After end_row is called, the next row can be appended.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, name VARCHAR)') appender = con.appender('users') appender .append_int32(1) .append_varchar('Alice') .end_row
Source
static VALUE appender_error_message(VALUE self) {
rubyDuckDBAppender *ctx;
#ifdef HAVE_DUCKDB_H_GE_V1_4_0
duckdb_error_data error_data;
#endif
const char *msg = NULL;
VALUE rb_msg = Qnil;
TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
#ifdef HAVE_DUCKDB_H_GE_V1_4_0
error_data = duckdb_appender_error_data(ctx->appender);
if (duckdb_error_data_has_error(error_data)) {
msg = duckdb_error_data_message(error_data);
rb_msg = rb_str_new2(msg);
}
duckdb_destroy_error_data(&error_data);
#else
msg = duckdb_appender_error(ctx->appender);
if (msg != NULL) {
rb_msg = rb_str_new2(msg);
}
#endif
return rb_msg;
}
Returns the error message of the appender. If there is no error, then it returns nil.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, name VARCHAR)') appender = con.appender('users') appender.error_message # => nil
Source
# File lib/duckdb/appender.rb, line 74 def flush return self if _flush raise_appender_error('failed to flush') end
Flushes the appender to the table, forcing the cache of the appender to be cleared. If flushing the data triggers a constraint violation or any other error, then all data is invalidated, and this method raises DuckDB::Error.
require 'duckdb' db = DuckDB::Database.open con = db.connect con.query('CREATE TABLE users (id INTEGER, name VARCHAR)') appender = con.appender('users') appender .append_int32(1) .append_varchar('Alice') .end_row .flush