duckdb 0.3.2.0 → 0.3.3.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 +22 -8
- data/.github/workflows/test_on_ubuntu.yml +2 -2
- data/.github/workflows/test_on_windows.yml +2 -2
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +3 -3
- data/README.md +4 -3
- data/ext/duckdb/appender.c +0 -29
- data/ext/duckdb/appender.h +0 -5
- data/ext/duckdb/column.c +73 -0
- data/ext/duckdb/column.h +14 -0
- data/ext/duckdb/duckdb.c +1 -4
- data/ext/duckdb/extconf.rb +2 -15
- data/ext/duckdb/prepared_statement.c +0 -34
- data/ext/duckdb/result.c +24 -8
- data/ext/duckdb/ruby-duckdb.h +6 -4
- data/lib/duckdb/appender.rb +211 -217
- data/lib/duckdb/column.rb +55 -0
- data/lib/duckdb/prepared_statement.rb +0 -1
- data/lib/duckdb/version.rb +1 -1
- data/lib/duckdb.rb +1 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f88e0fda10b4ddc1b18ccc7d91a2ecab498146be652604836fd0dc29f100957
|
4
|
+
data.tar.gz: d8ed6ede8914c4b28295d39889c6ebfe46f2c5c034d3fd69fdb1b5abc7bd3e59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64be83996e4cd611a89ef3169aeb9f9b918d2c8854804eeef4b536f1987e8e9d1ea7c777c64c9b2e745d236857002b3768084991d16a8d8c3e8032d00b4b4e46
|
7
|
+
data.tar.gz: 293d2c3fb7a9a920996ce671657ea2f305a7aa591bbaa1bf56f5fa44fcc2cc5dce1d6f463ba9a424eaed49afdb7d6ae477762c76ca8f5bebceb83ae28f1b565f
|
@@ -15,8 +15,8 @@ jobs:
|
|
15
15
|
runs-on: macos-latest
|
16
16
|
strategy:
|
17
17
|
matrix:
|
18
|
-
ruby: ['2.6.
|
19
|
-
duckdb: ['0.3.2', '0.3.
|
18
|
+
ruby: ['2.6.10', '2.7.6', '3.0.4', '3.1.2', 'head']
|
19
|
+
duckdb: ['0.3.2', '0.3.3']
|
20
20
|
|
21
21
|
steps:
|
22
22
|
- uses: actions/checkout@v2
|
@@ -26,17 +26,31 @@ jobs:
|
|
26
26
|
with:
|
27
27
|
ruby-version: ${{ matrix.ruby }}
|
28
28
|
|
29
|
-
- name:
|
29
|
+
- name: duckdb cache
|
30
|
+
id: duckdb-cache
|
31
|
+
uses: actions/cache@v2
|
32
|
+
with:
|
33
|
+
path: duckdb-v${{ matrix.duckdb }}
|
34
|
+
key: ${{ runner.os }}-duckdb-v${{ matrix.duckdb }}
|
35
|
+
|
36
|
+
- name: Build duckdb ${{ matrix.duckdb }}
|
30
37
|
env:
|
31
38
|
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
39
|
+
if: steps.duckdb-cache.outputs.cache-hit != 'true'
|
32
40
|
run: |
|
33
|
-
|
41
|
+
git clone -b v$DUCKDB_VERSION https://github.com/cwida/duckdb.git duckdb-tmp-v$DUCKDB_VERSION
|
42
|
+
cd duckdb-tmp-v$DUCKDB_VERSION && make && cd ..
|
43
|
+
rm -rf duckdb-v$DUCKDB_VERSION
|
44
|
+
mkdir -p duckdb-v$DUCKDB_VERSION/build/release/src duckdb-v$DUCKDB_VERSION/src
|
45
|
+
cp -rip duckdb-tmp-v$DUCKDB_VERSION/build/release/src/*.dylib duckdb-v$DUCKDB_VERSION/build/release/src
|
46
|
+
cp -rip duckdb-tmp-v$DUCKDB_VERSION/src/include duckdb-v$DUCKDB_VERSION/src/
|
34
47
|
|
35
|
-
- name:
|
48
|
+
- name: prepare duckdb header and libraries
|
49
|
+
env:
|
50
|
+
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
36
51
|
run: |
|
37
|
-
|
38
|
-
cp duckdb
|
39
|
-
cp libduckdb.dylib /usr/local/lib
|
52
|
+
cp duckdb-v$DUCKDB_VERSION/src/include/*.h /usr/local/include
|
53
|
+
cp duckdb-v$DUCKDB_VERSION/build/release/src/*.dylib /usr/local/lib
|
40
54
|
|
41
55
|
- name: Build and test with Rake with Ruby ${{ matrix.ruby }}
|
42
56
|
run: |
|
@@ -16,8 +16,8 @@ jobs:
|
|
16
16
|
runs-on: ubuntu-latest
|
17
17
|
strategy:
|
18
18
|
matrix:
|
19
|
-
ruby: ['2.6.
|
20
|
-
duckdb: ['0.3.2', '0.3.
|
19
|
+
ruby: ['2.6.10', '2.7.6', '3.0.4', '3.1.2', 'head']
|
20
|
+
duckdb: ['0.3.2', '0.3.3']
|
21
21
|
|
22
22
|
steps:
|
23
23
|
- uses: actions/checkout@v2
|
@@ -15,8 +15,8 @@ jobs:
|
|
15
15
|
runs-on: windows-latest
|
16
16
|
strategy:
|
17
17
|
matrix:
|
18
|
-
ruby: ['2.6.
|
19
|
-
duckdb: ['0.3.2', '0.3.
|
18
|
+
ruby: ['2.6.10', '2.7.6', '3.0.4', '3.1.2', 'mingw', 'head']
|
19
|
+
duckdb: ['0.3.2', '0.3.3']
|
20
20
|
|
21
21
|
steps:
|
22
22
|
- uses: actions/checkout@v2
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
duckdb (0.3.
|
4
|
+
duckdb (0.3.3.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
minitest (5.
|
9
|
+
minitest (5.15.0)
|
10
10
|
rake (13.0.6)
|
11
|
-
rake-compiler (1.
|
11
|
+
rake-compiler (1.2.0)
|
12
12
|
rake
|
13
13
|
|
14
14
|
PLATFORMS
|
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# ruby-duckdb
|
2
2
|
|
3
|
-
[](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AUbuntu)
|
4
|
-
[](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AMacOS)
|
5
|
-
[](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AWindows)
|
3
|
+
[](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AUbuntu)
|
4
|
+
[](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AMacOS)
|
5
|
+
[](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AWindows)
|
6
|
+
[](https://badge.fury.io/rb/duckdb)
|
6
7
|
|
7
8
|
## Description
|
8
9
|
|
data/ext/duckdb/appender.c
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
#include "ruby-duckdb.h"
|
2
2
|
|
3
|
-
#ifdef HAVE_DUCKDB_APPENDER_CREATE
|
4
|
-
|
5
3
|
static VALUE cDuckDBAppender;
|
6
4
|
|
7
5
|
static void deallocate(void *);
|
@@ -29,21 +27,11 @@ static VALUE appender_append_null(VALUE self);
|
|
29
27
|
static VALUE appender__append_date(VALUE self, VALUE yearval, VALUE monthval, VALUE dayval);
|
30
28
|
#endif
|
31
29
|
|
32
|
-
#ifdef HAVE_DUCKDB_APPEND_INTERVAL
|
33
30
|
static VALUE appender__append_interval(VALUE self, VALUE months, VALUE days, VALUE micros);
|
34
|
-
#endif
|
35
31
|
|
36
|
-
#ifdef HAVE_DUCKDB_APPEND_TIME
|
37
32
|
static VALUE appender__append_time(VALUE self, VALUE hour, VALUE min, VALUE sec, VALUE micros);
|
38
|
-
#endif
|
39
|
-
|
40
|
-
#ifdef HAVE_DUCKDB_APPEND_TIMESTAMP
|
41
33
|
static VALUE appender__append_timestamp(VALUE self, VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros);
|
42
|
-
#endif
|
43
|
-
|
44
|
-
#ifdef HAVE_DUCKDB_APPEND_HUGEINT
|
45
34
|
static VALUE appender__append_hugeint(VALUE self, VALUE lower, VALUE upper);
|
46
|
-
#endif
|
47
35
|
|
48
36
|
static VALUE appender_flush(VALUE self);
|
49
37
|
static VALUE appender_close(VALUE self);
|
@@ -302,7 +290,6 @@ static VALUE appender__append_date(VALUE self, VALUE year, VALUE month, VALUE da
|
|
302
290
|
}
|
303
291
|
#endif
|
304
292
|
|
305
|
-
#ifdef HAVE_DUCKDB_APPEND_INTERVAL
|
306
293
|
static VALUE appender__append_interval(VALUE self, VALUE months, VALUE days, VALUE micros) {
|
307
294
|
duckdb_interval interval;
|
308
295
|
rubyDuckDBAppender *ctx;
|
@@ -315,9 +302,7 @@ static VALUE appender__append_interval(VALUE self, VALUE months, VALUE days, VAL
|
|
315
302
|
}
|
316
303
|
return self;
|
317
304
|
}
|
318
|
-
#endif
|
319
305
|
|
320
|
-
#ifdef HAVE_DUCKDB_APPEND_TIME
|
321
306
|
static VALUE appender__append_time(VALUE self, VALUE hour, VALUE min, VALUE sec, VALUE micros) {
|
322
307
|
duckdb_time time;
|
323
308
|
rubyDuckDBAppender *ctx;
|
@@ -330,9 +315,7 @@ static VALUE appender__append_time(VALUE self, VALUE hour, VALUE min, VALUE sec,
|
|
330
315
|
}
|
331
316
|
return self;
|
332
317
|
}
|
333
|
-
#endif
|
334
318
|
|
335
|
-
#ifdef HAVE_DUCKDB_APPEND_TIMESTAMP
|
336
319
|
static VALUE appender__append_timestamp(VALUE self, VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros) {
|
337
320
|
duckdb_timestamp timestamp;
|
338
321
|
|
@@ -347,9 +330,7 @@ static VALUE appender__append_timestamp(VALUE self, VALUE year, VALUE month, VAL
|
|
347
330
|
}
|
348
331
|
return self;
|
349
332
|
}
|
350
|
-
#endif
|
351
333
|
|
352
|
-
#ifdef HAVE_DUCKDB_APPEND_HUGEINT
|
353
334
|
static VALUE appender__append_hugeint(VALUE self, VALUE lower, VALUE upper) {
|
354
335
|
duckdb_hugeint hugeint;
|
355
336
|
|
@@ -364,7 +345,6 @@ static VALUE appender__append_hugeint(VALUE self, VALUE lower, VALUE upper) {
|
|
364
345
|
}
|
365
346
|
return self;
|
366
347
|
}
|
367
|
-
#endif
|
368
348
|
|
369
349
|
static VALUE appender_flush(VALUE self) {
|
370
350
|
rubyDuckDBAppender *ctx;
|
@@ -410,19 +390,10 @@ void init_duckdb_appender(void) {
|
|
410
390
|
#ifdef HAVE_DUCKDB_APPEND_DATE
|
411
391
|
rb_define_private_method(cDuckDBAppender, "_append_date", appender__append_date, 3);
|
412
392
|
#endif
|
413
|
-
#ifdef HAVE_DUCKDB_APPEND_INTERVAL
|
414
393
|
rb_define_private_method(cDuckDBAppender, "_append_interval", appender__append_interval, 3);
|
415
|
-
#endif
|
416
|
-
#ifdef HAVE_DUCKDB_APPEND_TIME
|
417
394
|
rb_define_private_method(cDuckDBAppender, "_append_time", appender__append_time, 4);
|
418
|
-
#endif
|
419
|
-
#ifdef HAVE_DUCKDB_APPEND_TIMESTAMP
|
420
395
|
rb_define_private_method(cDuckDBAppender, "_append_timestamp", appender__append_timestamp, 7);
|
421
|
-
#endif
|
422
|
-
#ifdef HAVE_DUCKDB_APPEND_HUGEINT
|
423
396
|
rb_define_private_method(cDuckDBAppender, "_append_hugeint", appender__append_hugeint, 2);
|
424
|
-
#endif
|
425
397
|
rb_define_method(cDuckDBAppender, "flush", appender_flush, 0);
|
426
398
|
rb_define_method(cDuckDBAppender, "close", appender_close, 0);
|
427
399
|
}
|
428
|
-
#endif /* HAVE_DUCKDB_APPENDER_CREATE */
|
data/ext/duckdb/appender.h
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
#ifndef RUBY_DUCKDB_APPENDER_H
|
2
2
|
#define RUBY_DUCKDB_APPENDER_H
|
3
3
|
|
4
|
-
#ifdef HAVE_DUCKDB_APPENDER_CREATE
|
5
|
-
|
6
4
|
struct _rubyDuckDBAppender {
|
7
5
|
duckdb_appender appender;
|
8
6
|
};
|
@@ -12,6 +10,3 @@ typedef struct _rubyDuckDBAppender rubyDuckDBAppender;
|
|
12
10
|
void init_duckdb_appender(void);
|
13
11
|
|
14
12
|
#endif
|
15
|
-
|
16
|
-
#endif
|
17
|
-
|
data/ext/duckdb/column.c
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
#include "ruby-duckdb.h"
|
2
|
+
|
3
|
+
static VALUE cDuckDBColumn;
|
4
|
+
|
5
|
+
static void deallocate(void *ctx);
|
6
|
+
static VALUE allocate(VALUE klass);
|
7
|
+
static VALUE duckdb_column__type(VALUE oDuckDBColumn);
|
8
|
+
static VALUE duckdb_column_get_name(VALUE oDuckDBColumn);
|
9
|
+
|
10
|
+
static void deallocate(void *ctx) {
|
11
|
+
rubyDuckDBColumn *p = (rubyDuckDBColumn *)ctx;
|
12
|
+
|
13
|
+
xfree(p);
|
14
|
+
}
|
15
|
+
|
16
|
+
static VALUE allocate(VALUE klass) {
|
17
|
+
rubyDuckDBColumn *ctx = xcalloc((size_t)1, sizeof(rubyDuckDBColumn));
|
18
|
+
return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
|
19
|
+
}
|
20
|
+
|
21
|
+
/*
|
22
|
+
*
|
23
|
+
*/
|
24
|
+
VALUE duckdb_column__type(VALUE oDuckDBColumn) {
|
25
|
+
rubyDuckDBColumn *ctx;
|
26
|
+
Data_Get_Struct(oDuckDBColumn, rubyDuckDBColumn, ctx);
|
27
|
+
|
28
|
+
VALUE result = rb_ivar_get(oDuckDBColumn, rb_intern("result"));
|
29
|
+
rubyDuckDBResult *ctxresult;
|
30
|
+
Data_Get_Struct(result, rubyDuckDBResult, ctxresult);
|
31
|
+
duckdb_type type = duckdb_column_type(&(ctxresult->result), ctx->col);
|
32
|
+
|
33
|
+
return INT2FIX(type);
|
34
|
+
}
|
35
|
+
|
36
|
+
/*
|
37
|
+
* call-seq:
|
38
|
+
* column.name -> string.
|
39
|
+
*
|
40
|
+
* Returns the column name.
|
41
|
+
*
|
42
|
+
*/
|
43
|
+
VALUE duckdb_column_get_name(VALUE oDuckDBColumn) {
|
44
|
+
rubyDuckDBColumn *ctx;
|
45
|
+
Data_Get_Struct(oDuckDBColumn, rubyDuckDBColumn, ctx);
|
46
|
+
|
47
|
+
VALUE result = rb_ivar_get(oDuckDBColumn, rb_intern("result"));
|
48
|
+
rubyDuckDBResult *ctxresult;
|
49
|
+
Data_Get_Struct(result, rubyDuckDBResult, ctxresult);
|
50
|
+
|
51
|
+
return rb_str_new2(duckdb_column_name(&(ctxresult->result), ctx->col));
|
52
|
+
}
|
53
|
+
|
54
|
+
VALUE create_column(VALUE oDuckDBResult, idx_t col) {
|
55
|
+
VALUE obj;
|
56
|
+
|
57
|
+
obj = allocate(cDuckDBColumn);
|
58
|
+
rubyDuckDBColumn *ctx;
|
59
|
+
Data_Get_Struct(obj, rubyDuckDBColumn, ctx);
|
60
|
+
|
61
|
+
rb_ivar_set(obj, rb_intern("result"), oDuckDBResult);
|
62
|
+
ctx->col = col;
|
63
|
+
|
64
|
+
return obj;
|
65
|
+
}
|
66
|
+
|
67
|
+
void init_duckdb_column(void) {
|
68
|
+
cDuckDBColumn = rb_define_class_under(mDuckDB, "Column", rb_cObject);
|
69
|
+
rb_define_alloc_func(cDuckDBColumn, allocate);
|
70
|
+
|
71
|
+
rb_define_private_method(cDuckDBColumn, "_type", duckdb_column__type, 0);
|
72
|
+
rb_define_method(cDuckDBColumn, "name", duckdb_column_get_name, 0);
|
73
|
+
}
|
data/ext/duckdb/column.h
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#ifndef RUBY_DUCKDB_COLUMN_H
|
2
|
+
#define RUBY_DUCKDB_COLUMN_H
|
3
|
+
|
4
|
+
struct _rubyDuckDBColumn {
|
5
|
+
VALUE result;
|
6
|
+
idx_t col;
|
7
|
+
};
|
8
|
+
|
9
|
+
typedef struct _rubyDuckDBColumn rubyDuckDBColumn;
|
10
|
+
|
11
|
+
void init_duckdb_column(void);
|
12
|
+
VALUE create_column(VALUE oDuckDBResult, idx_t col);
|
13
|
+
|
14
|
+
#endif
|
data/ext/duckdb/duckdb.c
CHANGED
@@ -10,15 +10,12 @@ Init_duckdb_native(void) {
|
|
10
10
|
init_duckdb_database();
|
11
11
|
init_duckdb_connection();
|
12
12
|
init_duckdb_result();
|
13
|
+
init_duckdb_column();
|
13
14
|
init_duckdb_prepared_statement();
|
14
15
|
init_duckdb_blob();
|
15
16
|
|
16
|
-
#ifdef HAVE_DUCKDB_APPENDER_CREATE
|
17
|
-
|
18
17
|
init_duckdb_appender();
|
19
18
|
|
20
|
-
#endif /* HAVE_DUCKDB_APPENDER_CREATE */
|
21
|
-
|
22
19
|
#ifdef HAVE_DUCKDB_CREATE_CONFIG
|
23
20
|
|
24
21
|
init_duckdb_config();
|
data/ext/duckdb/extconf.rb
CHANGED
@@ -6,13 +6,9 @@ raise 'duckdb library is not found. Install duckdb library file and header file.
|
|
6
6
|
|
7
7
|
raise 'duckdb >= 0.2.9 is required. Install duckdb >= 0.2.9' unless have_func('duckdb_value_is_null', 'duckdb.h')
|
8
8
|
|
9
|
-
if
|
10
|
-
|
11
|
-
elsif have_func('duckdb_nparams(NULL, NULL)', 'duckdb.h')
|
12
|
-
$defs << '-DHAVE_DUCKDB_NPARAMS_028'
|
13
|
-
end
|
9
|
+
# ducdb >= 0.3.3 if duckdb_append_data_chunk() is defined.
|
10
|
+
have_func('duckdb_append_data_chunk', 'duckdb.h')
|
14
11
|
|
15
|
-
have_func('duckdb_appender_create', 'duckdb.h')
|
16
12
|
have_func('duckdb_free', 'duckdb.h')
|
17
13
|
|
18
14
|
have_func('duckdb_create_config', 'duckdb.h')
|
@@ -20,14 +16,5 @@ have_func('duckdb_open_ext', 'duckdb.h')
|
|
20
16
|
have_func('duckdb_prepare_error', 'duckdb.h')
|
21
17
|
|
22
18
|
have_func('duckdb_append_date', 'duckdb.h')
|
23
|
-
have_func('duckdb_append_interval', 'duckdb.h')
|
24
|
-
have_func('duckdb_append_time', 'duckdb.h')
|
25
|
-
have_func('duckdb_append_timestamp', 'duckdb.h')
|
26
|
-
have_func('duckdb_append_hugeint', 'duckdb.h')
|
27
|
-
|
28
|
-
have_func('duckdb_bind_date', 'duckdb.h')
|
29
|
-
have_func('duckdb_bind_time', 'duckdb.h')
|
30
|
-
have_func('duckdb_bind_timestamp', 'duckdb.h')
|
31
|
-
have_func('duckdb_bind_interval', 'duckdb.h')
|
32
19
|
|
33
20
|
create_makefile('duckdb/duckdb_native')
|
@@ -18,23 +18,10 @@ static VALUE duckdb_prepared_statement_bind_double(VALUE self, VALUE vidx, VALUE
|
|
18
18
|
static VALUE duckdb_prepared_statement_bind_varchar(VALUE self, VALUE vidx, VALUE str);
|
19
19
|
static VALUE duckdb_prepared_statement_bind_blob(VALUE self, VALUE vidx, VALUE blob);
|
20
20
|
static VALUE duckdb_prepared_statement_bind_null(VALUE self, VALUE vidx);
|
21
|
-
|
22
|
-
#ifdef HAVE_DUCKDB_BIND_DATE
|
23
21
|
static VALUE duckdb_prepared_statement__bind_date(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day);
|
24
|
-
#endif
|
25
|
-
|
26
|
-
#ifdef HAVE_DUCKDB_BIND_TIME
|
27
22
|
static VALUE duckdb_prepared_statement__bind_time(VALUE self, VALUE vidx, VALUE hour, VALUE min, VALUE sec, VALUE micros);
|
28
|
-
#endif
|
29
|
-
|
30
|
-
#ifdef HAVE_DUCKDB_BIND_TIMESTAMP
|
31
23
|
static VALUE duckdb_prepared_statement__bind_timestamp(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros);
|
32
|
-
#endif
|
33
|
-
|
34
|
-
#ifdef HAVE_DUCKDB_BIND_INTERVAL
|
35
24
|
static VALUE duckdb_prepared_statement__bind_interval(VALUE self, VALUE vidx, VALUE months, VALUE days, VALUE micros);
|
36
|
-
#endif
|
37
|
-
|
38
25
|
|
39
26
|
static void deallocate(void *ctx) {
|
40
27
|
rubyDuckDBPreparedStatement *p = (rubyDuckDBPreparedStatement *)ctx;
|
@@ -74,14 +61,7 @@ static VALUE duckdb_prepared_statement_initialize(VALUE self, VALUE con, VALUE q
|
|
74
61
|
static VALUE duckdb_prepared_statement_nparams(VALUE self) {
|
75
62
|
rubyDuckDBPreparedStatement *ctx;
|
76
63
|
Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
|
77
|
-
#ifdef HAVE_DUCKDB_NPARAMS_029
|
78
64
|
return rb_int2big(duckdb_nparams(ctx->prepared_statement));
|
79
|
-
#else
|
80
|
-
if (duckdb_nparams(ctx->prepared_statement, &(ctx->nparams)) == DuckDBError) {
|
81
|
-
rb_raise(eDuckDBError, "failed to get number of parameters");
|
82
|
-
}
|
83
|
-
return rb_int2big(ctx->nparams);
|
84
|
-
#endif
|
85
65
|
}
|
86
66
|
|
87
67
|
|
@@ -232,7 +212,6 @@ static VALUE duckdb_prepared_statement_bind_null(VALUE self, VALUE vidx) {
|
|
232
212
|
return self;
|
233
213
|
}
|
234
214
|
|
235
|
-
#ifdef HAVE_DUCKDB_BIND_DATE
|
236
215
|
static VALUE duckdb_prepared_statement__bind_date(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day) {
|
237
216
|
rubyDuckDBPreparedStatement *ctx;
|
238
217
|
duckdb_date dt;
|
@@ -246,9 +225,7 @@ static VALUE duckdb_prepared_statement__bind_date(VALUE self, VALUE vidx, VALUE
|
|
246
225
|
}
|
247
226
|
return self;
|
248
227
|
}
|
249
|
-
#endif
|
250
228
|
|
251
|
-
#ifdef HAVE_DUCKDB_BIND_TIME
|
252
229
|
static VALUE duckdb_prepared_statement__bind_time(VALUE self, VALUE vidx, VALUE hour, VALUE min, VALUE sec, VALUE micros){
|
253
230
|
rubyDuckDBPreparedStatement *ctx;
|
254
231
|
duckdb_time time;
|
@@ -263,9 +240,7 @@ static VALUE duckdb_prepared_statement__bind_time(VALUE self, VALUE vidx, VALUE
|
|
263
240
|
}
|
264
241
|
return self;
|
265
242
|
}
|
266
|
-
#endif
|
267
243
|
|
268
|
-
#ifdef HAVE_DUCKDB_BIND_TIMESTAMP
|
269
244
|
static VALUE duckdb_prepared_statement__bind_timestamp(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros) {
|
270
245
|
duckdb_timestamp timestamp;
|
271
246
|
rubyDuckDBPreparedStatement *ctx;
|
@@ -279,9 +254,7 @@ static VALUE duckdb_prepared_statement__bind_timestamp(VALUE self, VALUE vidx, V
|
|
279
254
|
}
|
280
255
|
return self;
|
281
256
|
}
|
282
|
-
#endif
|
283
257
|
|
284
|
-
#ifdef HAVE_DUCKDB_BIND_INTERVAL
|
285
258
|
static VALUE duckdb_prepared_statement__bind_interval(VALUE self, VALUE vidx, VALUE months, VALUE days, VALUE micros) {
|
286
259
|
duckdb_interval interval;
|
287
260
|
rubyDuckDBPreparedStatement *ctx;
|
@@ -295,7 +268,6 @@ static VALUE duckdb_prepared_statement__bind_interval(VALUE self, VALUE vidx, VA
|
|
295
268
|
}
|
296
269
|
return self;
|
297
270
|
}
|
298
|
-
#endif
|
299
271
|
|
300
272
|
void init_duckdb_prepared_statement(void) {
|
301
273
|
cDuckDBPreparedStatement = rb_define_class_under(mDuckDB, "PreparedStatement", rb_cObject);
|
@@ -316,13 +288,7 @@ void init_duckdb_prepared_statement(void) {
|
|
316
288
|
rb_define_method(cDuckDBPreparedStatement, "bind_blob", duckdb_prepared_statement_bind_blob, 2);
|
317
289
|
rb_define_method(cDuckDBPreparedStatement, "bind_null", duckdb_prepared_statement_bind_null, 1);
|
318
290
|
rb_define_private_method(cDuckDBPreparedStatement, "_bind_date", duckdb_prepared_statement__bind_date, 4);
|
319
|
-
#ifdef HAVE_DUCKDB_BIND_TIME
|
320
291
|
rb_define_private_method(cDuckDBPreparedStatement, "_bind_time", duckdb_prepared_statement__bind_time, 5);
|
321
|
-
#endif
|
322
|
-
#ifdef HAVE_DUCKDB_BIND_TIMESTAMP
|
323
292
|
rb_define_private_method(cDuckDBPreparedStatement, "_bind_timestamp", duckdb_prepared_statement__bind_timestamp, 8);
|
324
|
-
#endif
|
325
|
-
#ifdef HAVE_DUCKDB_BIND_INTERVAL
|
326
293
|
rb_define_private_method(cDuckDBPreparedStatement, "_bind_interval", duckdb_prepared_statement__bind_interval, 4);
|
327
|
-
#endif
|
328
294
|
}
|
data/ext/duckdb/result.c
CHANGED
@@ -16,6 +16,7 @@ static VALUE row_array(rubyDuckDBResult *ctx, idx_t row_idx);
|
|
16
16
|
static VALUE duckdb_result_row_size(VALUE oDuckDBResult, VALUE args, VALUE obj);
|
17
17
|
static VALUE duckdb_result_each(VALUE oDuckDBResult);
|
18
18
|
static VALUE duckdb_result_rows_changed(VALUE oDuckDBResult);
|
19
|
+
static VALUE duckdb_result_columns(VALUE oDuckDBResult);
|
19
20
|
|
20
21
|
static void deallocate(void *ctx) {
|
21
22
|
rubyDuckDBResult *p = (rubyDuckDBResult *)ctx;
|
@@ -65,11 +66,7 @@ static VALUE to_ruby_obj_string_from_blob(duckdb_result *result, idx_t col_idx,
|
|
65
66
|
str = rb_str_new(bval.data, bval.size);
|
66
67
|
|
67
68
|
if (bval.data) {
|
68
|
-
#ifdef HAVE_DUCKDB_FREE
|
69
69
|
duckdb_free(bval.data);
|
70
|
-
#else
|
71
|
-
free(bval.data);
|
72
|
-
#endif
|
73
70
|
}
|
74
71
|
|
75
72
|
return str;
|
@@ -100,11 +97,7 @@ static VALUE to_ruby_obj(duckdb_result *result, idx_t col_idx, idx_t row_idx) {
|
|
100
97
|
p = duckdb_value_varchar(result, col_idx, row_idx);
|
101
98
|
if (p) {
|
102
99
|
obj = rb_str_new2(p);
|
103
|
-
#ifdef HAVE_DUCKDB_FREE
|
104
100
|
duckdb_free(p);
|
105
|
-
#else
|
106
|
-
free(p);
|
107
|
-
#endif /* HAVE_DUCKDB_FREE */
|
108
101
|
if (duckdb_column_type(result, col_idx) == DUCKDB_TYPE_HUGEINT) {
|
109
102
|
obj = rb_funcall(obj, rb_intern("to_i"), 0);
|
110
103
|
}
|
@@ -174,6 +167,28 @@ static VALUE duckdb_result_rows_changed(VALUE oDuckDBResult) {
|
|
174
167
|
return LL2NUM(duckdb_rows_changed(&(ctx->result)));
|
175
168
|
}
|
176
169
|
|
170
|
+
/*
|
171
|
+
* call-seq:
|
172
|
+
* result.columns -> DuckDB::Column[]
|
173
|
+
*
|
174
|
+
* Returns the column class Lists.
|
175
|
+
*
|
176
|
+
*/
|
177
|
+
static VALUE duckdb_result_columns(VALUE oDuckDBResult) {
|
178
|
+
rubyDuckDBResult *ctx;
|
179
|
+
Data_Get_Struct(oDuckDBResult, rubyDuckDBResult, ctx);
|
180
|
+
|
181
|
+
idx_t col_idx;
|
182
|
+
idx_t column_count = duckdb_column_count(&(ctx->result));
|
183
|
+
|
184
|
+
VALUE ary = rb_ary_new2(column_count);
|
185
|
+
for(col_idx = 0; col_idx < column_count; col_idx++) {
|
186
|
+
VALUE column = create_column(oDuckDBResult, col_idx);
|
187
|
+
rb_ary_store(ary, col_idx, column);
|
188
|
+
}
|
189
|
+
return ary;
|
190
|
+
}
|
191
|
+
|
177
192
|
VALUE create_result(void) {
|
178
193
|
return allocate(cDuckDBResult);
|
179
194
|
}
|
@@ -184,4 +199,5 @@ void init_duckdb_result(void) {
|
|
184
199
|
|
185
200
|
rb_define_method(cDuckDBResult, "each", duckdb_result_each, 0);
|
186
201
|
rb_define_method(cDuckDBResult, "rows_changed", duckdb_result_rows_changed, 0);
|
202
|
+
rb_define_method(cDuckDBResult, "columns", duckdb_result_columns, 0);
|
187
203
|
}
|
data/ext/duckdb/ruby-duckdb.h
CHANGED
@@ -3,20 +3,22 @@
|
|
3
3
|
|
4
4
|
#include "ruby.h"
|
5
5
|
#include <duckdb.h>
|
6
|
+
|
7
|
+
#ifdef HAVE_DUCKDB_APPEND_DATA_CHUNK
|
8
|
+
#define HAVE_DUCKDB_HEADER_VERSION_033 1
|
9
|
+
#endif
|
10
|
+
|
6
11
|
#include "./error.h"
|
7
12
|
#include "./database.h"
|
8
13
|
#include "./connection.h"
|
9
14
|
#include "./result.h"
|
15
|
+
#include "./column.h"
|
10
16
|
#include "./prepared_statement.h"
|
11
17
|
#include "./util.h"
|
12
18
|
|
13
19
|
#include "./blob.h"
|
14
|
-
#ifdef HAVE_DUCKDB_APPENDER_CREATE
|
15
|
-
|
16
20
|
#include "./appender.h"
|
17
21
|
|
18
|
-
#endif /* HAVE_DUCKDB_APPENDER_CREATE */
|
19
|
-
|
20
22
|
#ifdef HAVE_DUCKDB_CREATE_CONFIG
|
21
23
|
|
22
24
|
#include "./config.h"
|
data/lib/duckdb/appender.rb
CHANGED
@@ -3,248 +3,242 @@ require 'time'
|
|
3
3
|
require_relative './converter'
|
4
4
|
|
5
5
|
module DuckDB
|
6
|
-
|
7
|
-
|
6
|
+
# The DuckDB::Appender encapsulates DuckDB Appender.
|
7
|
+
#
|
8
|
+
# require 'duckdb'
|
9
|
+
# db = DuckDB::Database.open
|
10
|
+
# con = db.connect
|
11
|
+
# con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
|
12
|
+
# appender = con.appender('users')
|
13
|
+
# appender.append_row(1, 'Alice')
|
14
|
+
#
|
15
|
+
class Appender
|
16
|
+
include DuckDB::Converter
|
17
|
+
|
18
|
+
RANGE_INT16 = -32_768..32_767
|
19
|
+
RANGE_INT32 = -2_147_483_648..2_147_483_647
|
20
|
+
RANGE_INT64 = -9_223_372_036_854_775_808..9_223_372_036_854_775_807
|
21
|
+
|
22
|
+
#
|
23
|
+
# appends huge int value.
|
8
24
|
#
|
9
25
|
# require 'duckdb'
|
10
26
|
# db = DuckDB::Database.open
|
11
27
|
# con = db.connect
|
12
|
-
# con.query('CREATE TABLE
|
13
|
-
# appender = con.appender('
|
14
|
-
# appender
|
28
|
+
# con.query('CREATE TABLE numbers (num HUGEINT)')
|
29
|
+
# appender = con.appender('numbers')
|
30
|
+
# appender
|
31
|
+
# .begin_row
|
32
|
+
# .append_hugeint(-170_141_183_460_469_231_731_687_303_715_884_105_727)
|
33
|
+
# .end_row
|
15
34
|
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
#
|
26
|
-
# require 'duckdb'
|
27
|
-
# db = DuckDB::Database.open
|
28
|
-
# con = db.connect
|
29
|
-
# con.query('CREATE TABLE numbers (num HUGEINT)')
|
30
|
-
# appender = con.appender('numbers')
|
31
|
-
# appender
|
32
|
-
# .begin_row
|
33
|
-
# .append_hugeint(-170_141_183_460_469_231_731_687_303_715_884_105_727)
|
34
|
-
# .end_row
|
35
|
-
#
|
36
|
-
def append_hugeint(value)
|
37
|
-
case value
|
38
|
-
when Integer
|
39
|
-
if respond_to?(:_append_hugeint, true)
|
40
|
-
half = 1 << 64
|
41
|
-
upper = value / half
|
42
|
-
lower = value - upper * half
|
43
|
-
_append_hugeint(lower, upper)
|
44
|
-
else
|
45
|
-
append_varchar(value.to_s)
|
46
|
-
end
|
47
|
-
else
|
48
|
-
raise(ArgumentError, "2nd argument `#{value}` must be Integer.")
|
49
|
-
end
|
35
|
+
def append_hugeint(value)
|
36
|
+
case value
|
37
|
+
when Integer
|
38
|
+
half = 1 << 64
|
39
|
+
upper = value / half
|
40
|
+
lower = value - upper * half
|
41
|
+
_append_hugeint(lower, upper)
|
42
|
+
else
|
43
|
+
raise(ArgumentError, "2nd argument `#{value}` must be Integer.")
|
50
44
|
end
|
45
|
+
end
|
51
46
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
end
|
47
|
+
#
|
48
|
+
# appends date value.
|
49
|
+
#
|
50
|
+
# require 'duckdb'
|
51
|
+
# db = DuckDB::Database.open
|
52
|
+
# con = db.connect
|
53
|
+
# con.query('CREATE TABLE dates (date_value DATE)')
|
54
|
+
# appender = con.appender('dates')
|
55
|
+
# appender.begin_row
|
56
|
+
# appender.append_date(Date.today)
|
57
|
+
# # or
|
58
|
+
# # appender.append_date(Time.now)
|
59
|
+
# # appender.append_date('2021-10-10')
|
60
|
+
# appender.end_row
|
61
|
+
# appender.flush
|
62
|
+
#
|
63
|
+
def append_date(value)
|
64
|
+
date = case value
|
65
|
+
when Date, Time
|
66
|
+
value
|
67
|
+
else
|
68
|
+
begin
|
69
|
+
Date.parse(value)
|
70
|
+
rescue
|
71
|
+
raise(ArgumentError, "Cannot parse argument `#{value}` to Date.")
|
78
72
|
end
|
73
|
+
end
|
79
74
|
|
80
|
-
|
81
|
-
|
75
|
+
_append_date(date.year, date.month, date.day)
|
76
|
+
end
|
82
77
|
|
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
|
-
end
|
78
|
+
#
|
79
|
+
# appends time value.
|
80
|
+
#
|
81
|
+
# require 'duckdb'
|
82
|
+
# db = DuckDB::Database.open
|
83
|
+
# con = db.connect
|
84
|
+
# con.query('CREATE TABLE times (time_value TIME)')
|
85
|
+
# appender = con.appender('times')
|
86
|
+
# appender.begin_row
|
87
|
+
# appender.append_time(Time.now)
|
88
|
+
# # or
|
89
|
+
# # appender.append_time('01:01:01')
|
90
|
+
# appender.end_row
|
91
|
+
# appender.flush
|
92
|
+
#
|
93
|
+
def append_time(value)
|
94
|
+
time = case value
|
95
|
+
when Time
|
96
|
+
value
|
97
|
+
else
|
98
|
+
begin
|
99
|
+
Time.parse(value)
|
100
|
+
rescue
|
101
|
+
raise(ArgumentError, "Cannot parse argument `#{value}` to Time.")
|
108
102
|
end
|
103
|
+
end
|
109
104
|
|
110
|
-
|
111
|
-
|
105
|
+
_append_time(time.hour, time.min, time.sec, time.usec)
|
106
|
+
end
|
112
107
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
end
|
108
|
+
#
|
109
|
+
# appends timestamp value.
|
110
|
+
#
|
111
|
+
# require 'duckdb'
|
112
|
+
# db = DuckDB::Database.open
|
113
|
+
# con = db.connect
|
114
|
+
# con.query('CREATE TABLE timestamps (timestamp_value TIMESTAMP)')
|
115
|
+
# appender = con.appender('timestamps')
|
116
|
+
# appender.begin_row
|
117
|
+
# appender.append_time(Time.now)
|
118
|
+
# # or
|
119
|
+
# # appender.append_time(Date.today)
|
120
|
+
# # appender.append_time('2021-08-01 01:01:01')
|
121
|
+
# appender.end_row
|
122
|
+
# appender.flush
|
123
|
+
#
|
124
|
+
def append_timestamp(value)
|
125
|
+
time = case value
|
126
|
+
when Time
|
127
|
+
value
|
128
|
+
when Date
|
129
|
+
value.to_time
|
130
|
+
else
|
131
|
+
begin
|
132
|
+
Time.parse(value)
|
133
|
+
rescue
|
134
|
+
raise(ArgumentError, "Cannot parse argument `#{value}` to Time or Date.")
|
141
135
|
end
|
136
|
+
end
|
142
137
|
|
143
|
-
|
144
|
-
|
138
|
+
_append_timestamp(time.year, time.month, time.day, time.hour, time.min, time.sec, time.nsec / 1000)
|
139
|
+
end
|
145
140
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
_append_interval(months, days, micros)
|
170
|
-
end
|
141
|
+
#
|
142
|
+
# appends interval.
|
143
|
+
# The argument must be ISO8601 duration format.
|
144
|
+
# WARNING: This method is expremental.
|
145
|
+
#
|
146
|
+
# require 'duckdb'
|
147
|
+
# db = DuckDB::Database.open
|
148
|
+
# con = db.connect
|
149
|
+
# con.query('CREATE TABLE intervals (interval_value INTERVAL)')
|
150
|
+
# appender = con.appender('intervals')
|
151
|
+
# appender
|
152
|
+
# .begin_row
|
153
|
+
# .append_interval('P1Y2D') # => append 1 year 2 days interval.
|
154
|
+
# .end_row
|
155
|
+
# .flush
|
156
|
+
#
|
157
|
+
def append_interval(value)
|
158
|
+
raise ArgumentError, "Argument `#{value}` must be a string." unless value.is_a?(String)
|
159
|
+
|
160
|
+
hash = iso8601_interval_to_hash(value)
|
161
|
+
|
162
|
+
months, days, micros = hash_to__append_interval_args(hash)
|
171
163
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
164
|
+
_append_interval(months, days, micros)
|
165
|
+
end
|
166
|
+
|
167
|
+
#
|
168
|
+
# appends value.
|
169
|
+
#
|
170
|
+
# require 'duckdb'
|
171
|
+
# db = DuckDB::Database.open
|
172
|
+
# con = db.connect
|
173
|
+
# con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
|
174
|
+
# appender = con.appender('users')
|
175
|
+
# appender.begin_row
|
176
|
+
# appender.append(1)
|
177
|
+
# appender.append('Alice')
|
178
|
+
# appender.end_row
|
179
|
+
#
|
180
|
+
def append(value)
|
181
|
+
case value
|
182
|
+
when NilClass
|
183
|
+
append_null
|
184
|
+
when Float
|
185
|
+
append_double(value)
|
186
|
+
when Integer
|
186
187
|
case value
|
187
|
-
when
|
188
|
-
|
189
|
-
when
|
190
|
-
|
191
|
-
when
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
blob?(value) ? append_blob(value) : append_varchar(value)
|
204
|
-
when TrueClass, FalseClass
|
205
|
-
append_bool(value)
|
206
|
-
when Time
|
207
|
-
if respond_to?(:append_timestamp)
|
208
|
-
append_timestamp(value)
|
209
|
-
else
|
210
|
-
append_varchar(value.strftime('%Y-%m-%d %H:%M:%S.%N'))
|
211
|
-
end
|
212
|
-
when Date
|
213
|
-
if respond_to?(:append_date)
|
214
|
-
append_date(value)
|
215
|
-
else
|
216
|
-
append_varchar(value.strftime('%Y-%m-%d'))
|
217
|
-
end
|
188
|
+
when RANGE_INT16
|
189
|
+
append_int16(value)
|
190
|
+
when RANGE_INT32
|
191
|
+
append_int32(value)
|
192
|
+
when RANGE_INT64
|
193
|
+
append_int64(value)
|
194
|
+
else
|
195
|
+
append_hugeint(value)
|
196
|
+
end
|
197
|
+
when String
|
198
|
+
blob?(value) ? append_blob(value) : append_varchar(value)
|
199
|
+
when TrueClass, FalseClass
|
200
|
+
append_bool(value)
|
201
|
+
when Time
|
202
|
+
if respond_to?(:append_timestamp)
|
203
|
+
append_timestamp(value)
|
218
204
|
else
|
219
|
-
|
205
|
+
append_varchar(value.strftime('%Y-%m-%d %H:%M:%S.%N'))
|
220
206
|
end
|
207
|
+
when Date
|
208
|
+
if respond_to?(:append_date)
|
209
|
+
append_date(value)
|
210
|
+
else
|
211
|
+
append_varchar(value.strftime('%Y-%m-%d'))
|
212
|
+
end
|
213
|
+
else
|
214
|
+
raise(DuckDB::Error, "not supported type #{value} (#{value.class})")
|
221
215
|
end
|
216
|
+
end
|
222
217
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
end
|
240
|
-
end_row
|
218
|
+
#
|
219
|
+
# append a row.
|
220
|
+
#
|
221
|
+
# appender.append_row(1, 'Alice')
|
222
|
+
#
|
223
|
+
# is same as:
|
224
|
+
#
|
225
|
+
# appender.begin_row
|
226
|
+
# appender.append(1)
|
227
|
+
# appender.append('Alice')
|
228
|
+
# appender.end_row
|
229
|
+
#
|
230
|
+
def append_row(*args)
|
231
|
+
begin_row
|
232
|
+
args.each do |arg|
|
233
|
+
append(arg)
|
241
234
|
end
|
235
|
+
end_row
|
236
|
+
end
|
242
237
|
|
243
|
-
|
238
|
+
private
|
244
239
|
|
245
|
-
|
246
|
-
|
247
|
-
end
|
240
|
+
def blob?(value)
|
241
|
+
value.instance_of?(DuckDB::Blob) || value.encoding == Encoding::BINARY
|
248
242
|
end
|
249
243
|
end
|
250
244
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module DuckDB
|
2
|
+
class Column
|
3
|
+
#
|
4
|
+
# returns column type symbol
|
5
|
+
# `:unknown` means that the column type is unknown/unsupported by ruby-duckdb.
|
6
|
+
# `:invalid` means that the column type is invalid in duckdb.
|
7
|
+
#
|
8
|
+
# require 'duckdb'
|
9
|
+
# db = DuckDB::Database.open
|
10
|
+
# con = db.connect
|
11
|
+
# con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
|
12
|
+
#
|
13
|
+
# users = con.query('SELECT * FROM users')
|
14
|
+
# columns = users.columns
|
15
|
+
# columns.first.type #=> :integer
|
16
|
+
#
|
17
|
+
def type
|
18
|
+
types = %i[
|
19
|
+
invalid
|
20
|
+
boolean
|
21
|
+
tinyint
|
22
|
+
smallint
|
23
|
+
integer
|
24
|
+
bigint
|
25
|
+
utinyint
|
26
|
+
usmallint
|
27
|
+
uinteger
|
28
|
+
ubigint
|
29
|
+
float
|
30
|
+
double
|
31
|
+
timestamp
|
32
|
+
date
|
33
|
+
time
|
34
|
+
interval
|
35
|
+
hugeint
|
36
|
+
varchar
|
37
|
+
blob
|
38
|
+
decimal
|
39
|
+
timestamp_s
|
40
|
+
timestamp_ms
|
41
|
+
timestamp_ns
|
42
|
+
enum
|
43
|
+
list
|
44
|
+
struct
|
45
|
+
map
|
46
|
+
uuid
|
47
|
+
json
|
48
|
+
]
|
49
|
+
index = _type
|
50
|
+
return :unknown if index >= types.size
|
51
|
+
|
52
|
+
types[index]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -124,7 +124,6 @@ module DuckDB
|
|
124
124
|
# stmt = PreparedStatement.new(con, sql)
|
125
125
|
# stmt.bind(1, 'P1Y2D')
|
126
126
|
def bind_interval(i, value)
|
127
|
-
raise(DuckDB::Error, 'bind_interval is not available with your duckdb version. please install duckdb latest version at first') unless respond_to?(:_bind_interval, true)
|
128
127
|
raise ArgumentError, "Argument `#{value}` must be a string." unless value.is_a?(String)
|
129
128
|
|
130
129
|
hash = iso8601_interval_to_hash(value)
|
data/lib/duckdb/version.rb
CHANGED
data/lib/duckdb.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: duckdb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masaki Suketa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-04-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -93,6 +93,8 @@ files:
|
|
93
93
|
- ext/duckdb/appender.h
|
94
94
|
- ext/duckdb/blob.c
|
95
95
|
- ext/duckdb/blob.h
|
96
|
+
- ext/duckdb/column.c
|
97
|
+
- ext/duckdb/column.h
|
96
98
|
- ext/duckdb/config.c
|
97
99
|
- ext/duckdb/config.h
|
98
100
|
- ext/duckdb/connection.c
|
@@ -112,6 +114,7 @@ files:
|
|
112
114
|
- ext/duckdb/util.h
|
113
115
|
- lib/duckdb.rb
|
114
116
|
- lib/duckdb/appender.rb
|
117
|
+
- lib/duckdb/column.rb
|
115
118
|
- lib/duckdb/config.rb
|
116
119
|
- lib/duckdb/connection.rb
|
117
120
|
- lib/duckdb/converter.rb
|
@@ -141,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
144
|
- !ruby/object:Gem::Version
|
142
145
|
version: '0'
|
143
146
|
requirements: []
|
144
|
-
rubygems_version: 3.3.
|
147
|
+
rubygems_version: 3.3.10
|
145
148
|
signing_key:
|
146
149
|
specification_version: 4
|
147
150
|
summary: This module is Ruby binding for DuckDB database engine.
|