duckdb 0.0.12 → 0.2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test_on_macos.yml +2 -8
- data/.github/workflows/test_on_ubuntu.yml +28 -28
- data/.github/workflows/test_on_windows.yml +37 -0
- data/.travis.yml +6 -6
- data/CHANGELOG.md +31 -0
- data/Gemfile.lock +3 -3
- data/README.md +81 -1
- data/ext/duckdb/appender.c +315 -0
- data/ext/duckdb/appender.h +17 -0
- data/ext/duckdb/config.c +80 -0
- data/ext/duckdb/config.h +18 -0
- data/ext/duckdb/database.c +48 -2
- data/ext/duckdb/duckdb.c +12 -0
- data/ext/duckdb/extconf.rb +5 -0
- data/ext/duckdb/prepared_statement.c +17 -2
- data/ext/duckdb/result.c +23 -3
- data/ext/duckdb/ruby-duckdb.h +18 -0
- data/lib/duckdb/appender.rb +102 -0
- data/lib/duckdb/config.rb +65 -0
- data/lib/duckdb/connection.rb +29 -0
- data/lib/duckdb/database.rb +15 -2
- data/lib/duckdb/prepared_statement.rb +20 -2
- data/lib/duckdb/version.rb +1 -1
- data/lib/duckdb.rb +2 -0
- metadata +13 -6
@@ -0,0 +1,17 @@
|
|
1
|
+
#ifndef RUBY_DUCKDB_APPENDER_H
|
2
|
+
#define RUBY_DUCKDB_APPENDER_H
|
3
|
+
|
4
|
+
#ifdef HAVE_DUCKDB_APPENDER_CREATE
|
5
|
+
|
6
|
+
struct _rubyDuckDBAppender {
|
7
|
+
duckdb_appender appender;
|
8
|
+
};
|
9
|
+
|
10
|
+
typedef struct _rubyDuckDBAppender rubyDuckDBAppender;
|
11
|
+
|
12
|
+
void init_duckdb_appender(void);
|
13
|
+
|
14
|
+
#endif
|
15
|
+
|
16
|
+
#endif
|
17
|
+
|
data/ext/duckdb/config.c
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
#include "ruby-duckdb.h"
|
2
|
+
|
3
|
+
#ifdef HAVE_DUCKDB_CREATE_CONFIG
|
4
|
+
|
5
|
+
VALUE cDuckDBConfig;
|
6
|
+
|
7
|
+
static void deallocate(void *);
|
8
|
+
static VALUE allocate(VALUE klass);
|
9
|
+
static VALUE config_s_size(VALUE klass);
|
10
|
+
static VALUE config_s_get_config_flag(VALUE self, VALUE value);
|
11
|
+
static VALUE config_initialize(VALUE self);
|
12
|
+
static VALUE config_set_config(VALUE self, VALUE key, VALUE value);
|
13
|
+
|
14
|
+
static void deallocate(void * ctx)
|
15
|
+
{
|
16
|
+
rubyDuckDBConfig *p = (rubyDuckDBConfig *)ctx;
|
17
|
+
|
18
|
+
duckdb_destroy_config(&(p->config));
|
19
|
+
xfree(p);
|
20
|
+
}
|
21
|
+
|
22
|
+
static VALUE allocate(VALUE klass)
|
23
|
+
{
|
24
|
+
rubyDuckDBConfig *ctx = xcalloc((size_t)1, sizeof(rubyDuckDBConfig));
|
25
|
+
return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
|
26
|
+
}
|
27
|
+
|
28
|
+
static VALUE config_initialize(VALUE self) {
|
29
|
+
rubyDuckDBConfig *ctx;
|
30
|
+
|
31
|
+
Data_Get_Struct(self, rubyDuckDBConfig, ctx);
|
32
|
+
|
33
|
+
if (duckdb_create_config(&(ctx->config)) == DuckDBError) {
|
34
|
+
rb_raise(eDuckDBError, "failed to create config");
|
35
|
+
}
|
36
|
+
return self;
|
37
|
+
}
|
38
|
+
|
39
|
+
static VALUE config_s_size(VALUE self) {
|
40
|
+
return INT2NUM(duckdb_config_count());
|
41
|
+
}
|
42
|
+
|
43
|
+
static VALUE config_s_get_config_flag(VALUE klass, VALUE value) {
|
44
|
+
const char *pkey;
|
45
|
+
const char *pdesc;
|
46
|
+
|
47
|
+
size_t i = NUM2INT(value);
|
48
|
+
|
49
|
+
if (duckdb_get_config_flag(i, &pkey, &pdesc) == DuckDBError) {
|
50
|
+
rb_raise(eDuckDBError, "failed to get config information of index %ld", i);
|
51
|
+
}
|
52
|
+
|
53
|
+
return rb_ary_new3(2, rb_str_new2(pkey), rb_str_new2(pdesc));
|
54
|
+
}
|
55
|
+
|
56
|
+
static VALUE config_set_config(VALUE self, VALUE key, VALUE value) {
|
57
|
+
const char *pkey = StringValuePtr(key);
|
58
|
+
const char *pval = StringValuePtr(value);
|
59
|
+
|
60
|
+
rubyDuckDBConfig *ctx;
|
61
|
+
Data_Get_Struct(self, rubyDuckDBConfig, ctx);
|
62
|
+
|
63
|
+
if (duckdb_set_config(ctx->config, pkey, pval) == DuckDBError) {
|
64
|
+
rb_raise(eDuckDBError, "failed to set config %s => %s", pkey, pval);
|
65
|
+
}
|
66
|
+
return self;
|
67
|
+
}
|
68
|
+
|
69
|
+
void init_duckdb_config(void) {
|
70
|
+
cDuckDBConfig = rb_define_class_under(mDuckDB, "Config", rb_cObject);
|
71
|
+
rb_define_alloc_func(cDuckDBConfig, allocate);
|
72
|
+
rb_define_singleton_method(cDuckDBConfig, "size", config_s_size, 0);
|
73
|
+
rb_define_singleton_method(cDuckDBConfig, "get_config_flag", config_s_get_config_flag, 1);
|
74
|
+
|
75
|
+
rb_define_method(cDuckDBConfig, "initialize", config_initialize, 0);
|
76
|
+
rb_define_method(cDuckDBConfig, "set_config", config_set_config, 2);
|
77
|
+
}
|
78
|
+
|
79
|
+
#endif
|
80
|
+
|
data/ext/duckdb/config.h
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#ifndef RUBY_DUCKDB_CONFIG_H
|
2
|
+
#define RUBY_DUCKDB_CONFIG_H
|
3
|
+
|
4
|
+
#ifdef HAVE_DUCKDB_CREATE_CONFIG
|
5
|
+
|
6
|
+
struct _rubyDuckDBConfig {
|
7
|
+
duckdb_config config;
|
8
|
+
};
|
9
|
+
|
10
|
+
typedef struct _rubyDuckDBConfig rubyDuckDBConfig;
|
11
|
+
|
12
|
+
void init_duckdb_config(void);
|
13
|
+
|
14
|
+
#endif
|
15
|
+
|
16
|
+
#endif
|
17
|
+
|
18
|
+
|
data/ext/duckdb/database.c
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
VALUE cDuckDBDatabase;
|
4
4
|
|
5
|
+
static void close_database(rubyDuckDB *p);
|
6
|
+
static void deallocate(void * ctx);
|
7
|
+
static VALUE allocate(VALUE klass);
|
8
|
+
static VALUE duckdb_database_s_open(int argc, VALUE *argv, VALUE cDuckDBDatabase);
|
9
|
+
static VALUE duckdb_database_s_open_ext(int argc, VALUE *argv, VALUE cDuckDBDatabase);
|
10
|
+
|
5
11
|
static void close_database(rubyDuckDB *p)
|
6
12
|
{
|
7
13
|
duckdb_close(&(p->db));
|
@@ -25,6 +31,7 @@ static VALUE duckdb_database_s_open(int argc, VALUE *argv, VALUE cDuckDBDatabase
|
|
25
31
|
{
|
26
32
|
rubyDuckDB *ctx;
|
27
33
|
VALUE obj;
|
34
|
+
|
28
35
|
char *pfile = NULL;
|
29
36
|
VALUE file = Qnil;
|
30
37
|
|
@@ -36,13 +43,49 @@ static VALUE duckdb_database_s_open(int argc, VALUE *argv, VALUE cDuckDBDatabase
|
|
36
43
|
|
37
44
|
obj = allocate(cDuckDBDatabase);
|
38
45
|
Data_Get_Struct(obj, rubyDuckDB, ctx);
|
39
|
-
if (duckdb_open(pfile, &(ctx->db)) == DuckDBError)
|
40
|
-
{
|
46
|
+
if (duckdb_open(pfile, &(ctx->db)) == DuckDBError) {
|
41
47
|
rb_raise(eDuckDBError, "Failed to open database"); /* FIXME */
|
42
48
|
}
|
43
49
|
return obj;
|
44
50
|
}
|
45
51
|
|
52
|
+
#ifdef HAVE_DUCKDB_OPEN_EXT
|
53
|
+
static VALUE duckdb_database_s_open_ext(int argc, VALUE *argv, VALUE cDuckDBDatabase)
|
54
|
+
{
|
55
|
+
rubyDuckDB *ctx;
|
56
|
+
VALUE obj;
|
57
|
+
rubyDuckDBConfig *ctx_config;
|
58
|
+
char *perror;
|
59
|
+
|
60
|
+
char *pfile = NULL;
|
61
|
+
VALUE file = Qnil;
|
62
|
+
VALUE config = Qnil;
|
63
|
+
|
64
|
+
rb_scan_args(argc, argv, "02", &file, &config);
|
65
|
+
|
66
|
+
if (!NIL_P(file)) {
|
67
|
+
pfile = StringValuePtr(file);
|
68
|
+
}
|
69
|
+
|
70
|
+
obj = allocate(cDuckDBDatabase);
|
71
|
+
Data_Get_Struct(obj, rubyDuckDB, ctx);
|
72
|
+
if (!NIL_P(config)) {
|
73
|
+
if (!rb_obj_is_kind_of(config, cDuckDBConfig)) {
|
74
|
+
rb_raise(rb_eTypeError, "The second argument must be DuckDB::Config object.");
|
75
|
+
}
|
76
|
+
Data_Get_Struct(config, rubyDuckDBConfig, ctx_config);
|
77
|
+
if (duckdb_open_ext(pfile, &(ctx->db), ctx_config->config, &perror) == DuckDBError) {
|
78
|
+
rb_raise(eDuckDBError, "Failed to open database %s", perror);
|
79
|
+
}
|
80
|
+
} else {
|
81
|
+
if (duckdb_open(pfile, &(ctx->db)) == DuckDBError) {
|
82
|
+
rb_raise(eDuckDBError, "Failed to open database"); /* FIXME */
|
83
|
+
}
|
84
|
+
}
|
85
|
+
return obj;
|
86
|
+
}
|
87
|
+
#endif /* HAVE_DUCKDB_OPEN_EXT */
|
88
|
+
|
46
89
|
static VALUE duckdb_database_connect(VALUE self)
|
47
90
|
{
|
48
91
|
return create_connection(self);
|
@@ -67,6 +110,9 @@ void init_duckdb_database(void)
|
|
67
110
|
cDuckDBDatabase = rb_define_class_under(mDuckDB, "Database", rb_cObject);
|
68
111
|
rb_define_alloc_func(cDuckDBDatabase, allocate);
|
69
112
|
rb_define_singleton_method(cDuckDBDatabase, "_open", duckdb_database_s_open, -1);
|
113
|
+
#ifdef HAVE_DUCKDB_OPEN_EXT
|
114
|
+
rb_define_singleton_method(cDuckDBDatabase, "_open_ext", duckdb_database_s_open_ext, -1);
|
115
|
+
#endif
|
70
116
|
rb_define_private_method(cDuckDBDatabase, "_connect", duckdb_database_connect, 0);
|
71
117
|
rb_define_method(cDuckDBDatabase, "close", duckdb_database_close, 0);
|
72
118
|
}
|
data/ext/duckdb/duckdb.c
CHANGED
@@ -18,4 +18,16 @@ Init_duckdb_native(void)
|
|
18
18
|
init_duckdb_blob();
|
19
19
|
|
20
20
|
#endif /* HAVE_DUCKDB_VALUE_BLOB */
|
21
|
+
|
22
|
+
#ifdef HAVE_DUCKDB_APPENDER_CREATE
|
23
|
+
|
24
|
+
init_duckdb_appender();
|
25
|
+
|
26
|
+
#endif /* HAVE_DUCKDB_APPENDER_CREATE */
|
27
|
+
|
28
|
+
#ifdef HAVE_DUCKDB_CREATE_CONFIG
|
29
|
+
|
30
|
+
init_duckdb_config();
|
31
|
+
|
32
|
+
#endif /* HAVE_DUCKDB_CREATE_CONFIG */
|
21
33
|
}
|
data/ext/duckdb/extconf.rb
CHANGED
@@ -3,5 +3,10 @@ require 'mkmf'
|
|
3
3
|
dir_config('duckdb')
|
4
4
|
if have_library('duckdb')
|
5
5
|
have_func('duckdb_value_blob', 'duckdb.h')
|
6
|
+
have_func('duckdb_bind_blob', 'duckdb.h')
|
7
|
+
have_func('duckdb_appender_create', 'duckdb.h')
|
8
|
+
have_func('duckdb_free', 'duckdb.h')
|
9
|
+
have_func('duckdb_create_config', 'duckdb.h')
|
10
|
+
have_func('duckdb_open_ext', 'duckdb.h')
|
6
11
|
create_makefile('duckdb/duckdb_native')
|
7
12
|
end
|
@@ -70,7 +70,7 @@ static idx_t check_index(VALUE vidx)
|
|
70
70
|
return idx;
|
71
71
|
}
|
72
72
|
|
73
|
-
static VALUE
|
73
|
+
static VALUE duckdb_prepared_statement_bind_bool(VALUE self, VALUE vidx, VALUE val)
|
74
74
|
{
|
75
75
|
rubyDuckDBPreparedStatement *ctx;
|
76
76
|
idx_t idx = check_index(vidx);
|
@@ -86,6 +86,20 @@ static VALUE duckdb_prepared_statement_bind_boolean(VALUE self, VALUE vidx, VALU
|
|
86
86
|
return self;
|
87
87
|
}
|
88
88
|
|
89
|
+
static VALUE duckdb_prepared_statement_bind_int8(VALUE self, VALUE vidx, VALUE val)
|
90
|
+
{
|
91
|
+
rubyDuckDBPreparedStatement *ctx;
|
92
|
+
idx_t idx = check_index(vidx);
|
93
|
+
int8_t i8val = (int8_t)NUM2INT(val);
|
94
|
+
|
95
|
+
Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
|
96
|
+
|
97
|
+
if (duckdb_bind_int8(ctx->prepared_statement, idx, i8val) == DuckDBError) {
|
98
|
+
rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
|
99
|
+
}
|
100
|
+
return self;
|
101
|
+
}
|
102
|
+
|
89
103
|
static VALUE duckdb_prepared_statement_bind_int16(VALUE self, VALUE vidx, VALUE val)
|
90
104
|
{
|
91
105
|
rubyDuckDBPreparedStatement *ctx;
|
@@ -203,7 +217,8 @@ void init_duckdb_prepared_statement(void)
|
|
203
217
|
rb_define_method(cDuckDBPreparedStatement, "initialize", duckdb_prepared_statement_initialize, 2);
|
204
218
|
rb_define_method(cDuckDBPreparedStatement, "execute", duckdb_prepared_statement_execute, 0);
|
205
219
|
rb_define_method(cDuckDBPreparedStatement, "nparams", duckdb_prepared_statement_nparams, 0);
|
206
|
-
rb_define_method(cDuckDBPreparedStatement, "
|
220
|
+
rb_define_method(cDuckDBPreparedStatement, "bind_bool", duckdb_prepared_statement_bind_bool, 2);
|
221
|
+
rb_define_method(cDuckDBPreparedStatement, "bind_int8", duckdb_prepared_statement_bind_int8, 2);
|
207
222
|
rb_define_method(cDuckDBPreparedStatement, "bind_int16", duckdb_prepared_statement_bind_int16, 2);
|
208
223
|
rb_define_method(cDuckDBPreparedStatement, "bind_int32", duckdb_prepared_statement_bind_int32, 2);
|
209
224
|
rb_define_method(cDuckDBPreparedStatement, "bind_int64", duckdb_prepared_statement_bind_int64, 2);
|
data/ext/duckdb/result.c
CHANGED
@@ -55,8 +55,19 @@ static VALUE to_ruby_obj_double(duckdb_result *result, idx_t col_idx, idx_t row_
|
|
55
55
|
#ifdef HAVE_DUCKDB_VALUE_BLOB
|
56
56
|
static VALUE to_ruby_obj_string_from_blob(duckdb_result *result, idx_t col_idx, idx_t row_idx)
|
57
57
|
{
|
58
|
+
VALUE str;
|
58
59
|
duckdb_blob bval = duckdb_value_blob(result, col_idx, row_idx);
|
59
|
-
|
60
|
+
str = rb_str_new(bval.data, bval.size);
|
61
|
+
|
62
|
+
if (bval.data) {
|
63
|
+
#ifdef HAVE_DUCKDB_FREE
|
64
|
+
duckdb_free(bval.data);
|
65
|
+
#else
|
66
|
+
free(bval.data);
|
67
|
+
#endif
|
68
|
+
}
|
69
|
+
|
70
|
+
return str;
|
60
71
|
}
|
61
72
|
#endif /* HAVE_DUCKDB_VALUE_BLOB */
|
62
73
|
|
@@ -86,8 +97,17 @@ static VALUE to_ruby_obj(duckdb_result *result, idx_t col_idx, idx_t row_idx)
|
|
86
97
|
#endif /* HAVE_DUCKDB_VALUE_BLOB */
|
87
98
|
default:
|
88
99
|
p = duckdb_value_varchar(result, col_idx, row_idx);
|
89
|
-
|
90
|
-
|
100
|
+
if (p) {
|
101
|
+
obj = rb_str_new2(p);
|
102
|
+
#ifdef HAVE_DUCKDB_FREE
|
103
|
+
duckdb_free(p);
|
104
|
+
#else
|
105
|
+
free(p);
|
106
|
+
#endif /* HAVE_DUCKDB_FREE */
|
107
|
+
if (result->columns[col_idx].type == DUCKDB_TYPE_HUGEINT) {
|
108
|
+
obj = rb_funcall(obj, rb_intern("to_i"), 0);
|
109
|
+
}
|
110
|
+
}
|
91
111
|
}
|
92
112
|
return obj;
|
93
113
|
}
|
data/ext/duckdb/ruby-duckdb.h
CHANGED
@@ -15,6 +15,18 @@
|
|
15
15
|
|
16
16
|
#endif /* HAVE_DUCKDB_VALUE_BLOB */
|
17
17
|
|
18
|
+
#ifdef HAVE_DUCKDB_APPENDER_CREATE
|
19
|
+
|
20
|
+
#include "./appender.h"
|
21
|
+
|
22
|
+
#endif /* HAVE_DUCKDB_APPENDER_CREATE */
|
23
|
+
|
24
|
+
#ifdef HAVE_DUCKDB_CREATE_CONFIG
|
25
|
+
|
26
|
+
#include "./config.h"
|
27
|
+
|
28
|
+
#endif /* HAVE_DUCKDB_CREATE_CONFIG */
|
29
|
+
|
18
30
|
extern VALUE mDuckDB;
|
19
31
|
extern VALUE cDuckDBDatabase;
|
20
32
|
extern VALUE cDuckDBConnection;
|
@@ -25,6 +37,12 @@ extern VALUE cDuckDBBlob;
|
|
25
37
|
|
26
38
|
#endif /* HAVE_DUCKDB_VALUE_BLOB */
|
27
39
|
|
40
|
+
#ifdef HAVE_DUCKDB_CREATE_CONFIG
|
41
|
+
|
42
|
+
extern VALUE cDuckDBConfig;
|
43
|
+
|
44
|
+
#endif /* HAVE_DUCKDB_CREATE_CONFIG */
|
45
|
+
|
28
46
|
extern VALUE eDuckDBError;
|
29
47
|
|
30
48
|
#endif
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module DuckDB
|
4
|
+
if defined?(DuckDB::Appender)
|
5
|
+
# The DuckDB::Appender encapsulates DuckDB Appender.
|
6
|
+
#
|
7
|
+
# require 'duckdb'
|
8
|
+
# db = DuckDB::Database.open
|
9
|
+
# con = db.connect
|
10
|
+
# con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
|
11
|
+
# appender = con.appender('users')
|
12
|
+
# appender.append_row(1, 'Alice')
|
13
|
+
#
|
14
|
+
class Appender
|
15
|
+
RANGE_INT16 = -32_768..32_767
|
16
|
+
RANGE_INT32 = -2_147_483_648..2_147_483_647
|
17
|
+
RANGE_INT64 = -9_223_372_036_854_775_808..9_223_372_036_854_775_807
|
18
|
+
|
19
|
+
def append_hugeint(value)
|
20
|
+
case value
|
21
|
+
when Integer
|
22
|
+
append_varchar(value.to_s)
|
23
|
+
else
|
24
|
+
rb_raise(ArgumentError, "2nd argument `#{value}` must be Integer.")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# appends value.
|
30
|
+
#
|
31
|
+
# require 'duckdb'
|
32
|
+
# db = DuckDB::Database.open
|
33
|
+
# con = db.connect
|
34
|
+
# con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
|
35
|
+
# appender = con.appender('users')
|
36
|
+
# appender.begin_row
|
37
|
+
# appender.append(1)
|
38
|
+
# appender.append('Alice')
|
39
|
+
# appender.end_row
|
40
|
+
#
|
41
|
+
def append(value)
|
42
|
+
case value
|
43
|
+
when NilClass
|
44
|
+
append_null
|
45
|
+
when Float
|
46
|
+
append_double(value)
|
47
|
+
when Integer
|
48
|
+
case value
|
49
|
+
when RANGE_INT16
|
50
|
+
append_int16(value)
|
51
|
+
when RANGE_INT32
|
52
|
+
append_int32(value)
|
53
|
+
when RANGE_INT64
|
54
|
+
append_int64(value)
|
55
|
+
else
|
56
|
+
append_hugeint(value)
|
57
|
+
end
|
58
|
+
when String
|
59
|
+
if defined?(DuckDB::Blob)
|
60
|
+
blob?(value) ? append_blob(value) : append_varchar(value)
|
61
|
+
else
|
62
|
+
append_varchar(value)
|
63
|
+
end
|
64
|
+
when TrueClass, FalseClass
|
65
|
+
append_bool(value)
|
66
|
+
when Time
|
67
|
+
append_varchar(value.strftime('%Y-%m-%d %H:%M:%S.%N'))
|
68
|
+
when Date
|
69
|
+
append_varchar(value.strftime('%Y-%m-%d'))
|
70
|
+
else
|
71
|
+
rb_raise(DuckDB::Error, "not supported type #{value} (value.class)")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# append a row.
|
77
|
+
#
|
78
|
+
# appender.append_row(1, 'Alice')
|
79
|
+
#
|
80
|
+
# is same as:
|
81
|
+
#
|
82
|
+
# appender.begin_row
|
83
|
+
# appender.append(1)
|
84
|
+
# appender.append('Alice')
|
85
|
+
# appender.end_row
|
86
|
+
#
|
87
|
+
def append_row(*args)
|
88
|
+
begin_row
|
89
|
+
args.each do |arg|
|
90
|
+
append(arg)
|
91
|
+
end
|
92
|
+
end_row
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def blob?(value)
|
98
|
+
value.instance_of?(DuckDB::Blob) || value.encoding == Encoding::BINARY
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|