duckdb 1.1.3.1 → 1.2.0.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/make_documents.yml +34 -0
- data/.github/workflows/test_on_macos.yml +2 -3
- data/.github/workflows/test_on_ubuntu.yml +2 -2
- data/.github/workflows/test_on_windows.yml +2 -2
- data/.gitignore +1 -0
- data/.rdoc_options +22 -0
- data/CHANGELOG.md +45 -0
- data/Dockerfile +2 -2
- data/Gemfile.lock +14 -12
- data/README.md +2 -1
- data/duckdb.gemspec +1 -0
- data/ext/duckdb/appender.c +92 -79
- data/ext/duckdb/blob.c +3 -0
- data/ext/duckdb/column.c +33 -3
- data/ext/duckdb/config.c +3 -0
- data/ext/duckdb/connection.c +6 -0
- data/ext/duckdb/database.c +6 -0
- data/ext/duckdb/duckdb.c +1 -0
- data/ext/duckdb/error.c +3 -0
- data/ext/duckdb/extconf.rb +0 -3
- data/ext/duckdb/extracted_statements.c +3 -0
- data/ext/duckdb/logical_type.c +187 -0
- data/ext/duckdb/logical_type.h +13 -0
- data/ext/duckdb/pending_result.c +5 -0
- data/ext/duckdb/prepared_statement.c +43 -6
- data/ext/duckdb/result.c +16 -44
- data/ext/duckdb/ruby-duckdb.h +2 -0
- data/lib/duckdb/appender.rb +211 -48
- data/lib/duckdb/column.rb +0 -2
- data/lib/duckdb/interval.rb +12 -10
- data/lib/duckdb/logical_type.rb +22 -0
- data/lib/duckdb/pending_result.rb +1 -1
- data/lib/duckdb/result.rb +16 -16
- data/lib/duckdb/version.rb +1 -1
- data/lib/duckdb.rb +1 -0
- metadata +9 -6
data/ext/duckdb/result.c
CHANGED
@@ -24,12 +24,11 @@ static void deallocate(void *ctx);
|
|
24
24
|
static VALUE allocate(VALUE klass);
|
25
25
|
static size_t memsize(const void *p);
|
26
26
|
static VALUE duckdb_result_column_count(VALUE oDuckDBResult);
|
27
|
-
static VALUE duckdb_result_row_count(VALUE oDuckDBResult);
|
28
27
|
static VALUE duckdb_result_rows_changed(VALUE oDuckDBResult);
|
29
28
|
static VALUE duckdb_result_columns(VALUE oDuckDBResult);
|
30
29
|
static VALUE duckdb_result_streaming_p(VALUE oDuckDBResult);
|
31
30
|
static VALUE destroy_data_chunk(VALUE arg);
|
32
|
-
static VALUE
|
31
|
+
static VALUE duckdb_result__chunk_each(VALUE oDuckDBResult);
|
33
32
|
|
34
33
|
static VALUE duckdb_result__chunk_stream(VALUE oDuckDBResult);
|
35
34
|
static VALUE yield_rows(VALUE arg);
|
@@ -147,36 +146,6 @@ static VALUE duckdb_result_column_count(VALUE oDuckDBResult) {
|
|
147
146
|
return LL2NUM(duckdb_column_count(&(ctx->result)));
|
148
147
|
}
|
149
148
|
|
150
|
-
/*
|
151
|
-
* call-seq:
|
152
|
-
* result.row_count -> Integer
|
153
|
-
*
|
154
|
-
* Returns the column size of the result.
|
155
|
-
*
|
156
|
-
* DuckDB::Database.open do |db|
|
157
|
-
* db.connect do |con|
|
158
|
-
* r = con.query('CREATE TABLE t2 (id INT, name VARCHAR(128))')
|
159
|
-
* r = con.query("INSERT INTO t2 VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Catherine')")
|
160
|
-
* r = con.query('SELECT * FROM t2')
|
161
|
-
* r.row_count # => 3
|
162
|
-
* r = con.query('SELECT * FROM t2 where id = 1')
|
163
|
-
* r.row_count # => 1
|
164
|
-
* end
|
165
|
-
* end
|
166
|
-
*
|
167
|
-
*/
|
168
|
-
static VALUE duckdb_result_row_count(VALUE oDuckDBResult) {
|
169
|
-
|
170
|
-
#ifdef DUCKDB_API_NO_DEPRECATED
|
171
|
-
return Qnil;
|
172
|
-
#else
|
173
|
-
rubyDuckDBResult *ctx;
|
174
|
-
rb_warn("`row_count` will be deprecated in the future.");
|
175
|
-
TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
|
176
|
-
return LL2NUM(duckdb_row_count(&(ctx->result)));
|
177
|
-
#endif
|
178
|
-
}
|
179
|
-
|
180
149
|
/*
|
181
150
|
* call-seq:
|
182
151
|
* result.columns -> DuckDB::Column[]
|
@@ -200,11 +169,7 @@ static VALUE duckdb_result_columns(VALUE oDuckDBResult) {
|
|
200
169
|
}
|
201
170
|
|
202
171
|
/*
|
203
|
-
*
|
204
|
-
* result.streaming? -> Boolean
|
205
|
-
*
|
206
|
-
* Returns true if the result is streaming, otherwise false.
|
207
|
-
*
|
172
|
+
* :nodoc:
|
208
173
|
*/
|
209
174
|
static VALUE duckdb_result_streaming_p(VALUE oDuckDBResult) {
|
210
175
|
rubyDuckDBResult *ctx;
|
@@ -212,6 +177,7 @@ static VALUE duckdb_result_streaming_p(VALUE oDuckDBResult) {
|
|
212
177
|
#ifdef DUCKDB_API_NO_DEPRECATED
|
213
178
|
return Qtrue;
|
214
179
|
#else
|
180
|
+
rb_warn("`DuckDB::Result#streaming?` will be deprecated in the future.");
|
215
181
|
/* FIXME streaming is allways true. so this method is not useful and deprecated. */
|
216
182
|
TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
|
217
183
|
return duckdb_result_is_streaming(ctx->result) ? Qtrue : Qfalse;
|
@@ -224,7 +190,8 @@ static VALUE destroy_data_chunk(VALUE arg) {
|
|
224
190
|
return Qnil;
|
225
191
|
}
|
226
192
|
|
227
|
-
|
193
|
+
/* :nodoc: */
|
194
|
+
static VALUE duckdb_result__chunk_each(VALUE oDuckDBResult) {
|
228
195
|
/*
|
229
196
|
#ifdef HAVE_DUCKDB_H_GE_V1_0_0
|
230
197
|
return duckdb_result__chunk_stream(oDuckDBResult);
|
@@ -258,6 +225,7 @@ static VALUE duckdb_result_chunk_each(VALUE oDuckDBResult) {
|
|
258
225
|
*/
|
259
226
|
}
|
260
227
|
|
228
|
+
/* :nodoc: */
|
261
229
|
static VALUE duckdb_result__chunk_stream(VALUE oDuckDBResult) {
|
262
230
|
rubyDuckDBResult *ctx;
|
263
231
|
struct chunk_arg arg;
|
@@ -268,11 +236,7 @@ static VALUE duckdb_result__chunk_stream(VALUE oDuckDBResult) {
|
|
268
236
|
|
269
237
|
arg.col_count = duckdb_column_count(&(ctx->result));
|
270
238
|
|
271
|
-
#ifdef HAVE_DUCKDB_H_GE_V1_0_0
|
272
239
|
while((arg.chunk = duckdb_fetch_chunk(ctx->result)) != NULL) {
|
273
|
-
#else
|
274
|
-
while((arg.chunk = duckdb_stream_fetch_chunk(ctx->result)) != NULL) {
|
275
|
-
#endif
|
276
240
|
rb_ensure(yield_rows, (VALUE)&arg, destroy_data_chunk, (VALUE)&arg);
|
277
241
|
}
|
278
242
|
return Qnil;
|
@@ -301,12 +265,14 @@ static VALUE yield_rows(VALUE arg) {
|
|
301
265
|
return Qnil;
|
302
266
|
}
|
303
267
|
|
268
|
+
/* :nodoc: */
|
304
269
|
static VALUE duckdb_result__column_type(VALUE oDuckDBResult, VALUE col_idx) {
|
305
270
|
rubyDuckDBResult *ctx;
|
306
271
|
TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
|
307
272
|
return LL2NUM(duckdb_column_type(&(ctx->result), NUM2LL(col_idx)));
|
308
273
|
}
|
309
274
|
|
275
|
+
/* :nodoc: */
|
310
276
|
static VALUE duckdb_result__return_type(VALUE oDuckDBResult) {
|
311
277
|
rubyDuckDBResult *ctx;
|
312
278
|
TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
|
@@ -320,12 +286,14 @@ static VALUE duckdb_result__return_type(VALUE oDuckDBResult) {
|
|
320
286
|
#endif
|
321
287
|
}
|
322
288
|
|
289
|
+
/* :nodoc: */
|
323
290
|
static VALUE duckdb_result__statement_type(VALUE oDuckDBResult) {
|
324
291
|
rubyDuckDBResult *ctx;
|
325
292
|
TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
|
326
293
|
return INT2FIX(duckdb_result_statement_type(ctx->result));
|
327
294
|
}
|
328
295
|
|
296
|
+
/* :nodoc: */
|
329
297
|
static VALUE duckdb_result__enum_internal_type(VALUE oDuckDBResult, VALUE col_idx) {
|
330
298
|
rubyDuckDBResult *ctx;
|
331
299
|
VALUE type = Qnil;
|
@@ -340,6 +308,7 @@ static VALUE duckdb_result__enum_internal_type(VALUE oDuckDBResult, VALUE col_id
|
|
340
308
|
return type;
|
341
309
|
}
|
342
310
|
|
311
|
+
/* :nodoc: */
|
343
312
|
static VALUE duckdb_result__enum_dictionary_size(VALUE oDuckDBResult, VALUE col_idx) {
|
344
313
|
rubyDuckDBResult *ctx;
|
345
314
|
VALUE size = Qnil;
|
@@ -354,6 +323,7 @@ static VALUE duckdb_result__enum_dictionary_size(VALUE oDuckDBResult, VALUE col_
|
|
354
323
|
return size;
|
355
324
|
}
|
356
325
|
|
326
|
+
/* :nodoc: */
|
357
327
|
static VALUE duckdb_result__enum_dictionary_value(VALUE oDuckDBResult, VALUE col_idx, VALUE idx) {
|
358
328
|
rubyDuckDBResult *ctx;
|
359
329
|
VALUE value = Qnil;
|
@@ -884,6 +854,9 @@ static VALUE vector_value(duckdb_vector vector, idx_t row_idx) {
|
|
884
854
|
}
|
885
855
|
|
886
856
|
void rbduckdb_init_duckdb_result(void) {
|
857
|
+
#if 0
|
858
|
+
VALUE mDuckDB = rb_define_module("DuckDB");
|
859
|
+
#endif
|
887
860
|
cDuckDBResult = rb_define_class_under(mDuckDB, "Result", rb_cObject);
|
888
861
|
id__to_date = rb_intern("_to_date");
|
889
862
|
id__to_time = rb_intern("_to_time");
|
@@ -902,11 +875,10 @@ void rbduckdb_init_duckdb_result(void) {
|
|
902
875
|
rb_define_alloc_func(cDuckDBResult, allocate);
|
903
876
|
|
904
877
|
rb_define_method(cDuckDBResult, "column_count", duckdb_result_column_count, 0);
|
905
|
-
rb_define_method(cDuckDBResult, "row_count", duckdb_result_row_count, 0); /* deprecated */
|
906
878
|
rb_define_method(cDuckDBResult, "rows_changed", duckdb_result_rows_changed, 0);
|
907
879
|
rb_define_method(cDuckDBResult, "columns", duckdb_result_columns, 0);
|
908
880
|
rb_define_method(cDuckDBResult, "streaming?", duckdb_result_streaming_p, 0);
|
909
|
-
|
881
|
+
rb_define_private_method(cDuckDBResult, "_chunk_each", duckdb_result__chunk_each, 0);
|
910
882
|
rb_define_private_method(cDuckDBResult, "_chunk_stream", duckdb_result__chunk_stream, 0);
|
911
883
|
rb_define_private_method(cDuckDBResult, "_column_type", duckdb_result__column_type, 1);
|
912
884
|
rb_define_private_method(cDuckDBResult, "_return_type", duckdb_result__return_type, 0);
|
data/ext/duckdb/ruby-duckdb.h
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
#define DUCKDB_NO_EXTENSION_FUNCTIONS // disable extension C-functions
|
6
6
|
|
7
7
|
#include "ruby.h"
|
8
|
+
#include "ruby/thread.h"
|
8
9
|
#include <duckdb.h>
|
9
10
|
|
10
11
|
#ifdef HAVE_DUCKDB_FETCH_CHUNK
|
@@ -24,6 +25,7 @@
|
|
24
25
|
#include "./connection.h"
|
25
26
|
#include "./result.h"
|
26
27
|
#include "./column.h"
|
28
|
+
#include "./logical_type.h"
|
27
29
|
#include "./prepared_statement.h"
|
28
30
|
#include "./extracted_statements.h"
|
29
31
|
#include "./pending_result.h"
|
data/lib/duckdb/appender.rb
CHANGED
@@ -13,15 +13,216 @@ module DuckDB
|
|
13
13
|
# con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
|
14
14
|
# appender = con.appender('users')
|
15
15
|
# appender.append_row(1, 'Alice')
|
16
|
-
#
|
17
16
|
class Appender
|
18
17
|
include DuckDB::Converter
|
19
18
|
|
19
|
+
# :stopdoc:
|
20
20
|
RANGE_INT16 = -32_768..32_767
|
21
21
|
RANGE_INT32 = -2_147_483_648..2_147_483_647
|
22
22
|
RANGE_INT64 = -9_223_372_036_854_775_808..9_223_372_036_854_775_807
|
23
|
+
private_constant :RANGE_INT16, :RANGE_INT32, :RANGE_INT64
|
24
|
+
# :startdoc:
|
25
|
+
|
26
|
+
# :call-seq:
|
27
|
+
# appender.begin_row -> self
|
28
|
+
# A nop method, provided for backwards compatibility reasons.
|
29
|
+
# Does nothing. Only `end_row` is required.
|
30
|
+
def begin_row
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
# call-seq:
|
35
|
+
# appender.end_row -> self
|
36
|
+
#
|
37
|
+
# Finish the current row of appends. After end_row is called, the next row can be appended.
|
38
|
+
# require 'duckdb'
|
39
|
+
# db = DuckDB::Database.open
|
40
|
+
# con = db.connect
|
41
|
+
# con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
|
42
|
+
# appender = con.appender('users')
|
43
|
+
# appender
|
44
|
+
# .append_int32(1)
|
45
|
+
# .append_varchar('Alice')
|
46
|
+
# .end_row
|
47
|
+
def end_row
|
48
|
+
return self if _end_row
|
49
|
+
|
50
|
+
raise_appender_error('failed to end_row')
|
51
|
+
end
|
52
|
+
|
53
|
+
# :call-seq:
|
54
|
+
# appender.flush -> self
|
55
|
+
#
|
56
|
+
# Flushes the appender to the table, forcing the cache of the appender to be cleared.
|
57
|
+
# If flushing the data triggers a constraint violation or any other error, then all
|
58
|
+
# data is invalidated, and this method raises DuckDB::Error.
|
59
|
+
#
|
60
|
+
# require 'duckdb'
|
61
|
+
# db = DuckDB::Database.open
|
62
|
+
# con = db.connect
|
63
|
+
# con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
|
64
|
+
# appender = con.appender('users')
|
65
|
+
# appender
|
66
|
+
# .append_int32(1)
|
67
|
+
# .append_varchar('Alice')
|
68
|
+
# .end_row
|
69
|
+
# .flush
|
70
|
+
def flush
|
71
|
+
return self if _flush
|
72
|
+
|
73
|
+
raise_appender_error('failed to flush')
|
74
|
+
end
|
75
|
+
|
76
|
+
# :call-seq:
|
77
|
+
# appender.close -> self
|
78
|
+
#
|
79
|
+
# Closes the appender by flushing all intermediate states and closing it for further appends.
|
80
|
+
# If flushing the data triggers a constraint violation or any other error, then all data is
|
81
|
+
# invalidated, and this method raises DuckDB::Error.
|
82
|
+
#
|
83
|
+
# require 'duckdb'
|
84
|
+
# db = DuckDB::Database.open
|
85
|
+
# con = db.connect
|
86
|
+
# con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
|
87
|
+
# appender = con.appender('users')
|
88
|
+
# appender
|
89
|
+
# .append_int32(1)
|
90
|
+
# .append_varchar('Alice')
|
91
|
+
# .end_row
|
92
|
+
# .close
|
93
|
+
def close
|
94
|
+
return self if _close
|
95
|
+
|
96
|
+
raise_appender_error('failed to close')
|
97
|
+
end
|
98
|
+
|
99
|
+
# call-seq:
|
100
|
+
# appender.append_bool(val) -> self
|
101
|
+
#
|
102
|
+
# Appends a boolean value to the current row in the appender.
|
103
|
+
#
|
104
|
+
# require 'duckdb'
|
105
|
+
# db = DuckDB::Database.open
|
106
|
+
# con = db.connect
|
107
|
+
# con.query('CREATE TABLE users (id INTEGER, active BOOLEAN)')
|
108
|
+
# appender = con.appender('users')
|
109
|
+
# appender
|
110
|
+
# .append_int32(1)
|
111
|
+
# .append_bool(true)
|
112
|
+
# .end_row
|
113
|
+
# .flush
|
114
|
+
def append_bool(value)
|
115
|
+
return self if _append_bool(value)
|
116
|
+
|
117
|
+
raise_appender_error('failed to append_bool')
|
118
|
+
end
|
119
|
+
|
120
|
+
# call-seq:
|
121
|
+
# appender.append_int8(val) -> self
|
122
|
+
#
|
123
|
+
# Appends an int8(TINYINT) value to the current row in the appender.
|
124
|
+
#
|
125
|
+
# require 'duckdb'
|
126
|
+
# db = DuckDB::Database.open
|
127
|
+
# con = db.connect
|
128
|
+
# con.query('CREATE TABLE users (id INTEGER, age TINYINT)')
|
129
|
+
# appender = con.appender('users')
|
130
|
+
# appender
|
131
|
+
# .append_int32(1)
|
132
|
+
# .append_int8(20)
|
133
|
+
# .end_row
|
134
|
+
# .flush
|
135
|
+
#
|
136
|
+
def append_int8(value)
|
137
|
+
return self if _append_int8(value)
|
138
|
+
|
139
|
+
raise_appender_error('failed to append_int8')
|
140
|
+
end
|
23
141
|
|
142
|
+
# call-seq:
|
143
|
+
# appender.append_int16(val) -> self
|
24
144
|
#
|
145
|
+
# Appends an int16(SMALLINT) value to the current row in the appender.
|
146
|
+
#
|
147
|
+
# require 'duckdb'
|
148
|
+
# db = DuckDB::Database.open
|
149
|
+
# con = db.connect
|
150
|
+
# con.query('CREATE TABLE users (id INTEGER, age SMALLINT)')
|
151
|
+
# appender = con.appender('users')
|
152
|
+
# appender
|
153
|
+
# .append_int32(1)
|
154
|
+
# .append_int16(20)
|
155
|
+
# .end_row
|
156
|
+
# .flush
|
157
|
+
def append_int16(value)
|
158
|
+
return self if _append_int16(value)
|
159
|
+
|
160
|
+
raise_appender_error('failed to append_int16')
|
161
|
+
end
|
162
|
+
|
163
|
+
# call-seq:
|
164
|
+
# appender.append_int32(val) -> self
|
165
|
+
#
|
166
|
+
# Appends an int32(INTEGER) value to the current row in the appender.
|
167
|
+
#
|
168
|
+
# require 'duckdb'
|
169
|
+
# db = DuckDB::Database.open
|
170
|
+
# con = db.connect
|
171
|
+
# con.query('CREATE TABLE users (id INTEGER, age INTEGER)')
|
172
|
+
# appender = con.appender('users')
|
173
|
+
# appender
|
174
|
+
# .append_int32(1)
|
175
|
+
# .append_int32(20)
|
176
|
+
# .end_row
|
177
|
+
# .flush
|
178
|
+
def append_int32(value)
|
179
|
+
return self if _append_int32(value)
|
180
|
+
|
181
|
+
raise_appender_error('failed to append_int32')
|
182
|
+
end
|
183
|
+
|
184
|
+
# call-seq:
|
185
|
+
# appender.append_int64(val) -> self
|
186
|
+
#
|
187
|
+
# Appends an int64(BIGINT) value to the current row in the appender.
|
188
|
+
#
|
189
|
+
# require 'duckdb'
|
190
|
+
# db = DuckDB::Database.open
|
191
|
+
# con = db.connect
|
192
|
+
# con.query('CREATE TABLE users (id INTEGER, age BIGINT)')
|
193
|
+
# appender = con.appender('users')
|
194
|
+
# appender
|
195
|
+
# .append_int32(1)
|
196
|
+
# .append_int64(20)
|
197
|
+
# .end_row
|
198
|
+
# .flush
|
199
|
+
def append_int64(value)
|
200
|
+
return self if _append_int64(value)
|
201
|
+
|
202
|
+
raise_appender_error('failed to append_int64')
|
203
|
+
end
|
204
|
+
|
205
|
+
# call-seq:
|
206
|
+
# appender.append_uint8(val) -> self
|
207
|
+
#
|
208
|
+
# Appends an uint8 value to the current row in the appender.
|
209
|
+
#
|
210
|
+
# require 'duckdb'
|
211
|
+
# db = DuckDB::Database.open
|
212
|
+
# con = db.connect
|
213
|
+
# con.query('CREATE TABLE users (id INTEGER, age UTINYINT)')
|
214
|
+
# appender = con.appender('users')
|
215
|
+
# appender
|
216
|
+
# .append_int32(1)
|
217
|
+
# .append_uint8(20)
|
218
|
+
# .end_row
|
219
|
+
# .flush
|
220
|
+
def append_uint8(value)
|
221
|
+
return self if _append_uint8(value)
|
222
|
+
|
223
|
+
raise_appender_error('failed to append_uint8')
|
224
|
+
end
|
225
|
+
|
25
226
|
# appends huge int value.
|
26
227
|
#
|
27
228
|
# require 'duckdb'
|
@@ -30,16 +231,13 @@ module DuckDB
|
|
30
231
|
# con.query('CREATE TABLE numbers (num HUGEINT)')
|
31
232
|
# appender = con.appender('numbers')
|
32
233
|
# appender
|
33
|
-
# .begin_row
|
34
234
|
# .append_hugeint(-170_141_183_460_469_231_731_687_303_715_884_105_727)
|
35
235
|
# .end_row
|
36
|
-
#
|
37
236
|
def append_hugeint(value)
|
38
237
|
lower, upper = integer_to_hugeint(value)
|
39
238
|
_append_hugeint(lower, upper)
|
40
239
|
end
|
41
240
|
|
42
|
-
#
|
43
241
|
# appends unsigned huge int value.
|
44
242
|
#
|
45
243
|
# require 'duckdb'
|
@@ -48,16 +246,13 @@ module DuckDB
|
|
48
246
|
# con.query('CREATE TABLE numbers (num UHUGEINT)')
|
49
247
|
# appender = con.appender('numbers')
|
50
248
|
# appender
|
51
|
-
# .begin_row
|
52
249
|
# .append_hugeint(340_282_366_920_938_463_463_374_607_431_768_211_455)
|
53
250
|
# .end_row
|
54
|
-
#
|
55
251
|
def append_uhugeint(value)
|
56
252
|
lower, upper = integer_to_hugeint(value)
|
57
253
|
_append_uhugeint(lower, upper)
|
58
254
|
end
|
59
255
|
|
60
|
-
#
|
61
256
|
# appends date value.
|
62
257
|
#
|
63
258
|
# require 'duckdb'
|
@@ -65,21 +260,18 @@ module DuckDB
|
|
65
260
|
# con = db.connect
|
66
261
|
# con.query('CREATE TABLE dates (date_value DATE)')
|
67
262
|
# appender = con.appender('dates')
|
68
|
-
# appender.begin_row
|
69
263
|
# appender.append_date(Date.today)
|
70
264
|
# # or
|
71
265
|
# # appender.append_date(Time.now)
|
72
266
|
# # appender.append_date('2021-10-10')
|
73
267
|
# appender.end_row
|
74
268
|
# appender.flush
|
75
|
-
#
|
76
269
|
def append_date(value)
|
77
|
-
date =
|
270
|
+
date = _parse_date(value)
|
78
271
|
|
79
272
|
_append_date(date.year, date.month, date.day)
|
80
273
|
end
|
81
274
|
|
82
|
-
#
|
83
275
|
# appends time value.
|
84
276
|
#
|
85
277
|
# require 'duckdb'
|
@@ -87,20 +279,17 @@ module DuckDB
|
|
87
279
|
# con = db.connect
|
88
280
|
# con.query('CREATE TABLE times (time_value TIME)')
|
89
281
|
# appender = con.appender('times')
|
90
|
-
# appender.begin_row
|
91
282
|
# appender.append_time(Time.now)
|
92
283
|
# # or
|
93
284
|
# # appender.append_time('01:01:01')
|
94
285
|
# appender.end_row
|
95
286
|
# appender.flush
|
96
|
-
#
|
97
287
|
def append_time(value)
|
98
288
|
time = _parse_time(value)
|
99
289
|
|
100
290
|
_append_time(time.hour, time.min, time.sec, time.usec)
|
101
291
|
end
|
102
292
|
|
103
|
-
#
|
104
293
|
# appends timestamp value.
|
105
294
|
#
|
106
295
|
# require 'duckdb'
|
@@ -108,21 +297,18 @@ module DuckDB
|
|
108
297
|
# con = db.connect
|
109
298
|
# con.query('CREATE TABLE timestamps (timestamp_value TIMESTAMP)')
|
110
299
|
# appender = con.appender('timestamps')
|
111
|
-
# appender.begin_row
|
112
300
|
# appender.append_time(Time.now)
|
113
301
|
# # or
|
114
302
|
# # appender.append_time(Date.today)
|
115
303
|
# # appender.append_time('2021-08-01 01:01:01')
|
116
304
|
# appender.end_row
|
117
305
|
# appender.flush
|
118
|
-
#
|
119
306
|
def append_timestamp(value)
|
120
307
|
time = to_time(value)
|
121
308
|
|
122
309
|
_append_timestamp(time.year, time.month, time.day, time.hour, time.min, time.sec, time.nsec / 1000)
|
123
310
|
end
|
124
311
|
|
125
|
-
#
|
126
312
|
# appends interval.
|
127
313
|
# The argument must be ISO8601 duration format.
|
128
314
|
# WARNING: This method is expremental.
|
@@ -133,17 +319,14 @@ module DuckDB
|
|
133
319
|
# con.query('CREATE TABLE intervals (interval_value INTERVAL)')
|
134
320
|
# appender = con.appender('intervals')
|
135
321
|
# appender
|
136
|
-
# .begin_row
|
137
322
|
# .append_interval('P1Y2D') # => append 1 year 2 days interval.
|
138
323
|
# .end_row
|
139
324
|
# .flush
|
140
|
-
#
|
141
325
|
def append_interval(value)
|
142
326
|
value = Interval.to_interval(value)
|
143
327
|
_append_interval(value.interval_months, value.interval_days, value.interval_micros)
|
144
328
|
end
|
145
329
|
|
146
|
-
#
|
147
330
|
# appends value.
|
148
331
|
#
|
149
332
|
# require 'duckdb'
|
@@ -151,11 +334,9 @@ module DuckDB
|
|
151
334
|
# con = db.connect
|
152
335
|
# con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
|
153
336
|
# appender = con.appender('users')
|
154
|
-
# appender.begin_row
|
155
337
|
# appender.append(1)
|
156
338
|
# appender.append('Alice')
|
157
339
|
# appender.end_row
|
158
|
-
#
|
159
340
|
def append(value)
|
160
341
|
case value
|
161
342
|
when NilClass
|
@@ -188,20 +369,16 @@ module DuckDB
|
|
188
369
|
end
|
189
370
|
end
|
190
371
|
|
191
|
-
#
|
192
372
|
# append a row.
|
193
373
|
#
|
194
374
|
# appender.append_row(1, 'Alice')
|
195
375
|
#
|
196
376
|
# is same as:
|
197
377
|
#
|
198
|
-
# appender.
|
199
|
-
# appender.append(1)
|
378
|
+
# appender.append(2)
|
200
379
|
# appender.append('Alice')
|
201
380
|
# appender.end_row
|
202
|
-
#
|
203
381
|
def append_row(*args)
|
204
|
-
begin_row
|
205
382
|
args.each do |arg|
|
206
383
|
append(arg)
|
207
384
|
end
|
@@ -210,35 +387,21 @@ module DuckDB
|
|
210
387
|
|
211
388
|
private
|
212
389
|
|
213
|
-
def
|
214
|
-
|
390
|
+
def raise_appender_error(default_message) # :nodoc:
|
391
|
+
message = error_message
|
392
|
+
raise DuckDB::Error, message || default_message
|
215
393
|
end
|
216
394
|
|
217
|
-
def
|
218
|
-
|
219
|
-
when Date, Time
|
220
|
-
value
|
221
|
-
else
|
222
|
-
begin
|
223
|
-
Date.parse(value)
|
224
|
-
rescue StandardError
|
225
|
-
raise(ArgumentError, "Cannot parse argument `#{value}` to Date.")
|
226
|
-
end
|
227
|
-
end
|
395
|
+
def blob?(value) # :nodoc:
|
396
|
+
value.instance_of?(DuckDB::Blob) || value.encoding == Encoding::BINARY
|
228
397
|
end
|
229
398
|
|
230
|
-
def to_time(value)
|
399
|
+
def to_time(value) # :nodoc:
|
231
400
|
case value
|
232
|
-
when Time
|
233
|
-
value
|
234
401
|
when Date
|
235
402
|
value.to_time
|
236
403
|
else
|
237
|
-
|
238
|
-
Time.parse(value)
|
239
|
-
rescue StandardError
|
240
|
-
raise(ArgumentError, "Cannot parse argument `#{value}` to Time or Date.")
|
241
|
-
end
|
404
|
+
_parse_time(value)
|
242
405
|
end
|
243
406
|
end
|
244
407
|
end
|
data/lib/duckdb/column.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
module DuckDB
|
4
4
|
class Column
|
5
|
-
#
|
6
5
|
# returns column type symbol
|
7
6
|
# `:unknown` means that the column type is unknown/unsupported by ruby-duckdb.
|
8
7
|
# `:invalid` means that the column type is invalid in duckdb.
|
@@ -15,7 +14,6 @@ module DuckDB
|
|
15
14
|
# users = con.query('SELECT * FROM users')
|
16
15
|
# columns = users.columns
|
17
16
|
# columns.first.type #=> :integer
|
18
|
-
#
|
19
17
|
def type
|
20
18
|
type_id = _type
|
21
19
|
DuckDB::Converter::IntToSym.type_to_sym(type_id)
|
data/lib/duckdb/interval.rb
CHANGED
@@ -24,11 +24,11 @@ module DuckDB
|
|
24
24
|
# con.query('CREATE TABLE intervals (interval_value INTERVAL)')
|
25
25
|
# appender = con.appender('intervals')
|
26
26
|
# appender
|
27
|
-
# .begin_row
|
28
27
|
# .append_interval(interval)
|
29
28
|
# .end_row
|
30
29
|
# .flush
|
31
30
|
class Interval
|
31
|
+
# :stopdoc:
|
32
32
|
ISO8601_REGEXP = Regexp.compile(
|
33
33
|
'(?<negativ>-{0,1})P
|
34
34
|
(?<year>-{0,1}\d+Y){0,1}
|
@@ -40,6 +40,8 @@ module DuckDB
|
|
40
40
|
((?<sec>-{0,1}\d+)\.{0,1}(?<usec>\d*)S){0,1}',
|
41
41
|
Regexp::EXTENDED
|
42
42
|
)
|
43
|
+
private_constant :ISO8601_REGEXP
|
44
|
+
# :startdoc:
|
43
45
|
|
44
46
|
class << self
|
45
47
|
# parses the ISO8601 format string and return the Interval object.
|
@@ -93,7 +95,7 @@ module DuckDB
|
|
93
95
|
|
94
96
|
private
|
95
97
|
|
96
|
-
def matched_to_i(matched)
|
98
|
+
def matched_to_i(matched) # :nodoc:
|
97
99
|
sign = to_sign(matched)
|
98
100
|
sec = to_sec(matched)
|
99
101
|
usec = to_usec(matched)
|
@@ -104,35 +106,35 @@ module DuckDB
|
|
104
106
|
sign.positive? ? value : value.map { |v| v * sign }
|
105
107
|
end
|
106
108
|
|
107
|
-
def to_sign(matched)
|
109
|
+
def to_sign(matched) # :nodoc:
|
108
110
|
matched[:negativ] == '-' ? -1 : 1
|
109
111
|
end
|
110
112
|
|
111
|
-
def to_year(matched)
|
113
|
+
def to_year(matched) # :nodoc:
|
112
114
|
matched[:year].to_i
|
113
115
|
end
|
114
116
|
|
115
|
-
def to_month(matched)
|
117
|
+
def to_month(matched) # :nodoc:
|
116
118
|
matched[:month].to_i
|
117
119
|
end
|
118
120
|
|
119
|
-
def to_day(matched)
|
121
|
+
def to_day(matched) # :nodoc:
|
120
122
|
matched[:day].to_i
|
121
123
|
end
|
122
124
|
|
123
|
-
def to_hour(matched)
|
125
|
+
def to_hour(matched) # :nodoc:
|
124
126
|
matched[:hour].to_i
|
125
127
|
end
|
126
128
|
|
127
|
-
def to_min(matched)
|
129
|
+
def to_min(matched) # :nodoc:
|
128
130
|
matched[:min].to_i
|
129
131
|
end
|
130
132
|
|
131
|
-
def to_sec(matched)
|
133
|
+
def to_sec(matched) # :nodoc:
|
132
134
|
matched[:sec].to_i
|
133
135
|
end
|
134
136
|
|
135
|
-
def to_usec(matched)
|
137
|
+
def to_usec(matched) # :nodoc:
|
136
138
|
matched[:usec].to_s.ljust(6, '0')[0, 6].to_i
|
137
139
|
end
|
138
140
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DuckDB
|
4
|
+
class LogicalType
|
5
|
+
# returns logical type's type symbol
|
6
|
+
# `:unknown` means that the logical type's type is unknown/unsupported by ruby-duckdb.
|
7
|
+
# `:invalid` means that the logical type's type is invalid in duckdb.
|
8
|
+
#
|
9
|
+
# require 'duckdb'
|
10
|
+
# db = DuckDB::Database.open
|
11
|
+
# con = db.connect
|
12
|
+
# con.query('CREATE TABLE climates (id INTEGER, temperature DECIMAIL)')
|
13
|
+
#
|
14
|
+
# users = con.query('SELECT * FROM climates')
|
15
|
+
# columns = users.columns
|
16
|
+
# columns.second.logical_type.type #=> :decimal
|
17
|
+
def type
|
18
|
+
type_id = _type
|
19
|
+
DuckDB::Converter::IntToSym.type_to_sym(type_id)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|