duckdb 0.2.8.0 → 0.3.2.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 +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/
|