Class: DuckDB::Appender
- Inherits:
-
Object
- Object
- DuckDB::Appender
- Includes:
- Converter
- Defined in:
- lib/duckdb/appender.rb,
ext/duckdb/appender.c
Overview
Constant Summary
Constants included from Converter
Converter::EPOCH, Converter::EPOCH_UTC, Converter::HALF_HUGEINT, Converter::HALF_HUGEINT_BIT, Converter::LOWER_HUGEINT_MASK, Converter::RANGE_HUGEINT, Converter::RANGE_INT16, Converter::RANGE_INT32, Converter::RANGE_INT64, Converter::RANGE_INT8, Converter::RANGE_UHUGEINT, Converter::RANGE_UINT16, Converter::RANGE_UINT32, Converter::RANGE_UINT64, Converter::RANGE_UINT8
Class Method Summary collapse
-
.DuckDB::Appender.create_query ⇒ DuckDB::Appender
(also: from_query)
Returns a new Appender instance created from a query.
Instance Method Summary collapse
-
#append(value) ⇒ Object
appends value.
-
#append_blob(value) ⇒ Object
call-seq: appender.append_blob(val) -> self.
-
#append_bool(value) ⇒ Object
call-seq: appender.append_bool(val) -> self.
-
#append_data_chunk(chunk) ⇒ Object
call-seq: appender.append_data_chunk(chunk) -> self.
-
#append_date(value) ⇒ Object
call-seq: appender.append_date(val) -> self.
-
#append_default ⇒ Object
call-seq: appender.append_default -> self.
-
#append_double(value) ⇒ Object
call-seq: appender.append_double(val) -> self.
-
#append_float(value) ⇒ Object
call-seq: appender.append_float(val) -> self.
-
#append_hugeint(value) ⇒ Object
call-seq: appender.append_hugeint(val) -> self.
-
#append_int16(value) ⇒ Object
call-seq: appender.append_int16(val) -> self.
-
#append_int32(value) ⇒ Object
call-seq: appender.append_int32(val) -> self.
-
#append_int64(value) ⇒ Object
call-seq: appender.append_int64(val) -> self.
-
#append_int8(value) ⇒ Object
call-seq: appender.append_int8(val) -> self.
-
#append_interval(value) ⇒ Object
call-seq: appender.append_interval(val) -> self.
-
#append_null ⇒ Object
call-seq: appender.append_null -> self.
-
#append_row(*args) ⇒ Object
append a row.
-
#append_time(value) ⇒ Object
call-seq: appender.append_time(val) -> self.
-
#append_timestamp(value) ⇒ Object
call-seq: appender.append_timestamp(val) -> self.
-
#append_uhugeint(value) ⇒ Object
call-seq: appender.append_uhugeint(val) -> self.
-
#append_uint16(value) ⇒ Object
call-seq: appender.append_uint16(val) -> self.
-
#append_uint32(value) ⇒ Object
call-seq: appender.append_uint32(val) -> self.
-
#append_uint64(value) ⇒ Object
call-seq: appender.append_uint64(val) -> self.
-
#append_uint8(value) ⇒ Object
call-seq: appender.append_uint8(val) -> self.
-
#append_value(value) ⇒ Object
call-seq: appender.append_value(val) -> self.
-
#append_varchar(value) ⇒ Object
call-seq: appender.append_varchar(val) -> self.
-
#append_varchar_length(value, length) ⇒ Object
call-seq: appender.append_varchar_length(val, len) -> self.
-
#begin_row ⇒ Object
:call-seq: appender.begin_row -> self A nop method, provided for backwards compatibility reasons.
-
#close ⇒ Object
:call-seq: appender.close -> self.
-
#end_row ⇒ Object
call-seq: appender.end_row -> self.
-
#error_message ⇒ String
Returns the error message of the appender.
-
#flush ⇒ Object
:call-seq: appender.flush -> self.
- #initialize(con, schema, table) ⇒ Object constructor
Methods included from Converter
_decimal_to_unscaled, _hugeint_lower, _hugeint_upper, _parse_date, _parse_deciaml, _parse_time, _to_date, _to_decimal_from_hugeint, _to_decimal_from_value, _to_hugeint_from_vector, _to_infinity, _to_interval_from_vector, _to_query_progress, _to_time, _to_time_from_duckdb_time, _to_time_from_duckdb_time_ns, _to_time_from_duckdb_time_tz, _to_time_from_duckdb_timestamp_ms, _to_time_from_duckdb_timestamp_ns, _to_time_from_duckdb_timestamp_s, _to_time_from_duckdb_timestamp_tz, decimal_to_hugeint, default_timezone_utc?, format_timestamp_with_micro, format_timezone_offset, integer_to_hugeint
Constructor Details
#initialize(con, schema, table) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'ext/duckdb/appender.c', line 126
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;
}
|
Class Method Details
.DuckDB::Appender.create_query ⇒ DuckDB::Appender Also known as: from_query
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])
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'ext/duckdb/appender.c', line 78
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;
}
|
Instance Method Details
#append(value) ⇒ Object
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 |
# File 'lib/duckdb/appender.rb', line 609 def append(value) case value when NilClass append_null when Float append_double(value) when Integer append_integer_value(value) when String append_string_value(value) when TrueClass, FalseClass append_bool(value) when Time (value) when Date append_date(value) when DuckDB::Interval append_interval(value) else raise(DuckDB::Error, "not supported type #{value} (#{value.class})") end end |
#append_blob(value) ⇒ Object
call-seq:
appender.append_blob(val) -> self
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
380 381 382 383 384 |
# File 'lib/duckdb/appender.rb', line 380 def append_blob(value) return self if _append_blob(value) raise_appender_error('failed to append_blob') end |
#append_bool(value) ⇒ Object
call-seq:
appender.append_bool(val) -> self
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
111 112 113 114 115 |
# File 'lib/duckdb/appender.rb', line 111 def append_bool(value) return self if _append_bool(value) raise_appender_error('failed to append_bool') end |
#append_data_chunk(chunk) ⇒ Object
call-seq:
appender.append_data_chunk(chunk) -> self
590 591 592 593 594 595 596 |
# File 'lib/duckdb/appender.rb', line 590 def append_data_chunk(chunk) raise ArgumentError, "expected DuckDB::DataChunk, got #{chunk.class}" unless chunk.is_a?(DuckDB::DataChunk) return self if _append_data_chunk(chunk) raise_appender_error('failed to append_data_chunk') end |
#append_date(value) ⇒ Object
call-seq:
appender.append_date(val) -> self
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
488 489 490 491 492 493 494 |
# File 'lib/duckdb/appender.rb', line 488 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 |
#append_default ⇒ Object
call-seq:
appender.append_default -> self
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
422 423 424 425 426 |
# File 'lib/duckdb/appender.rb', line 422 def append_default return self if _append_default raise_appender_error('failed to append_default') end |
#append_double(value) ⇒ Object
320 321 322 323 324 |
# File 'lib/duckdb/appender.rb', line 320 def append_double(value) return self if _append_double(value) raise_appender_error('failed to append_double') end |
#append_float(value) ⇒ Object
300 301 302 303 304 |
# File 'lib/duckdb/appender.rb', line 300 def append_float(value) return self if _append_float(value) raise_appender_error('failed to append_float') end |
#append_hugeint(value) ⇒ Object
call-seq:
appender.append_hugeint(val) -> self
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
442 443 444 445 446 447 448 |
# File 'lib/duckdb/appender.rb', line 442 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 |
#append_int16(value) ⇒ Object
call-seq:
appender.append_int16(val) -> self
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
154 155 156 157 158 |
# File 'lib/duckdb/appender.rb', line 154 def append_int16(value) return self if _append_int16(value) raise_appender_error('failed to append_int16') end |
#append_int32(value) ⇒ Object
call-seq:
appender.append_int32(val) -> self
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
175 176 177 178 179 |
# File 'lib/duckdb/appender.rb', line 175 def append_int32(value) return self if _append_int32(value) raise_appender_error('failed to append_int32') end |
#append_int64(value) ⇒ Object
call-seq:
appender.append_int64(val) -> self
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
196 197 198 199 200 |
# File 'lib/duckdb/appender.rb', line 196 def append_int64(value) return self if _append_int64(value) raise_appender_error('failed to append_int64') end |
#append_int8(value) ⇒ Object
call-seq:
appender.append_int8(val) -> self
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
133 134 135 136 137 |
# File 'lib/duckdb/appender.rb', line 133 def append_int8(value) return self if _append_int8(value) raise_appender_error('failed to append_int8') end |
#append_interval(value) ⇒ Object
call-seq:
appender.append_interval(val) -> self
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
558 559 560 561 562 563 564 |
# File 'lib/duckdb/appender.rb', line 558 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 |
#append_null ⇒ Object
400 401 402 403 404 |
# File 'lib/duckdb/appender.rb', line 400 def append_null return self if _append_null raise_appender_error('failed to append_null') end |
#append_row(*args) ⇒ Object
append a row.
appender.append_row(1, 'Alice')
is same as:
appender.append(2)
appender.append('Alice')
appender.end_row
642 643 644 645 646 647 |
# File 'lib/duckdb/appender.rb', line 642 def append_row(*args) args.each do |arg| append(arg) end end_row end |
#append_time(value) ⇒ Object
call-seq:
appender.append_time(val) -> self
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
511 512 513 514 515 516 517 |
# File 'lib/duckdb/appender.rb', line 511 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 |
#append_timestamp(value) ⇒ Object
call-seq:
appender.append_timestamp(val) -> self
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
535 536 537 538 539 540 541 |
# File 'lib/duckdb/appender.rb', line 535 def (value) time = to_time(value) return self if (time.year, time.month, time.day, time.hour, time.min, time.sec, time.nsec / 1000) raise_appender_error('failed to append_timestamp') end |
#append_uhugeint(value) ⇒ Object
call-seq:
appender.append_uhugeint(val) -> self
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
464 465 466 467 468 469 470 |
# File 'lib/duckdb/appender.rb', line 464 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 |
#append_uint16(value) ⇒ Object
call-seq:
appender.append_uint16(val) -> self
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
238 239 240 241 242 |
# File 'lib/duckdb/appender.rb', line 238 def append_uint16(value) return self if _append_uint16(value) raise_appender_error('failed to append_uint16') end |
#append_uint32(value) ⇒ Object
call-seq:
appender.append_uint32(val) -> self
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
259 260 261 262 263 |
# File 'lib/duckdb/appender.rb', line 259 def append_uint32(value) return self if _append_uint32(value) raise_appender_error('failed to append_uint32') end |
#append_uint64(value) ⇒ Object
call-seq:
appender.append_uint64(val) -> self
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
280 281 282 283 284 |
# File 'lib/duckdb/appender.rb', line 280 def append_uint64(value) return self if _append_uint64(value) raise_appender_error('failed to append_uint64') end |
#append_uint8(value) ⇒ Object
call-seq:
appender.append_uint8(val) -> self
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
217 218 219 220 221 |
# File 'lib/duckdb/appender.rb', line 217 def append_uint8(value) return self if _append_uint8(value) raise_appender_error('failed to append_uint8') end |
#append_value(value) ⇒ Object
call-seq:
appender.append_value(val) -> self
Appends a DuckDB::Value to the current row in the appender.
require 'duckdb'
db = DuckDB::Database.open
con = db.connect
con.query('CREATE TABLE numbers (num INTEGER)')
appender = con.appender('numbers')
appender
.append_value(DuckDB::Value.create_int32(42))
.end_row
.flush
580 581 582 583 584 585 586 |
# File 'lib/duckdb/appender.rb', line 580 def append_value(value) raise ArgumentError, "expected DuckDB::Value, got #{value.class}" unless value.is_a?(DuckDB::Value) return self if _append_value(value) raise_appender_error('failed to append_value') end |
#append_varchar(value) ⇒ Object
340 341 342 343 344 |
# File 'lib/duckdb/appender.rb', line 340 def append_varchar(value) return self if _append_varchar(value) raise_appender_error('failed to append_varchar') end |
#append_varchar_length(value, length) ⇒ Object
call-seq:
appender.append_varchar_length(val, len) -> self
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
360 361 362 363 364 |
# File 'lib/duckdb/appender.rb', line 360 def append_varchar_length(value, length) return self if _append_varchar_length(value, length) raise_appender_error('failed to append_varchar_length') end |
#begin_row ⇒ Object
:call-seq:
appender.begin_row -> self
A nop method, provided for backwards compatibility reasons. Does nothing. Only ‘end_row` is required.
27 28 29 |
# File 'lib/duckdb/appender.rb', line 27 def begin_row self end |
#close ⇒ Object
:call-seq:
appender.close -> self
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
90 91 92 93 94 |
# File 'lib/duckdb/appender.rb', line 90 def close return self if _close raise_appender_error('failed to close') end |
#end_row ⇒ Object
call-seq:
appender.end_row -> self
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
44 45 46 47 48 |
# File 'lib/duckdb/appender.rb', line 44 def end_row return self if _end_row raise_appender_error('failed to end_row') end |
#error_message ⇒ String
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'ext/duckdb/appender.c', line 161
static VALUE appender_error_message(VALUE self) {
rubyDuckDBAppender *ctx;
duckdb_error_data error_data;
const char *msg = NULL;
VALUE rb_msg = Qnil;
TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
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);
return rb_msg;
}
|
#flush ⇒ Object
:call-seq:
appender.flush -> self
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
67 68 69 70 71 |
# File 'lib/duckdb/appender.rb', line 67 def flush return self if _flush raise_appender_error('failed to flush') end |