duckdb 0.2.8.0 → 0.3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test_on_macos.yml +21 -4
- data/.github/workflows/test_on_ubuntu.yml +26 -37
- data/.github/workflows/test_on_windows.yml +22 -9
- data/CHANGELOG.md +37 -0
- data/CONTRIBUTION.md +24 -0
- data/Gemfile.lock +2 -1
- data/README.md +31 -3
- data/duckdb.gemspec +2 -2
- data/ext/duckdb/appender.c +117 -4
- data/ext/duckdb/blob.c +1 -5
- data/ext/duckdb/blob.h +0 -4
- data/ext/duckdb/config.c +3 -5
- data/ext/duckdb/connection.c +14 -15
- data/ext/duckdb/database.c +10 -16
- data/ext/duckdb/duckdb.c +1 -7
- data/ext/duckdb/error.c +1 -2
- data/ext/duckdb/extconf.rb +29 -8
- data/ext/duckdb/prepared_statement.c +136 -40
- data/ext/duckdb/result.c +70 -41
- data/ext/duckdb/ruby-duckdb.h +1 -16
- data/ext/duckdb/util.c +45 -0
- data/ext/duckdb/util.h +13 -0
- data/lib/duckdb/appender.rb +158 -10
- data/lib/duckdb/config.rb +1 -4
- data/lib/duckdb/converter.rb +52 -0
- data/lib/duckdb/prepared_statement.rb +114 -10
- data/lib/duckdb/version.rb +1 -1
- data/lib/duckdb.rb +1 -0
- metadata +8 -5
- data/.travis.yml +0 -18
data/ext/duckdb/ruby-duckdb.h
CHANGED
@@ -8,13 +8,9 @@
|
|
8
8
|
#include "./connection.h"
|
9
9
|
#include "./result.h"
|
10
10
|
#include "./prepared_statement.h"
|
11
|
-
|
12
|
-
#ifdef HAVE_DUCKDB_VALUE_BLOB
|
11
|
+
#include "./util.h"
|
13
12
|
|
14
13
|
#include "./blob.h"
|
15
|
-
|
16
|
-
#endif /* HAVE_DUCKDB_VALUE_BLOB */
|
17
|
-
|
18
14
|
#ifdef HAVE_DUCKDB_APPENDER_CREATE
|
19
15
|
|
20
16
|
#include "./appender.h"
|
@@ -30,19 +26,8 @@
|
|
30
26
|
extern VALUE mDuckDB;
|
31
27
|
extern VALUE cDuckDBDatabase;
|
32
28
|
extern VALUE cDuckDBConnection;
|
33
|
-
|
34
|
-
#ifdef HAVE_DUCKDB_VALUE_BLOB
|
35
|
-
|
36
29
|
extern VALUE cDuckDBBlob;
|
37
|
-
|
38
|
-
#endif /* HAVE_DUCKDB_VALUE_BLOB */
|
39
|
-
|
40
|
-
#ifdef HAVE_DUCKDB_CREATE_CONFIG
|
41
|
-
|
42
30
|
extern VALUE cDuckDBConfig;
|
43
|
-
|
44
|
-
#endif /* HAVE_DUCKDB_CREATE_CONFIG */
|
45
|
-
|
46
31
|
extern VALUE eDuckDBError;
|
47
32
|
|
48
33
|
#endif
|
data/ext/duckdb/util.c
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#include "ruby-duckdb.h"
|
2
|
+
|
3
|
+
#ifdef HAVE_DUCKDB_APPEND_DATE
|
4
|
+
|
5
|
+
duckdb_date to_duckdb_date_from_value(VALUE year, VALUE month, VALUE day) {
|
6
|
+
duckdb_date_struct dt_struct;
|
7
|
+
|
8
|
+
dt_struct.year = NUM2INT(year);
|
9
|
+
dt_struct.month = NUM2INT(month);
|
10
|
+
dt_struct.day = NUM2INT(day);
|
11
|
+
|
12
|
+
return duckdb_to_date(dt_struct);
|
13
|
+
}
|
14
|
+
|
15
|
+
duckdb_time to_duckdb_time_from_value(VALUE hour, VALUE min, VALUE sec, VALUE micros) {
|
16
|
+
duckdb_time_struct time_st;
|
17
|
+
|
18
|
+
time_st.hour = NUM2INT(hour);
|
19
|
+
time_st.min = NUM2INT(min);
|
20
|
+
time_st.sec = NUM2INT(sec);
|
21
|
+
time_st.micros = NUM2INT(micros);
|
22
|
+
|
23
|
+
return duckdb_to_time(time_st);
|
24
|
+
}
|
25
|
+
|
26
|
+
duckdb_timestamp to_duckdb_timestamp_from_value(VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros) {
|
27
|
+
duckdb_timestamp_struct timestamp_st;
|
28
|
+
|
29
|
+
timestamp_st.date.year = NUM2INT(year);
|
30
|
+
timestamp_st.date.month = NUM2INT(month);
|
31
|
+
timestamp_st.date.day = NUM2INT(day);
|
32
|
+
timestamp_st.time.hour = NUM2INT(hour);
|
33
|
+
timestamp_st.time.min = NUM2INT(min);
|
34
|
+
timestamp_st.time.sec = NUM2INT(sec);
|
35
|
+
timestamp_st.time.micros = NUM2INT(micros);
|
36
|
+
|
37
|
+
return duckdb_to_timestamp(timestamp_st);
|
38
|
+
}
|
39
|
+
|
40
|
+
void to_duckdb_interval_from_value(duckdb_interval* interval, VALUE months, VALUE days, VALUE micros) {
|
41
|
+
interval->months = NUM2INT(months);
|
42
|
+
interval->days = NUM2INT(days);
|
43
|
+
interval->micros = NUM2LL(micros);
|
44
|
+
}
|
45
|
+
#endif
|
data/ext/duckdb/util.h
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#ifndef RUBY_DUCKDB_UTIL_H
|
2
|
+
#define RUBY_DUCKDB_UTIL_H
|
3
|
+
|
4
|
+
#ifdef HAVE_DUCKDB_APPEND_DATE
|
5
|
+
|
6
|
+
duckdb_date to_duckdb_date_from_value(VALUE year, VALUE month, VALUE day);
|
7
|
+
duckdb_time to_duckdb_time_from_value(VALUE hour, VALUE min, VALUE sec, VALUE micros);
|
8
|
+
duckdb_timestamp to_duckdb_timestamp_from_value(VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros);
|
9
|
+
void to_duckdb_interval_from_value(duckdb_interval* interval, VALUE months, VALUE days, VALUE micros);
|
10
|
+
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#endif
|
data/lib/duckdb/appender.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'date'
|
2
|
+
require 'time'
|
3
|
+
require_relative './converter'
|
2
4
|
|
3
5
|
module DuckDB
|
4
6
|
if defined?(DuckDB::Appender)
|
@@ -12,19 +14,161 @@ module DuckDB
|
|
12
14
|
# appender.append_row(1, 'Alice')
|
13
15
|
#
|
14
16
|
class Appender
|
17
|
+
include DuckDB::Converter
|
18
|
+
|
15
19
|
RANGE_INT16 = -32_768..32_767
|
16
20
|
RANGE_INT32 = -2_147_483_648..2_147_483_647
|
17
21
|
RANGE_INT64 = -9_223_372_036_854_775_808..9_223_372_036_854_775_807
|
18
22
|
|
23
|
+
#
|
24
|
+
# appends huge int value.
|
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
|
+
#
|
19
36
|
def append_hugeint(value)
|
20
37
|
case value
|
21
38
|
when Integer
|
22
|
-
|
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
|
23
47
|
else
|
24
|
-
|
48
|
+
raise(ArgumentError, "2nd argument `#{value}` must be Integer.")
|
25
49
|
end
|
26
50
|
end
|
27
51
|
|
52
|
+
#
|
53
|
+
# appends date value.
|
54
|
+
#
|
55
|
+
# require 'duckdb'
|
56
|
+
# db = DuckDB::Database.open
|
57
|
+
# con = db.connect
|
58
|
+
# con.query('CREATE TABLE dates (date_value DATE)')
|
59
|
+
# appender = con.appender('dates')
|
60
|
+
# appender.begin_row
|
61
|
+
# appender.append_date(Date.today)
|
62
|
+
# # or
|
63
|
+
# # appender.append_date(Time.now)
|
64
|
+
# # appender.append_date('2021-10-10')
|
65
|
+
# appender.end_row
|
66
|
+
# appender.flush
|
67
|
+
#
|
68
|
+
def append_date(value)
|
69
|
+
date = case value
|
70
|
+
when Date, Time
|
71
|
+
value
|
72
|
+
else
|
73
|
+
begin
|
74
|
+
Date.parse(value)
|
75
|
+
rescue
|
76
|
+
raise(ArgumentError, "Cannot parse argument `#{value}` to Date.")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
_append_date(date.year, date.month, date.day)
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# appends time value.
|
85
|
+
#
|
86
|
+
# require 'duckdb'
|
87
|
+
# db = DuckDB::Database.open
|
88
|
+
# con = db.connect
|
89
|
+
# con.query('CREATE TABLE times (time_value TIME)')
|
90
|
+
# appender = con.appender('times')
|
91
|
+
# appender.begin_row
|
92
|
+
# appender.append_time(Time.now)
|
93
|
+
# # or
|
94
|
+
# # appender.append_time('01:01:01')
|
95
|
+
# appender.end_row
|
96
|
+
# appender.flush
|
97
|
+
#
|
98
|
+
def append_time(value)
|
99
|
+
time = case value
|
100
|
+
when Time
|
101
|
+
value
|
102
|
+
else
|
103
|
+
begin
|
104
|
+
Time.parse(value)
|
105
|
+
rescue
|
106
|
+
raise(ArgumentError, "Cannot parse argument `#{value}` to Time.")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
_append_time(time.hour, time.min, time.sec, time.usec)
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# appends timestamp value.
|
115
|
+
#
|
116
|
+
# require 'duckdb'
|
117
|
+
# db = DuckDB::Database.open
|
118
|
+
# con = db.connect
|
119
|
+
# con.query('CREATE TABLE timestamps (timestamp_value TIMESTAMP)')
|
120
|
+
# appender = con.appender('timestamps')
|
121
|
+
# appender.begin_row
|
122
|
+
# appender.append_time(Time.now)
|
123
|
+
# # or
|
124
|
+
# # appender.append_time(Date.today)
|
125
|
+
# # appender.append_time('2021-08-01 01:01:01')
|
126
|
+
# appender.end_row
|
127
|
+
# appender.flush
|
128
|
+
#
|
129
|
+
def append_timestamp(value)
|
130
|
+
time = case value
|
131
|
+
when Time
|
132
|
+
value
|
133
|
+
when Date
|
134
|
+
value.to_time
|
135
|
+
else
|
136
|
+
begin
|
137
|
+
Time.parse(value)
|
138
|
+
rescue
|
139
|
+
raise(ArgumentError, "Cannot parse argument `#{value}` to Time or Date.")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
_append_timestamp(time.year, time.month, time.day, time.hour, time.min, time.sec, time.nsec / 1000)
|
144
|
+
end
|
145
|
+
|
146
|
+
#
|
147
|
+
# appends interval.
|
148
|
+
# The argument must be ISO8601 duration format.
|
149
|
+
# WARNING: This method is expremental.
|
150
|
+
#
|
151
|
+
# require 'duckdb'
|
152
|
+
# db = DuckDB::Database.open
|
153
|
+
# con = db.connect
|
154
|
+
# con.query('CREATE TABLE intervals (interval_value INTERVAL)')
|
155
|
+
# appender = con.appender('intervals')
|
156
|
+
# appender
|
157
|
+
# .begin_row
|
158
|
+
# .append_interval('P1Y2D') # => append 1 year 2 days interval.
|
159
|
+
# .end_row
|
160
|
+
# .flush
|
161
|
+
#
|
162
|
+
def append_interval(value)
|
163
|
+
raise ArgumentError, "Argument `#{value}` must be a string." unless value.is_a?(String)
|
164
|
+
|
165
|
+
hash = iso8601_interval_to_hash(value)
|
166
|
+
|
167
|
+
months, days, micros = hash_to__append_interval_args(hash)
|
168
|
+
|
169
|
+
_append_interval(months, days, micros)
|
170
|
+
end
|
171
|
+
|
28
172
|
#
|
29
173
|
# appends value.
|
30
174
|
#
|
@@ -56,19 +200,23 @@ module DuckDB
|
|
56
200
|
append_hugeint(value)
|
57
201
|
end
|
58
202
|
when String
|
59
|
-
|
60
|
-
blob?(value) ? append_blob(value) : append_varchar(value)
|
61
|
-
else
|
62
|
-
append_varchar(value)
|
63
|
-
end
|
203
|
+
blob?(value) ? append_blob(value) : append_varchar(value)
|
64
204
|
when TrueClass, FalseClass
|
65
205
|
append_bool(value)
|
66
206
|
when Time
|
67
|
-
|
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
|
68
212
|
when Date
|
69
|
-
|
213
|
+
if respond_to?(:append_date)
|
214
|
+
append_date(value)
|
215
|
+
else
|
216
|
+
append_varchar(value.strftime('%Y-%m-%d'))
|
217
|
+
end
|
70
218
|
else
|
71
|
-
|
219
|
+
raise(DuckDB::Error, "not supported type #{value} (#{value.class})")
|
72
220
|
end
|
73
221
|
end
|
74
222
|
|
data/lib/duckdb/config.rb
CHANGED
@@ -34,10 +34,7 @@ module DuckDB
|
|
34
34
|
# configs['default_order'] # => "The order type used when none is specified ([ASC] or DESC)"
|
35
35
|
#
|
36
36
|
def key_descriptions
|
37
|
-
|
38
|
-
|
39
|
-
n = size
|
40
|
-
@key_descriptions = (0...n).each_with_object({}) do |i, hash|
|
37
|
+
@key_descriptions ||= (0...size).each_with_object({}) do |i, hash|
|
41
38
|
key, description = key_description(i)
|
42
39
|
hash[key] = description
|
43
40
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module DuckDB
|
2
|
+
module Converter
|
3
|
+
private
|
4
|
+
|
5
|
+
def iso8601_interval_to_hash(value)
|
6
|
+
digit = ''
|
7
|
+
time = false
|
8
|
+
hash = {}
|
9
|
+
hash.default = 0
|
10
|
+
|
11
|
+
value.each_char do |c|
|
12
|
+
if '-0123456789.'.include?(c)
|
13
|
+
digit += c
|
14
|
+
elsif c == 'T'
|
15
|
+
time = true
|
16
|
+
digit = ''
|
17
|
+
elsif c == 'M'
|
18
|
+
m_interval_to_hash(hash, digit, time)
|
19
|
+
digit = ''
|
20
|
+
elsif c == 'S'
|
21
|
+
s_interval_to_hash(hash, digit)
|
22
|
+
digit = ''
|
23
|
+
elsif 'YDH'.include?(c)
|
24
|
+
hash[c] = digit.to_i
|
25
|
+
digit = ''
|
26
|
+
elsif c != 'P'
|
27
|
+
raise ArgumentError, "The argument `#{value}` can't be parse."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
hash
|
31
|
+
end
|
32
|
+
|
33
|
+
def m_interval_to_hash(hash, digit, time)
|
34
|
+
key = time ? 'TM' : 'M'
|
35
|
+
hash[key] = digit.to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
def s_interval_to_hash(hash, digit)
|
39
|
+
sec, msec = digit.split('.')
|
40
|
+
hash['S'] = sec.to_i
|
41
|
+
hash['MS'] = "#{msec}000000"[0, 6].to_i
|
42
|
+
hash['MS'] *= -1 if hash['S'].negative?
|
43
|
+
end
|
44
|
+
|
45
|
+
def hash_to__append_interval_args(hash)
|
46
|
+
months = hash['Y'] * 12 + hash['M']
|
47
|
+
days = hash['D']
|
48
|
+
micros = (hash['H'] * 3600 + hash['TM'] * 60 + hash['S']) * 1_000_000 + hash['MS']
|
49
|
+
[months, days, micros]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'date'
|
2
|
+
require_relative './converter'
|
2
3
|
|
3
4
|
module DuckDB
|
4
5
|
# The DuckDB::PreparedStatement encapsulates connection with DuckDB prepared
|
@@ -12,6 +13,7 @@ module DuckDB
|
|
12
13
|
# stmt.bind(1, 'email@example.com')
|
13
14
|
# stmt.execute
|
14
15
|
class PreparedStatement
|
16
|
+
include DuckDB::Converter
|
15
17
|
|
16
18
|
RANGE_INT16 = -32768..32767
|
17
19
|
RANGE_INT32 = -2147483648..2147483647
|
@@ -22,13 +24,119 @@ module DuckDB
|
|
22
24
|
when Integer
|
23
25
|
bind_varchar(i, value.to_s)
|
24
26
|
else
|
25
|
-
|
27
|
+
raise(ArgumentError, "2nd argument `#{value}` must be Integer.")
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
29
31
|
# binds i-th parameter with SQL prepared statement.
|
30
|
-
# The first argument is index of parameter.
|
31
|
-
# 1 not 0.
|
32
|
+
# The first argument is index of parameter.
|
33
|
+
# The index of first parameter is 1 not 0.
|
34
|
+
# The second argument value is to expected date.
|
35
|
+
#
|
36
|
+
# require 'duckdb'
|
37
|
+
# db = DuckDB::Database.open('duckdb_database')
|
38
|
+
# con = db.connect
|
39
|
+
# sql ='SELECT name FROM users WHERE birth_day = ?'
|
40
|
+
# stmt = PreparedStatement.new(con, sql)
|
41
|
+
# stmt.bind(1, Date.today)
|
42
|
+
# # or you can specify date string.
|
43
|
+
# # stmt.bind(1, '2021-02-23')
|
44
|
+
def bind_date(i, value)
|
45
|
+
case value
|
46
|
+
when Date, Time
|
47
|
+
date = value
|
48
|
+
else
|
49
|
+
begin
|
50
|
+
date = Date.parse(value)
|
51
|
+
rescue => e
|
52
|
+
raise(ArgumentError, "Cannot parse argument value to date. #{e.message}")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
_bind_date(i, date.year, date.month, date.day)
|
57
|
+
end
|
58
|
+
|
59
|
+
# binds i-th parameter with SQL prepared statement.
|
60
|
+
# The first argument is index of parameter.
|
61
|
+
# The index of first parameter is 1 not 0.
|
62
|
+
# The second argument value is to expected time value.
|
63
|
+
#
|
64
|
+
# require 'duckdb'
|
65
|
+
# db = DuckDB::Database.open('duckdb_database')
|
66
|
+
# con = db.connect
|
67
|
+
# sql ='SELECT name FROM users WHERE birth_time = ?'
|
68
|
+
# stmt = PreparedStatement.new(con, sql)
|
69
|
+
# stmt.bind(1, Time.now)
|
70
|
+
# # or you can specify time string.
|
71
|
+
# # stmt.bind(1, '07:39:45')
|
72
|
+
def bind_time(i, value)
|
73
|
+
case value
|
74
|
+
when Time
|
75
|
+
time = value
|
76
|
+
else
|
77
|
+
begin
|
78
|
+
time = Time.parse(value)
|
79
|
+
rescue => e
|
80
|
+
raise(ArgumentError, "Cannot parse argument value to time. #{e.message}")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
_bind_time(i, time.hour, time.min, time.sec, time.usec)
|
85
|
+
end
|
86
|
+
|
87
|
+
# binds i-th parameter with SQL prepared statement.
|
88
|
+
# The first argument is index of parameter.
|
89
|
+
# The index of first parameter is 1 not 0.
|
90
|
+
# The second argument value is to expected time value.
|
91
|
+
#
|
92
|
+
# require 'duckdb'
|
93
|
+
# db = DuckDB::Database.open('duckdb_database')
|
94
|
+
# con = db.connect
|
95
|
+
# sql ='SELECT name FROM users WHERE created_at = ?'
|
96
|
+
# stmt = PreparedStatement.new(con, sql)
|
97
|
+
# stmt.bind(1, Time.now)
|
98
|
+
# # or you can specify timestamp string.
|
99
|
+
# # stmt.bind(1, '2022-02-23 07:39:45')
|
100
|
+
def bind_timestamp(i, value)
|
101
|
+
case value
|
102
|
+
when Time
|
103
|
+
time = value
|
104
|
+
else
|
105
|
+
begin
|
106
|
+
time = Time.parse(value)
|
107
|
+
rescue => e
|
108
|
+
raise(ArgumentError, "Cannot parse argument value to time. #{e.message}")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
_bind_timestamp(i, time.year, time.month, time.day, time.hour, time.min, time.sec, time.usec)
|
113
|
+
end
|
114
|
+
|
115
|
+
# binds i-th parameter with SQL prepared statement.
|
116
|
+
# The first argument is index of parameter.
|
117
|
+
# The index of first parameter is 1 not 0.
|
118
|
+
# The second argument value is to expected ISO8601 time interval string.
|
119
|
+
#
|
120
|
+
# require 'duckdb'
|
121
|
+
# db = DuckDB::Database.open('duckdb_database')
|
122
|
+
# con = db.connect
|
123
|
+
# sql ='SELECT value FROM intervals WHERE interval = ?'
|
124
|
+
# stmt = PreparedStatement.new(con, sql)
|
125
|
+
# stmt.bind(1, 'P1Y2D')
|
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
|
+
raise ArgumentError, "Argument `#{value}` must be a string." unless value.is_a?(String)
|
129
|
+
|
130
|
+
hash = iso8601_interval_to_hash(value)
|
131
|
+
|
132
|
+
months, days, micros = hash_to__append_interval_args(hash)
|
133
|
+
|
134
|
+
_bind_interval(i, months, days, micros)
|
135
|
+
end
|
136
|
+
|
137
|
+
# binds i-th parameter with SQL prepared statement.
|
138
|
+
# The first argument is index of parameter.
|
139
|
+
# The index of first parameter is 1 not 0.
|
32
140
|
# The second argument value is the value of prepared statement parameter.
|
33
141
|
#
|
34
142
|
# require 'duckdb'
|
@@ -40,7 +148,7 @@ module DuckDB
|
|
40
148
|
def bind(i, value)
|
41
149
|
case value
|
42
150
|
when NilClass
|
43
|
-
|
151
|
+
bind_null(i)
|
44
152
|
when Float
|
45
153
|
bind_double(i, value)
|
46
154
|
when Integer
|
@@ -51,11 +159,7 @@ module DuckDB
|
|
51
159
|
bind_varchar(i, value.to_s)
|
52
160
|
end
|
53
161
|
when String
|
54
|
-
|
55
|
-
blob?(value) ? bind_blob(i, value) : bind_varchar(i, value)
|
56
|
-
else
|
57
|
-
bind_varchar(i, value)
|
58
|
-
end
|
162
|
+
blob?(value) ? bind_blob(i, value) : bind_varchar(i, value)
|
59
163
|
when TrueClass, FalseClass
|
60
164
|
bind_bool(i, value)
|
61
165
|
when Time
|
@@ -63,7 +167,7 @@ module DuckDB
|
|
63
167
|
when Date
|
64
168
|
bind_varchar(i, value.strftime('%Y-%m-%d'))
|
65
169
|
else
|
66
|
-
|
170
|
+
raise(DuckDB::Error, "not supported type `#{value}` (#{value.class})")
|
67
171
|
end
|
68
172
|
end
|
69
173
|
|
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.2.
|
4
|
+
version: 0.3.2.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:
|
11
|
+
date: 2022-02-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -79,8 +79,8 @@ files:
|
|
79
79
|
- ".github/workflows/test_on_ubuntu.yml"
|
80
80
|
- ".github/workflows/test_on_windows.yml"
|
81
81
|
- ".gitignore"
|
82
|
-
- ".travis.yml"
|
83
82
|
- CHANGELOG.md
|
83
|
+
- CONTRIBUTION.md
|
84
84
|
- Gemfile
|
85
85
|
- Gemfile.lock
|
86
86
|
- LICENSE
|
@@ -108,10 +108,13 @@ files:
|
|
108
108
|
- ext/duckdb/result.c
|
109
109
|
- ext/duckdb/result.h
|
110
110
|
- ext/duckdb/ruby-duckdb.h
|
111
|
+
- ext/duckdb/util.c
|
112
|
+
- ext/duckdb/util.h
|
111
113
|
- lib/duckdb.rb
|
112
114
|
- lib/duckdb/appender.rb
|
113
115
|
- lib/duckdb/config.rb
|
114
116
|
- lib/duckdb/connection.rb
|
117
|
+
- lib/duckdb/converter.rb
|
115
118
|
- lib/duckdb/database.rb
|
116
119
|
- lib/duckdb/prepared_statement.rb
|
117
120
|
- lib/duckdb/result.rb
|
@@ -131,14 +134,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
131
134
|
requirements:
|
132
135
|
- - ">="
|
133
136
|
- !ruby/object:Gem::Version
|
134
|
-
version: 2.
|
137
|
+
version: 2.6.0
|
135
138
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
139
|
requirements:
|
137
140
|
- - ">="
|
138
141
|
- !ruby/object:Gem::Version
|
139
142
|
version: '0'
|
140
143
|
requirements: []
|
141
|
-
rubygems_version: 3.
|
144
|
+
rubygems_version: 3.3.7
|
142
145
|
signing_key:
|
143
146
|
specification_version: 4
|
144
147
|
summary: This module is Ruby binding for DuckDB database engine.
|
data/.travis.yml
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
cache:
|
3
|
-
bundler: true
|
4
|
-
directories:
|
5
|
-
- ${HOME}/duckdb-v0.2.8
|
6
|
-
before_install:
|
7
|
-
- yes | gem update --system
|
8
|
-
- if [[ ! -d ${HOME}/duckdb-v0.2.8/build ]]; then cd ${HOME} && git clone -b v0.2.8 https://github.com/cwida/duckdb.git duckdb-v0.2.8 && cd duckdb-v0.2.8 && make && cd ${TRAVIS_BUILD_DIR}; fi
|
9
|
-
|
10
|
-
env:
|
11
|
-
- DUCKDB_VERSION=0.2.8
|
12
|
-
rvm:
|
13
|
-
- 2.5.8
|
14
|
-
- 2.6.8
|
15
|
-
- 2.7.4
|
16
|
-
- 3.0.2
|
17
|
-
- ruby-head
|
18
|
-
script: bundle exec rake -- --with-duckdb-include=${HOME}/duckdb-v${DUCKDB_VERSION}/src/include --with-duckdb-lib=${HOME}/duckdb-v${DUCKDB_VERSION}/build/release/src/
|