duckdb 1.1.3.1 → 1.2.1.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.
@@ -13,16 +13,425 @@ 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
141
+
142
+ # call-seq:
143
+ # appender.append_int16(val) -> self
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
+
226
+ # call-seq:
227
+ # appender.append_uint16(val) -> self
228
+ #
229
+ # Appends an uint16 value to the current row in the appender.
230
+ #
231
+ # require 'duckdb'
232
+ # db = DuckDB::Database.open
233
+ # con = db.connect
234
+ # con.query('CREATE TABLE users (id INTEGER, age USMALLINT)')
235
+ # appender = con.appender('users')
236
+ # appender
237
+ # .append_int32(1)
238
+ # .append_uint16(20)
239
+ # .end_row
240
+ # .flush
241
+ def append_uint16(value)
242
+ return self if _append_uint16(value)
243
+
244
+ raise_appender_error('failed to append_uint16')
245
+ end
246
+
247
+ # call-seq:
248
+ # appender.append_uint32(val) -> self
249
+ #
250
+ # Appends an uint32 value to the current row in the appender.
251
+ #
252
+ # require 'duckdb'
253
+ # db = DuckDB::Database.open
254
+ # con = db.connect
255
+ # con.query('CREATE TABLE users (id INTEGER, age UINTEGER)')
256
+ # appender = con.appender('users')
257
+ # appender
258
+ # .append_int32(1)
259
+ # .append_uint32(20)
260
+ # .end_row
261
+ # .flush
262
+ def append_uint32(value)
263
+ return self if _append_uint32(value)
264
+
265
+ raise_appender_error('failed to append_uint32')
266
+ end
267
+
268
+ # call-seq:
269
+ # appender.append_uint64(val) -> self
270
+ #
271
+ # Appends an uint64 value to the current row in the appender.
272
+ #
273
+ # require 'duckdb'
274
+ # db = DuckDB::Database.open
275
+ # con = db.connect
276
+ # con.query('CREATE TABLE users (id INTEGER, age UBIGINT)')
277
+ # appender = con.appender('users')
278
+ # Appender
279
+ # .append_int32(1)
280
+ # .append_uint64(20)
281
+ # .end_row
282
+ # .flush
283
+ def append_uint64(value)
284
+ return self if _append_uint64(value)
285
+
286
+ raise_appender_error('failed to append_uint64')
287
+ end
288
+
289
+ # call-seq:
290
+ # appender.append_float(val) -> self
291
+ #
292
+ # Appends a float value to the current row in the appender.
293
+ #
294
+ # require 'duckdb'
295
+ # db = DuckDB::Database.open
296
+ # con = db.connect
297
+ # con.query('CREATE TABLE numbers (num FLOAT)')
298
+ # appender = con.appender('numbers')
299
+ # appender
300
+ # .append_float(1.23)
301
+ # .end_row
302
+ # .flush
303
+ def append_float(value)
304
+ return self if _append_float(value)
305
+
306
+ raise_appender_error('failed to append_float')
307
+ end
308
+
309
+ # call-seq:
310
+ # appender.append_double(val) -> self
311
+ #
312
+ # Appends a double value to the current row in the appender.
313
+ #
314
+ # require 'duckdb'
315
+ # db = DuckDB::Database.open
316
+ # con = db.connect
317
+ # con.query('CREATE TABLE numbers (num DOUBLE)')
318
+ # appender = con.appender('numbers')
319
+ # appender
320
+ # .append_double(1.23)
321
+ # .end_row
322
+ # .flush
323
+ def append_double(value)
324
+ return self if _append_double(value)
325
+
326
+ raise_appender_error('failed to append_double')
327
+ end
328
+
329
+ # call-seq:
330
+ # appender.append_varchar(val) -> self
331
+ #
332
+ # Appends a varchar value to the current row in the appender.
333
+ #
334
+ # require 'duckdb'
335
+ # db = DuckDB::Database.open
336
+ # con = db.connect
337
+ # con.query('CREATE TABLE names (name VARCHAR)')
338
+ # appender = con.appender('names')
339
+ # appender
340
+ # .append_varchar('Alice')
341
+ # .end_row
342
+ # .flush
343
+ def append_varchar(value)
344
+ return self if _append_varchar(value)
345
+
346
+ raise_appender_error('failed to append_varchar')
347
+ end
348
+
349
+ # call-seq:
350
+ # appender.append_varchar_length(val, len) -> self
351
+ #
352
+ # Appends a varchar value to the current row in the appender.
353
+ #
354
+ # require 'duckdb'
355
+ # db = DuckDB::Database.open
356
+ # con = db.connect
357
+ # con.query('CREATE TABLE names (name VARCHAR)')
358
+ # appender = con.appender('names')
359
+ # appender
360
+ # .append_varchar_length('Alice', 5)
361
+ # .end_row
362
+ # .flush
363
+ def append_varchar_length(value, length)
364
+ return self if _append_varchar_length(value, length)
365
+
366
+ raise_appender_error('failed to append_varchar_length')
367
+ end
368
+
369
+ # call-seq:
370
+ # appender.append_blob(val) -> self
371
+ #
372
+ # Appends a varchar value to the current row in the appender.
373
+ #
374
+ # require 'duckdb'
375
+ # db = DuckDB::Database.open
376
+ # con = db.connect
377
+ # con.query('CREATE TABLE values (value BLOB)')
378
+ # appender = con.appender('values')
379
+ # appender
380
+ # .append('\0\1\2\3\4\5'.encode(Encoding::BINARY))
381
+ # .end_row
382
+ # .flush
383
+ def append_blob(value)
384
+ return self if _append_blob(value)
385
+
386
+ raise_appender_error('failed to append_blob')
387
+ end
388
+
389
+ # call-seq:
390
+ # appender.append_null -> self
391
+ #
392
+ # Appends a NULL value to the current row in the appender.
393
+ #
394
+ # require 'duckdb'
395
+ # db = DuckDB::Database.open
396
+ # con = db.connect
397
+ # con.query('CREATE TABLE values (value INTEGER)')
398
+ # appender = con.appender('values')
399
+ # appender
400
+ # .append_null
401
+ # .end_row
402
+ # .flush
403
+ def append_null
404
+ return self if _append_null
405
+
406
+ raise_appender_error('failed to append_null')
407
+ end
408
+
409
+ # call-seq:
410
+ # appender.append_default -> self
411
+ #
412
+ # Appends a default value to the current row in the appender.
413
+ # If the column does not have a default value, this method
414
+ # appends a NULL value.
415
+ #
416
+ # require 'duckdb'
417
+ # db = DuckDB::Database.open
418
+ # con = db.connect
419
+ # con.query('CREATE TABLE values (value INTEGER DEFAULT 1)')
420
+ # appender = con.appender('values')
421
+ # appender
422
+ # .append_default
423
+ # .end_row
424
+ # .flush
425
+ def append_default
426
+ return self if _append_default
23
427
 
428
+ raise_appender_error('failed to append_default')
429
+ end
430
+
431
+ # call-seq:
432
+ # appender.append_hugeint(val) -> self
24
433
  #
25
- # appends huge int value.
434
+ # Appends a huge int value to the current row in the appender.
26
435
  #
27
436
  # require 'duckdb'
28
437
  # db = DuckDB::Database.open
@@ -30,17 +439,21 @@ module DuckDB
30
439
  # con.query('CREATE TABLE numbers (num HUGEINT)')
31
440
  # appender = con.appender('numbers')
32
441
  # appender
33
- # .begin_row
34
442
  # .append_hugeint(-170_141_183_460_469_231_731_687_303_715_884_105_727)
35
443
  # .end_row
36
- #
444
+ # .flush
37
445
  def append_hugeint(value)
38
446
  lower, upper = integer_to_hugeint(value)
39
- _append_hugeint(lower, upper)
447
+
448
+ return self if _append_hugeint(lower, upper)
449
+
450
+ raise_appender_error('failed to append_hugeint')
40
451
  end
41
452
 
453
+ # call-seq:
454
+ # appender.append_uhugeint(val) -> self
42
455
  #
43
- # appends unsigned huge int value.
456
+ # Appends an unsigned huge int value to the current row in the appender.
44
457
  #
45
458
  # require 'duckdb'
46
459
  # db = DuckDB::Database.open
@@ -48,84 +461,93 @@ module DuckDB
48
461
  # con.query('CREATE TABLE numbers (num UHUGEINT)')
49
462
  # appender = con.appender('numbers')
50
463
  # appender
51
- # .begin_row
52
464
  # .append_hugeint(340_282_366_920_938_463_463_374_607_431_768_211_455)
53
465
  # .end_row
54
- #
466
+ # .flush
55
467
  def append_uhugeint(value)
56
468
  lower, upper = integer_to_hugeint(value)
57
- _append_uhugeint(lower, upper)
469
+
470
+ return self if _append_uhugeint(lower, upper)
471
+
472
+ raise_appender_error('failed to append_uhugeint')
58
473
  end
59
474
 
475
+ # call-seq:
476
+ # appender.append_date(val) -> self
60
477
  #
61
- # appends date value.
478
+ # Appends a date value to the current row in the appender.
62
479
  #
63
480
  # require 'duckdb'
64
481
  # db = DuckDB::Database.open
65
482
  # con = db.connect
66
483
  # con.query('CREATE TABLE dates (date_value DATE)')
67
484
  # appender = con.appender('dates')
68
- # appender.begin_row
69
485
  # appender.append_date(Date.today)
70
486
  # # or
71
487
  # # appender.append_date(Time.now)
72
488
  # # appender.append_date('2021-10-10')
73
489
  # appender.end_row
74
490
  # appender.flush
75
- #
76
491
  def append_date(value)
77
- date = to_date(value)
492
+ date = _parse_date(value)
493
+
494
+ return self if _append_date(date.year, date.month, date.day)
78
495
 
79
- _append_date(date.year, date.month, date.day)
496
+ raise_appender_error('failed to append_date')
80
497
  end
81
498
 
499
+ # call-seq:
500
+ # appender.append_time(val) -> self
82
501
  #
83
- # appends time value.
502
+ # Appends a time value to the current row in the appender.
84
503
  #
85
504
  # require 'duckdb'
86
505
  # db = DuckDB::Database.open
87
506
  # con = db.connect
88
507
  # con.query('CREATE TABLE times (time_value TIME)')
89
508
  # appender = con.appender('times')
90
- # appender.begin_row
91
509
  # appender.append_time(Time.now)
92
510
  # # or
93
511
  # # appender.append_time('01:01:01')
94
512
  # appender.end_row
95
513
  # appender.flush
96
- #
97
514
  def append_time(value)
98
515
  time = _parse_time(value)
99
516
 
100
- _append_time(time.hour, time.min, time.sec, time.usec)
517
+ return self if _append_time(time.hour, time.min, time.sec, time.usec)
518
+
519
+ raise_appender_error('failed to append_time')
101
520
  end
102
521
 
522
+ # call-seq:
523
+ # appender.append_timestamp(val) -> self
103
524
  #
104
- # appends timestamp value.
525
+ # Appends a timestamp value to the current row in the appender.
105
526
  #
106
527
  # require 'duckdb'
107
528
  # db = DuckDB::Database.open
108
529
  # con = db.connect
109
530
  # con.query('CREATE TABLE timestamps (timestamp_value TIMESTAMP)')
110
531
  # appender = con.appender('timestamps')
111
- # appender.begin_row
112
532
  # appender.append_time(Time.now)
113
533
  # # or
114
534
  # # appender.append_time(Date.today)
115
535
  # # appender.append_time('2021-08-01 01:01:01')
116
536
  # appender.end_row
117
537
  # appender.flush
118
- #
119
538
  def append_timestamp(value)
120
539
  time = to_time(value)
121
540
 
122
- _append_timestamp(time.year, time.month, time.day, time.hour, time.min, time.sec, time.nsec / 1000)
541
+ return self if _append_timestamp(time.year, time.month, time.day, time.hour, time.min, time.sec, time.nsec / 1000)
542
+
543
+ raise_appender_error('failed to append_timestamp')
123
544
  end
124
545
 
546
+ # call-seq:
547
+ # appender.append_interval(val) -> self
125
548
  #
126
- # appends interval.
549
+ # Appends an interval value to the current row in the appender.
127
550
  # The argument must be ISO8601 duration format.
128
- # WARNING: This method is expremental.
129
551
  #
130
552
  # require 'duckdb'
131
553
  # db = DuckDB::Database.open
@@ -133,17 +555,17 @@ module DuckDB
133
555
  # con.query('CREATE TABLE intervals (interval_value INTERVAL)')
134
556
  # appender = con.appender('intervals')
135
557
  # appender
136
- # .begin_row
137
558
  # .append_interval('P1Y2D') # => append 1 year 2 days interval.
138
559
  # .end_row
139
560
  # .flush
140
- #
141
561
  def append_interval(value)
142
562
  value = Interval.to_interval(value)
143
- _append_interval(value.interval_months, value.interval_days, value.interval_micros)
563
+
564
+ return self if _append_interval(value.interval_months, value.interval_days, value.interval_micros)
565
+
566
+ raise_appender_error('failed to append_interval')
144
567
  end
145
568
 
146
- #
147
569
  # appends value.
148
570
  #
149
571
  # require 'duckdb'
@@ -151,11 +573,9 @@ module DuckDB
151
573
  # con = db.connect
152
574
  # con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
153
575
  # appender = con.appender('users')
154
- # appender.begin_row
155
576
  # appender.append(1)
156
577
  # appender.append('Alice')
157
578
  # appender.end_row
158
- #
159
579
  def append(value)
160
580
  case value
161
581
  when NilClass
@@ -188,20 +608,16 @@ module DuckDB
188
608
  end
189
609
  end
190
610
 
191
- #
192
611
  # append a row.
193
612
  #
194
613
  # appender.append_row(1, 'Alice')
195
614
  #
196
615
  # is same as:
197
616
  #
198
- # appender.begin_row
199
- # appender.append(1)
617
+ # appender.append(2)
200
618
  # appender.append('Alice')
201
619
  # appender.end_row
202
- #
203
620
  def append_row(*args)
204
- begin_row
205
621
  args.each do |arg|
206
622
  append(arg)
207
623
  end
@@ -210,35 +626,21 @@ module DuckDB
210
626
 
211
627
  private
212
628
 
213
- def blob?(value)
214
- value.instance_of?(DuckDB::Blob) || value.encoding == Encoding::BINARY
629
+ def raise_appender_error(default_message) # :nodoc:
630
+ message = error_message
631
+ raise DuckDB::Error, message || default_message
215
632
  end
216
633
 
217
- def to_date(value)
218
- case value
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
634
+ def blob?(value) # :nodoc:
635
+ value.instance_of?(DuckDB::Blob) || value.encoding == Encoding::BINARY
228
636
  end
229
637
 
230
- def to_time(value)
638
+ def to_time(value) # :nodoc:
231
639
  case value
232
- when Time
233
- value
234
640
  when Date
235
641
  value.to_time
236
642
  else
237
- begin
238
- Time.parse(value)
239
- rescue StandardError
240
- raise(ArgumentError, "Cannot parse argument `#{value}` to Time or Date.")
241
- end
643
+ _parse_time(value)
242
644
  end
243
645
  end
244
646
  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)