duckdb 1.1.3.0 → 1.1.3.1
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 +2 -1
- data/CHANGELOG.md +4 -0
- data/Dockerfile +18 -7
- data/Gemfile.lock +17 -7
- data/README.md +15 -2
- data/ext/duckdb/appender.c +22 -0
- data/ext/duckdb/prepared_statement.c +3 -2
- data/lib/duckdb/connection.rb +1 -12
- data/lib/duckdb/database.rb +1 -6
- data/lib/duckdb/library_version.rb +2 -0
- data/lib/duckdb/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97d0a0fdf67bcfdd00102540f9dd675e1fe87176e349ef06db6f1c72f78b5219
|
4
|
+
data.tar.gz: da34340b078ae95c6b9fa7ddb872de4be16f3bc298169004761d532a9f378f20
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 924d05547e0f9bf6f4772db3a93085930cd48961a0eee92d114815ea8286cd4ad6d1454764ffd97caa0cc6be103a2b084d1f402e98a973dc529b674754b4cfd7
|
7
|
+
data.tar.gz: 022f30d9b659b487f109d91b7d9818a26bb6d0a7fffd62fc8ae0375453688b3981b652fcb00826a826f15503ee119ca73830fe251329d51235d46ffa6c17ff50
|
@@ -15,7 +15,8 @@ jobs:
|
|
15
15
|
runs-on: macos-latest
|
16
16
|
strategy:
|
17
17
|
matrix:
|
18
|
-
ruby: ['3.1.6', '3.2.6', '3.3.6', '3.4.0-preview2', 'head']
|
18
|
+
# ruby: ['3.1.6', '3.2.6', '3.3.6', '3.4.0-preview2', 'head']
|
19
|
+
ruby: ['3.1.6', '3.2.6', '3.3.6', '3.4.0-preview2']
|
19
20
|
duckdb: ['1.1.3', '1.1.1', '1.0.0']
|
20
21
|
|
21
22
|
steps:
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
# Unreleased
|
5
|
+
# 1.1.3.1 - 2024-11-27
|
6
|
+
- fix to `DuckDB::Connection#query` with multiple SQL statements. Calling PreparedStatement#destroy after each statement executed.
|
7
|
+
- install valgrind in docker development environment.
|
8
|
+
- add `DuckDB::Appender#append_default`.
|
5
9
|
|
6
10
|
# 1.1.3.0 - 2024-11-10
|
7
11
|
- add `DuckDB::PreparedStatement#bind_decimal`. (Thanks to @otegami)
|
data/Dockerfile
CHANGED
@@ -2,20 +2,31 @@ ARG RUBY_VERSION=3.3.6
|
|
2
2
|
FROM ruby:${RUBY_VERSION}
|
3
3
|
|
4
4
|
ARG DUCKDB_VERSION=1.1.3
|
5
|
+
ARG VALGRIND_VERSION=3.21.0
|
5
6
|
|
6
7
|
RUN apt update -qq && \
|
7
|
-
apt install -y build-essential curl git wget
|
8
|
+
apt install -y build-essential curl git wget libc6-dbg
|
8
9
|
|
9
10
|
COPY getduckdb.sh .
|
10
11
|
RUN ./getduckdb.sh
|
11
12
|
|
12
|
-
RUN unzip duckdb.zip -d libduckdb
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
RUN unzip duckdb.zip -d libduckdb && \
|
14
|
+
mv libduckdb/duckdb.* /usr/local/include && \
|
15
|
+
mv libduckdb/libduckdb.so /usr/local/lib && \
|
16
|
+
ldconfig /usr/local/lib
|
17
|
+
|
18
|
+
RUN mkdir valgrind-tmp && \
|
19
|
+
cd valgrind-tmp && \
|
20
|
+
wget https://sourceware.org/pub/valgrind/valgrind-${VALGRIND_VERSION}.tar.bz2 && \
|
21
|
+
tar xf valgrind-${VALGRIND_VERSION}.tar.bz2 && \
|
22
|
+
cd valgrind-${VALGRIND_VERSION} && \
|
23
|
+
./configure && \
|
24
|
+
make -s && \
|
25
|
+
make -s install && \
|
26
|
+
cd .. && \
|
27
|
+
rm -rf /valgrind-tmp
|
16
28
|
|
17
29
|
COPY . /root/ruby-duckdb
|
18
30
|
WORKDIR /root/ruby-duckdb
|
19
31
|
RUN git config --global --add safe.directory /root/ruby-duckdb
|
20
|
-
RUN bundle install
|
21
|
-
RUN rake build
|
32
|
+
RUN bundle install && rake build
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
duckdb (1.1.3.
|
4
|
+
duckdb (1.1.3.1)
|
5
5
|
bigdecimal (>= 3.1.4)
|
6
6
|
|
7
7
|
GEM
|
@@ -9,10 +9,16 @@ GEM
|
|
9
9
|
specs:
|
10
10
|
benchmark-ips (2.14.0)
|
11
11
|
bigdecimal (3.1.8)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
minitest (5.25.2)
|
13
|
+
nokogiri (1.16.7-aarch64-linux)
|
14
|
+
racc (~> 1.4)
|
15
|
+
nokogiri (1.16.7-arm-linux)
|
16
|
+
racc (~> 1.4)
|
17
|
+
nokogiri (1.16.7-arm64-darwin)
|
18
|
+
racc (~> 1.4)
|
19
|
+
nokogiri (1.16.7-x86-linux)
|
20
|
+
racc (~> 1.4)
|
21
|
+
nokogiri (1.16.7-x86_64-darwin)
|
16
22
|
racc (~> 1.4)
|
17
23
|
nokogiri (1.16.7-x86_64-linux)
|
18
24
|
racc (~> 1.4)
|
@@ -25,7 +31,11 @@ GEM
|
|
25
31
|
stackprof (0.2.26)
|
26
32
|
|
27
33
|
PLATFORMS
|
28
|
-
|
34
|
+
aarch64-linux
|
35
|
+
arm-linux
|
36
|
+
arm64-darwin
|
37
|
+
x86-linux
|
38
|
+
x86_64-darwin
|
29
39
|
x86_64-linux
|
30
40
|
|
31
41
|
DEPENDENCIES
|
@@ -39,4 +49,4 @@ DEPENDENCIES
|
|
39
49
|
stackprof
|
40
50
|
|
41
51
|
BUNDLED WITH
|
42
|
-
2.5.
|
52
|
+
2.5.22
|
data/README.md
CHANGED
@@ -46,7 +46,7 @@ brew install duckdb
|
|
46
46
|
|
47
47
|
Using [Ruby + Devkit](https://rubyinstaller.org/downloads/) is recommended.
|
48
48
|
|
49
|
-
1. Download libduckdb-windows-amd64.zip from [DuckDB](https://github.com/duckdb/duckdb/releases) and
|
49
|
+
1. Download libduckdb-windows-amd64.zip from [DuckDB](https://github.com/duckdb/duckdb/releases) and extract it.
|
50
50
|
2. Copy `duckdb.dll` into `C:\Windows\System32`
|
51
51
|
|
52
52
|
## How to install
|
@@ -115,7 +115,7 @@ con.query('SELECT * FROM users WHERE name = $name AND email = $email', name: 'Al
|
|
115
115
|
```
|
116
116
|
### Using prepared statement
|
117
117
|
|
118
|
-
You can use prepared statement.
|
118
|
+
You can use prepared statement. Prepared statement object is created by `Connection#prepare` method or `DuckDB::PreparedStatement.new`.
|
119
119
|
|
120
120
|
```ruby
|
121
121
|
stmt = con.prepare('SELECT * FROM users WHERE name = $name AND email = $email')
|
@@ -125,7 +125,20 @@ stmt = con.prepare('SELECT * FROM users WHERE name = $name AND email = $email')
|
|
125
125
|
# stmt = DuckDB::PreparedStatement.new(con, 'SELECT * FROM users WHERE name = $name AND email = $email')
|
126
126
|
stmt.bind(name: 'Alice', email: 'alice@example.com')
|
127
127
|
result = stmt.execute
|
128
|
+
stmt.destroy
|
128
129
|
```
|
130
|
+
You must call `PreparedStatement#destroy` method after using prepared statement. Otherwise, automatically destroyed
|
131
|
+
when the PreparedStatement object is garbage collected.
|
132
|
+
|
133
|
+
Instead of calling `PreparedStatement#destroy`, you can use block.
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
result = con.prepare('SELECT * FROM users WHERE name = $name AND email = $email') do |stmt|
|
137
|
+
stmt.bind(name: 'Alice', email: 'alice@example.com')
|
138
|
+
stmt.execute
|
139
|
+
end
|
140
|
+
```
|
141
|
+
|
129
142
|
### Using async query
|
130
143
|
|
131
144
|
You can use async query.
|
data/ext/duckdb/appender.c
CHANGED
@@ -23,6 +23,11 @@ static VALUE appender_append_varchar(VALUE self, VALUE val);
|
|
23
23
|
static VALUE appender_append_varchar_length(VALUE self, VALUE val, VALUE len);
|
24
24
|
static VALUE appender_append_blob(VALUE self, VALUE val);
|
25
25
|
static VALUE appender_append_null(VALUE self);
|
26
|
+
|
27
|
+
#ifdef HAVE_DUCKDB_H_GE_V1_1_0
|
28
|
+
static VALUE appender_append_default(VALUE self);
|
29
|
+
#endif
|
30
|
+
|
26
31
|
static VALUE appender__append_date(VALUE self, VALUE yearval, VALUE monthval, VALUE dayval);
|
27
32
|
static VALUE appender__append_interval(VALUE self, VALUE months, VALUE days, VALUE micros);
|
28
33
|
static VALUE appender__append_time(VALUE self, VALUE hour, VALUE min, VALUE sec, VALUE micros);
|
@@ -281,6 +286,18 @@ static VALUE appender_append_null(VALUE self) {
|
|
281
286
|
return self;
|
282
287
|
}
|
283
288
|
|
289
|
+
#ifdef HAVE_DUCKDB_H_GE_V1_1_0
|
290
|
+
static VALUE appender_append_default(VALUE self) {
|
291
|
+
rubyDuckDBAppender *ctx;
|
292
|
+
TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
|
293
|
+
|
294
|
+
if (duckdb_append_default(ctx->appender) == DuckDBError) {
|
295
|
+
rb_raise(eDuckDBError, "failed to append");
|
296
|
+
}
|
297
|
+
return self;
|
298
|
+
}
|
299
|
+
#endif
|
300
|
+
|
284
301
|
static VALUE appender__append_date(VALUE self, VALUE year, VALUE month, VALUE day) {
|
285
302
|
duckdb_date dt;
|
286
303
|
rubyDuckDBAppender *ctx;
|
@@ -406,6 +423,11 @@ void rbduckdb_init_duckdb_appender(void) {
|
|
406
423
|
rb_define_method(cDuckDBAppender, "append_varchar_length", appender_append_varchar_length, 2);
|
407
424
|
rb_define_method(cDuckDBAppender, "append_blob", appender_append_blob, 1);
|
408
425
|
rb_define_method(cDuckDBAppender, "append_null", appender_append_null, 0);
|
426
|
+
|
427
|
+
#ifdef HAVE_DUCKDB_H_GE_V1_1_0
|
428
|
+
rb_define_method(cDuckDBAppender, "append_default", appender_append_default, 0);
|
429
|
+
#endif
|
430
|
+
|
409
431
|
rb_define_private_method(cDuckDBAppender, "_append_date", appender__append_date, 3);
|
410
432
|
rb_define_private_method(cDuckDBAppender, "_append_interval", appender__append_interval, 3);
|
411
433
|
rb_define_private_method(cDuckDBAppender, "_append_time", appender__append_time, 4);
|
@@ -72,7 +72,8 @@ VALUE rbduckdb_prepared_statement_new(duckdb_connection con, duckdb_extracted_st
|
|
72
72
|
TypedData_Get_Struct(obj, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
|
73
73
|
|
74
74
|
if (duckdb_prepare_extracted_statement(con, extracted_statements, index, &(ctx->prepared_statement)) == DuckDBError) {
|
75
|
-
|
75
|
+
const char *error = duckdb_prepare_error(ctx->prepared_statement);
|
76
|
+
rb_raise(eDuckDBError, "%s", error ? error : "Failed to create DuckDB::PreparedStatement object.");
|
76
77
|
}
|
77
78
|
return obj;
|
78
79
|
}
|
@@ -90,7 +91,7 @@ static VALUE duckdb_prepared_statement_initialize(VALUE self, VALUE con, VALUE q
|
|
90
91
|
|
91
92
|
if (duckdb_prepare(ctxcon->con, StringValuePtr(query), &(ctx->prepared_statement)) == DuckDBError) {
|
92
93
|
const char *error = duckdb_prepare_error(ctx->prepared_statement);
|
93
|
-
rb_raise(eDuckDBError, "%s", error);
|
94
|
+
rb_raise(eDuckDBError, "%s", error ? error : "Failed to prepare statement(Database connection closed?).");
|
94
95
|
}
|
95
96
|
return self;
|
96
97
|
}
|
data/lib/duckdb/connection.rb
CHANGED
@@ -8,7 +8,6 @@ module DuckDB
|
|
8
8
|
# con = db.connect
|
9
9
|
# con.query(sql)
|
10
10
|
class Connection
|
11
|
-
#
|
12
11
|
# executes sql with args.
|
13
12
|
# The first argument sql must be SQL string.
|
14
13
|
# The rest arguments are parameters of SQL string.
|
@@ -24,7 +23,6 @@ module DuckDB
|
|
24
23
|
#
|
25
24
|
# sql = 'SELECT * FROM users WHERE name = $name AND email = $email'
|
26
25
|
# dave = con.query(sql, name: 'Dave', email: 'dave@example.com')
|
27
|
-
#
|
28
26
|
def query(sql, *args, **kwargs)
|
29
27
|
return query_multi_sql(sql) if args.empty? && kwargs.empty?
|
30
28
|
|
@@ -39,13 +37,13 @@ module DuckDB
|
|
39
37
|
result = nil
|
40
38
|
stmts.each do |stmt|
|
41
39
|
result = stmt.execute
|
40
|
+
stmt.destroy
|
42
41
|
end
|
43
42
|
result
|
44
43
|
ensure
|
45
44
|
stmts&.destroy
|
46
45
|
end
|
47
46
|
|
48
|
-
#
|
49
47
|
# executes sql with args asynchronously.
|
50
48
|
# The first argument sql must be SQL string.
|
51
49
|
# The rest arguments are parameters of SQL string.
|
@@ -60,7 +58,6 @@ module DuckDB
|
|
60
58
|
# pending_result.execute_task while pending_result.state == :not_ready
|
61
59
|
# result = pending_result.execute_pending
|
62
60
|
# result.each.first
|
63
|
-
#
|
64
61
|
def async_query(sql, *args, **kwargs)
|
65
62
|
prepare(sql) do |stmt|
|
66
63
|
stmt.bind_args(*args, **kwargs)
|
@@ -68,7 +65,6 @@ module DuckDB
|
|
68
65
|
end
|
69
66
|
end
|
70
67
|
|
71
|
-
#
|
72
68
|
# executes sql with args asynchronously and provides streaming result.
|
73
69
|
# The first argument sql must be SQL string.
|
74
70
|
# The rest arguments are parameters of SQL string.
|
@@ -84,7 +80,6 @@ module DuckDB
|
|
84
80
|
# pending_result.execute_task while pending_result.state == :not_ready
|
85
81
|
# result = pending_result.execute_pending
|
86
82
|
# result.each.first
|
87
|
-
#
|
88
83
|
def async_query_stream(sql, *args, **kwargs)
|
89
84
|
prepare(sql) do |stmt|
|
90
85
|
stmt.bind_args(*args, **kwargs)
|
@@ -92,10 +87,8 @@ module DuckDB
|
|
92
87
|
end
|
93
88
|
end
|
94
89
|
|
95
|
-
#
|
96
90
|
# connects DuckDB database
|
97
91
|
# The first argument is DuckDB::Database object
|
98
|
-
#
|
99
92
|
def connect(db)
|
100
93
|
conn = _connect(db)
|
101
94
|
return conn unless block_given?
|
@@ -107,7 +100,6 @@ module DuckDB
|
|
107
100
|
end
|
108
101
|
end
|
109
102
|
|
110
|
-
#
|
111
103
|
# returns PreparedStatement object.
|
112
104
|
# The first argument is SQL string.
|
113
105
|
# If block is given, the block is executed with PreparedStatement object
|
@@ -127,17 +119,14 @@ module DuckDB
|
|
127
119
|
# stmt.bind_args(name: 'Dave', email: 'dave@example.com')
|
128
120
|
# stmt.execute
|
129
121
|
# end
|
130
|
-
#
|
131
122
|
def prepared_statement(str, &)
|
132
123
|
return PreparedStatement.new(self, str) unless block_given?
|
133
124
|
|
134
125
|
PreparedStatement.prepare(self, str, &)
|
135
126
|
end
|
136
127
|
|
137
|
-
#
|
138
128
|
# returns Appender object.
|
139
129
|
# The first argument is table name
|
140
|
-
#
|
141
130
|
def appender(table)
|
142
131
|
appender = create_appender(table)
|
143
132
|
|
data/lib/duckdb/database.rb
CHANGED
@@ -20,13 +20,11 @@ module DuckDB
|
|
20
20
|
# result.each do |row|
|
21
21
|
# p row
|
22
22
|
# end
|
23
|
-
#
|
24
23
|
class Database
|
25
24
|
private_class_method :_open
|
26
25
|
private_class_method :_open_ext
|
27
26
|
|
28
27
|
class << self
|
29
|
-
##
|
30
28
|
# Opens database.
|
31
29
|
# The first argument is DuckDB database file path to open.
|
32
30
|
# If there is no argument, the method opens DuckDB database in memory.
|
@@ -40,7 +38,6 @@ module DuckDB
|
|
40
38
|
# con = db.connect
|
41
39
|
# con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
|
42
40
|
# end
|
43
|
-
#
|
44
41
|
def open(dbpath = nil, config = nil)
|
45
42
|
db = _db_open(dbpath, config)
|
46
43
|
return db unless block_given?
|
@@ -54,7 +51,7 @@ module DuckDB
|
|
54
51
|
|
55
52
|
private
|
56
53
|
|
57
|
-
def _db_open(dbpath, config)
|
54
|
+
def _db_open(dbpath, config) # :nodoc:
|
58
55
|
if config
|
59
56
|
_open_ext(dbpath, config)
|
60
57
|
else
|
@@ -63,7 +60,6 @@ module DuckDB
|
|
63
60
|
end
|
64
61
|
end
|
65
62
|
|
66
|
-
##
|
67
63
|
# connects database.
|
68
64
|
#
|
69
65
|
# The method yields block and disconnects the database if block given
|
@@ -75,7 +71,6 @@ module DuckDB
|
|
75
71
|
# db.connect do |con|
|
76
72
|
# con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
|
77
73
|
# end
|
78
|
-
#
|
79
74
|
def connect
|
80
75
|
conn = _connect
|
81
76
|
return conn unless block_given?
|
data/lib/duckdb/version.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: 1.1.3.
|
4
|
+
version: 1.1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masaki Suketa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bigdecimal
|
@@ -181,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
181
181
|
- !ruby/object:Gem::Version
|
182
182
|
version: '0'
|
183
183
|
requirements: []
|
184
|
-
rubygems_version: 3.5.
|
184
|
+
rubygems_version: 3.5.22
|
185
185
|
signing_key:
|
186
186
|
specification_version: 4
|
187
187
|
summary: This module is Ruby binding for DuckDB database engine.
|