duckdb 1.5.0.2 → 1.5.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.
- checksums.yaml +4 -4
- data/.github/workflows/test_on_macos.yml +28 -20
- data/.github/workflows/test_on_ubuntu.yml +30 -18
- data/.github/workflows/test_on_windows.yml +15 -9
- data/CHANGELOG.md +23 -0
- data/Dockerfile +1 -1
- data/Gemfile.lock +5 -14
- data/README.md +3 -5
- data/ext/duckdb/client_context.c +70 -0
- data/ext/duckdb/client_context.h +14 -0
- data/ext/duckdb/converter.h +29 -0
- data/ext/duckdb/conveter.c +162 -0
- data/ext/duckdb/duckdb.c +6 -3
- data/ext/duckdb/expression.c +104 -0
- data/ext/duckdb/expression.h +13 -0
- data/ext/duckdb/logical_type.c +21 -0
- data/ext/duckdb/result.c +9 -142
- data/ext/duckdb/ruby-duckdb.h +6 -3
- data/ext/duckdb/scalar_function.c +91 -0
- data/ext/duckdb/scalar_function.h +1 -0
- data/ext/duckdb/scalar_function_bind_info.c +109 -0
- data/ext/duckdb/scalar_function_bind_info.h +13 -0
- data/ext/duckdb/table_function.c +7 -7
- data/ext/duckdb/table_function.h +1 -0
- data/ext/duckdb/{bind_info.c → table_function_bind_info.c} +13 -52
- data/ext/duckdb/table_function_bind_info.h +14 -0
- data/ext/duckdb/{function_info.c → table_function_function_info.c} +6 -6
- data/ext/duckdb/{function_info.h → table_function_function_info.h} +3 -3
- data/ext/duckdb/{init_info.c → table_function_init_info.c} +6 -6
- data/ext/duckdb/table_function_init_info.h +14 -0
- data/ext/duckdb/value_impl.c +88 -0
- data/ext/duckdb/value_impl.h +2 -0
- data/lib/duckdb/appender.rb +1 -1
- data/lib/duckdb/client_context.rb +10 -0
- data/lib/duckdb/converter/int_to_sym.rb +1 -0
- data/lib/duckdb/expression.rb +24 -0
- data/lib/duckdb/logical_type.rb +15 -0
- data/lib/duckdb/scalar_function/bind_info.rb +35 -0
- data/lib/duckdb/scalar_function.rb +100 -9
- data/lib/duckdb/table_function/bind_info.rb +34 -0
- data/lib/duckdb/table_function/function_info.rb +23 -0
- data/lib/duckdb/table_function/init_info.rb +24 -0
- data/lib/duckdb/version.rb +1 -1
- data/lib/duckdb.rb +20 -3
- metadata +20 -11
- data/ext/duckdb/bind_info.h +0 -13
- data/ext/duckdb/init_info.h +0 -13
- data/lib/duckdb/bind_info.rb +0 -32
- data/lib/duckdb/function_info.rb +0 -21
- data/lib/duckdb/init_info.rb +0 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c55213e9e388de53b04f29987c7714975ab5c1a8fa10a40ae378189507dae752
|
|
4
|
+
data.tar.gz: a96e6256ce85583fd395d936994d2a871727af8f7ba11fadc40a9d9ca79c15fa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 67c2d5de633c5999ca07e3deb7c98a091b4eaedb70eacce2d2f7c34b9e8795b012d4415e197d5996ca80eb9c526dc28e86ced8f1d977cc040fcfd8c59a9a3ad2
|
|
7
|
+
data.tar.gz: 38de479e2069a0b4dd1fa8684b2174d6f42c15375d54269f56983b530e2b7ea43150284b8825879cdceca1fe959f1c05b8043bb1c2202b30456c63eac8dbc6ab
|
|
@@ -21,7 +21,7 @@ jobs:
|
|
|
21
21
|
strategy:
|
|
22
22
|
matrix:
|
|
23
23
|
ruby: ['3.2.9', '3.3.10', '3.4.9', '4.0.2', 'head']
|
|
24
|
-
duckdb: ['1.4.4', '1.5.
|
|
24
|
+
duckdb: ['1.4.4', '1.5.1']
|
|
25
25
|
|
|
26
26
|
steps:
|
|
27
27
|
- uses: actions/checkout@v4
|
|
@@ -35,39 +35,36 @@ jobs:
|
|
|
35
35
|
id: duckdb-cache
|
|
36
36
|
uses: actions/cache@v4
|
|
37
37
|
with:
|
|
38
|
-
path:
|
|
38
|
+
path: libduckdb-osx-universal
|
|
39
39
|
key: ${{ runner.os }}-duckdb-v${{ matrix.duckdb }}
|
|
40
40
|
|
|
41
|
-
- name:
|
|
41
|
+
- name: Download duckdb ${{ matrix.duckdb }}
|
|
42
|
+
if: steps.duckdb-cache.outputs.cache-hit != 'true'
|
|
42
43
|
env:
|
|
43
44
|
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
|
44
|
-
if: steps.duckdb-cache.outputs.cache-hit != 'true'
|
|
45
45
|
run: |
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
curl -OL https://github.com/duckdb/duckdb/releases/download/v${DUCKDB_VERSION}/libduckdb-osx-universal.zip
|
|
47
|
+
case "${DUCKDB_VERSION}" in
|
|
48
|
+
"1.5.1") EXPECTED_SHA256="d9dd723c59f8571202b468f6bf71d4555238544553dd1445e6c9ecb39f54c0f3" ;;
|
|
49
|
+
"1.4.4") EXPECTED_SHA256="5e6d79f5fb86bbd4f24d59cee3bc38f113d1433761df35337e3c01c62eeafe26" ;;
|
|
50
|
+
*) echo "No known SHA256 for DuckDB v${DUCKDB_VERSION}"; exit 1 ;;
|
|
51
|
+
esac
|
|
52
|
+
echo "${EXPECTED_SHA256} libduckdb-osx-universal.zip" | shasum -a 256 -c
|
|
53
|
+
mkdir libduckdb-osx-universal
|
|
54
|
+
unzip libduckdb-osx-universal.zip -d libduckdb-osx-universal
|
|
52
55
|
|
|
53
56
|
- name: bundle install with Ruby ${{ matrix.ruby }}
|
|
54
|
-
env:
|
|
55
|
-
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
|
56
57
|
run: |
|
|
57
58
|
bundle install --jobs 4 --retry 3
|
|
58
59
|
|
|
59
60
|
- name: Build test with DUCKDB_API_NO_DEPRECATED and Ruby ${{ matrix.ruby }}
|
|
60
|
-
env:
|
|
61
|
-
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
|
62
61
|
run: |
|
|
63
|
-
env DUCKDB_API_NO_DEPRECATED=1 bundle exec rake build -- --with-duckdb-include=${GITHUB_WORKSPACE}/
|
|
62
|
+
env DUCKDB_API_NO_DEPRECATED=1 bundle exec rake build -- --with-duckdb-include=${GITHUB_WORKSPACE}/libduckdb-osx-universal --with-duckdb-lib=${GITHUB_WORKSPACE}/libduckdb-osx-universal
|
|
64
63
|
bundle exec rake clean
|
|
65
64
|
|
|
66
65
|
- name: Build with Ruby ${{ matrix.ruby }}
|
|
67
|
-
env:
|
|
68
|
-
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
|
69
66
|
run: |
|
|
70
|
-
bundle exec rake build -- --with-duckdb-include=${GITHUB_WORKSPACE}/
|
|
67
|
+
bundle exec rake build -- --with-duckdb-include=${GITHUB_WORKSPACE}/libduckdb-osx-universal --with-duckdb-lib=${GITHUB_WORKSPACE}/libduckdb-osx-universal
|
|
71
68
|
|
|
72
69
|
- name: Setup MySQL
|
|
73
70
|
run: |
|
|
@@ -79,12 +76,23 @@ jobs:
|
|
|
79
76
|
mysql -u root -e "GRANT ALL PRIVILEGES ON test_db.* TO 'test_user'@'127.0.0.1';"
|
|
80
77
|
mysql -u root -e "FLUSH PRIVILEGES;"
|
|
81
78
|
|
|
79
|
+
- name: confirm duckdb library version
|
|
80
|
+
env:
|
|
81
|
+
EXPECTED_DUCKDB_VERSION: ${{ matrix.duckdb }}
|
|
82
|
+
DYLD_LIBRARY_PATH: ${{ github.workspace }}/libduckdb-osx-universal
|
|
83
|
+
run: |
|
|
84
|
+
ruby -Ilib -rduckdb -e '
|
|
85
|
+
actual = DuckDB::LIBRARY_VERSION
|
|
86
|
+
expected = ENV.fetch("EXPECTED_DUCKDB_VERSION")
|
|
87
|
+
abort("Expected DuckDB #{expected}, got #{actual}") if actual != expected
|
|
88
|
+
puts "duckdb library #{actual}"
|
|
89
|
+
'
|
|
90
|
+
|
|
82
91
|
- name: test with Ruby ${{ matrix.ruby }}
|
|
83
92
|
env:
|
|
84
|
-
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
|
85
93
|
MYSQL_TEST: 1
|
|
94
|
+
DYLD_LIBRARY_PATH: ${{ github.workspace }}/libduckdb-osx-universal
|
|
86
95
|
run: |
|
|
87
|
-
export DYLD_LIBRARY_PATH=${GITHUB_WORKSPACE}/duckdb-v${DUCKDB_VERSION}/build/release/src:${DYLD_LIBRARY_PATH}
|
|
88
96
|
env RUBYOPT=-W:deprecated rake test
|
|
89
97
|
|
|
90
98
|
post-test:
|
|
@@ -21,7 +21,7 @@ jobs:
|
|
|
21
21
|
strategy:
|
|
22
22
|
matrix:
|
|
23
23
|
ruby: ['3.2.9', '3.3.10', '3.4.9', '4.0.2', 'head']
|
|
24
|
-
duckdb: ['1.4.4', '1.5.
|
|
24
|
+
duckdb: ['1.4.4', '1.5.1']
|
|
25
25
|
|
|
26
26
|
services:
|
|
27
27
|
mysql:
|
|
@@ -47,43 +47,55 @@ jobs:
|
|
|
47
47
|
id: duckdb-cache
|
|
48
48
|
uses: actions/cache@v4
|
|
49
49
|
with:
|
|
50
|
-
path:
|
|
50
|
+
path: libduckdb-linux-amd64
|
|
51
51
|
key: ${{ runner.os }}-duckdb-v${{ matrix.duckdb }}
|
|
52
52
|
|
|
53
|
-
- name:
|
|
53
|
+
- name: Download duckdb ${{ matrix.duckdb }}
|
|
54
|
+
if: steps.duckdb-cache.outputs.cache-hit != 'true'
|
|
54
55
|
env:
|
|
55
56
|
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
|
56
|
-
if: steps.duckdb-cache.outputs.cache-hit != 'true'
|
|
57
57
|
run: |
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
curl -OL https://github.com/duckdb/duckdb/releases/download/v${DUCKDB_VERSION}/libduckdb-linux-amd64.zip
|
|
59
|
+
case "${DUCKDB_VERSION}" in
|
|
60
|
+
"1.5.1") EXPECTED_SHA256="21aec66a60eae1696270ba715a481ab066a88d99a62718d0577579ac1a7a4834" ;;
|
|
61
|
+
"1.4.4") EXPECTED_SHA256="09cc288295964d897b47665d1898e16e8ef176cae9ea615797fc136eae15bd5d" ;;
|
|
62
|
+
*) echo "No known SHA256 for DuckDB v${DUCKDB_VERSION}"; exit 1 ;;
|
|
63
|
+
esac
|
|
64
|
+
echo "${EXPECTED_SHA256} libduckdb-linux-amd64.zip" | sha256sum -c
|
|
65
|
+
mkdir libduckdb-linux-amd64
|
|
66
|
+
unzip libduckdb-linux-amd64.zip -d libduckdb-linux-amd64
|
|
67
|
+
|
|
68
|
+
- name: setup libduckdb.so
|
|
69
|
+
run: |
|
|
70
|
+
sudo cp libduckdb-linux-amd64/libduckdb.so /usr/local/lib/
|
|
71
|
+
sudo ldconfig
|
|
64
72
|
|
|
65
73
|
- name: bundle install with Ruby ${{ matrix.ruby }}
|
|
66
|
-
env:
|
|
67
|
-
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
|
68
74
|
run: |
|
|
69
75
|
bundle install --jobs 4 --retry 3
|
|
70
76
|
|
|
71
77
|
- name: Build test with DUCKDB_API_NO_DEPRECATED and Ruby ${{ matrix.ruby }}
|
|
72
|
-
env:
|
|
73
|
-
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
|
74
78
|
run: |
|
|
75
|
-
env DUCKDB_API_NO_DEPRECATED=1 bundle exec rake build -- --with-duckdb-include=${GITHUB_WORKSPACE}/
|
|
79
|
+
env DUCKDB_API_NO_DEPRECATED=1 bundle exec rake build -- --with-duckdb-include=${GITHUB_WORKSPACE}/libduckdb-linux-amd64 --with-duckdb-lib=${GITHUB_WORKSPACE}/libduckdb-linux-amd64
|
|
76
80
|
bundle exec rake clean
|
|
77
81
|
|
|
78
82
|
- name: Build with Ruby ${{ matrix.ruby }}
|
|
83
|
+
run: |
|
|
84
|
+
bundle exec rake build -- --with-duckdb-include=${GITHUB_WORKSPACE}/libduckdb-linux-amd64 --with-duckdb-lib=${GITHUB_WORKSPACE}/libduckdb-linux-amd64
|
|
85
|
+
|
|
86
|
+
- name: confirm duckdb library version
|
|
79
87
|
env:
|
|
80
|
-
|
|
88
|
+
EXPECTED_DUCKDB_VERSION: ${{ matrix.duckdb }}
|
|
81
89
|
run: |
|
|
82
|
-
|
|
90
|
+
ruby -Ilib -rduckdb -e '
|
|
91
|
+
actual = DuckDB::LIBRARY_VERSION
|
|
92
|
+
expected = ENV.fetch("EXPECTED_DUCKDB_VERSION")
|
|
93
|
+
abort("Expected DuckDB #{expected}, got #{actual}") if actual != expected
|
|
94
|
+
puts "duckdb library #{actual}"
|
|
95
|
+
'
|
|
83
96
|
|
|
84
97
|
- name: test with Ruby ${{ matrix.ruby }}
|
|
85
98
|
env:
|
|
86
|
-
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
|
87
99
|
MYSQL_TEST: 1
|
|
88
100
|
run: |
|
|
89
101
|
env RUBYOPT=-W:deprecated rake test
|
|
@@ -17,11 +17,11 @@ concurrency:
|
|
|
17
17
|
jobs:
|
|
18
18
|
test:
|
|
19
19
|
runs-on: windows-latest
|
|
20
|
-
timeout-minutes:
|
|
20
|
+
timeout-minutes: 8
|
|
21
21
|
strategy:
|
|
22
22
|
matrix:
|
|
23
23
|
ruby: ['3.2.9', '3.3.10', '3.4.8', '4.0.1', 'ucrt', 'mingw', 'mswin', 'head']
|
|
24
|
-
duckdb: ['1.4.4', '1.5.
|
|
24
|
+
duckdb: ['1.4.4', '1.5.1']
|
|
25
25
|
|
|
26
26
|
steps:
|
|
27
27
|
- uses: actions/checkout@v4
|
|
@@ -31,29 +31,35 @@ jobs:
|
|
|
31
31
|
with:
|
|
32
32
|
ruby-version: ${{ matrix.ruby }}
|
|
33
33
|
|
|
34
|
+
- name: duckdb cache
|
|
35
|
+
id: duckdb-cache
|
|
36
|
+
uses: actions/cache@v4
|
|
37
|
+
with:
|
|
38
|
+
path: libduckdb-windows-amd64
|
|
39
|
+
key: ${{ runner.os }}-duckdb-v${{ matrix.duckdb }}
|
|
40
|
+
|
|
34
41
|
- name: download duckdb binary for windows 64bit
|
|
42
|
+
if: steps.duckdb-cache.outputs.cache-hit != 'true'
|
|
35
43
|
env:
|
|
36
44
|
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
|
37
45
|
run: |
|
|
38
46
|
curl -OL https://github.com/duckdb/duckdb/releases/download/v${env:DUCKDB_VERSION}/libduckdb-windows-amd64.zip
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
run: |
|
|
42
|
-
unzip libduckdb-windows-amd64.zip
|
|
47
|
+
mkdir libduckdb-windows-amd64
|
|
48
|
+
unzip libduckdb-windows-amd64.zip -d libduckdb-windows-amd64
|
|
43
49
|
|
|
44
50
|
- name: setup duckdb.dll
|
|
45
51
|
run: |
|
|
46
|
-
cp duckdb.dll C:/Windows/System32/
|
|
52
|
+
cp libduckdb-windows-amd64/duckdb.dll C:/Windows/System32/
|
|
47
53
|
|
|
48
54
|
- name: Build with Rake with Ruby ${{ matrix.ruby }}
|
|
49
55
|
run: |
|
|
50
56
|
bundle install
|
|
51
|
-
bundle exec rake build -- --with-duckdb-include
|
|
57
|
+
bundle exec rake build -- --with-duckdb-include=../../../../libduckdb-windows-amd64 --with-duckdb-lib=../../../../libduckdb-windows-amd64
|
|
52
58
|
|
|
53
59
|
- name: rake test
|
|
54
60
|
uses: nick-fields/retry@v3
|
|
55
61
|
with:
|
|
56
|
-
timeout_minutes:
|
|
62
|
+
timeout_minutes: 1
|
|
57
63
|
max_attempts: 3
|
|
58
64
|
command: bundle exec rake test TESTOPTS="--verbose"
|
|
59
65
|
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,29 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
# Unreleased
|
|
6
6
|
|
|
7
|
+
# 1.5.1.0 - 2026-03-29
|
|
8
|
+
|
|
9
|
+
- add `DuckDB::ScalarFunction#varargs_type=` to register a scalar function that accepts a variable number of arguments of a given type (wraps `duckdb_scalar_function_set_varargs`).
|
|
10
|
+
- `DuckDB::ScalarFunction.create` accepts `varargs_type:` keyword argument (mutually exclusive with `parameter_type:`/`parameter_types:`).
|
|
11
|
+
- add `DuckDB::ScalarFunction#set_special_handling` to make the block receive `nil` for NULL inputs instead of DuckDB short-circuiting (wraps `duckdb_scalar_function_set_special_handling`).
|
|
12
|
+
- `DuckDB::ScalarFunction.create` accepts `null_handling: true` keyword to enable special NULL handling.
|
|
13
|
+
- add `34 => :any` to `Converter::IntToSym::HASH_TYPES` and `:any` to `ScalarFunction::SUPPORTED_TYPES` so `DuckDB::LogicalType::ANY` can be used with `varargs_type=`.
|
|
14
|
+
- add `DuckDB::ScalarFunction#set_bind` to register a bind callback (wraps `duckdb_scalar_function_set_bind`). The block receives a `DuckDB::ScalarFunction::BindInfo` object at query planning time (once, before per-row execution).
|
|
15
|
+
- add `DuckDB::ScalarFunction::BindInfo#argument_count` to return the number of arguments passed to the scalar function (wraps `duckdb_scalar_function_bind_get_argument_count`).
|
|
16
|
+
- add `DuckDB::ScalarFunction::BindInfo#set_error(message)` to report an error early at planning time (wraps `duckdb_scalar_function_bind_set_error`).
|
|
17
|
+
- add `DuckDB::ScalarFunction::BindInfo#get_argument(index)` to return the expression at the given argument index as a `DuckDB::Expression` object (wraps `duckdb_scalar_function_bind_get_argument`). Raises `ArgumentError` for out-of-range index.
|
|
18
|
+
- add `DuckDB::Expression#foldable?` to check whether an expression can be folded to a constant at query planning time (wraps `duckdb_expression_is_foldable`). Returns `true` for literals and constant arithmetic, `false` for column references and non-deterministic functions.
|
|
19
|
+
- add `DuckDB::LogicalType.create_map` to create a map logical type.
|
|
20
|
+
- bump duckdb to 1.5.1 on CI
|
|
21
|
+
- add `DuckDB::ScalarFunction::BindInfo#client_context` to return the client context of the bind phase as a `DuckDB::ClientContext` object (wraps `duckdb_scalar_function_get_client_context`).
|
|
22
|
+
- add `DuckDB::ClientContext#connection_id` to return the connection id of the client context (wraps `duckdb_client_context_get_connection_id`).
|
|
23
|
+
- add `DuckDB::Expression#fold(client_context)` to fold a constant expression to a native Ruby value at query planning time (wraps `duckdb_expression_fold`). Returns Integer, Float, String, true/false, or nil. Raises `DuckDB::Error` if the expression is not foldable.
|
|
24
|
+
|
|
25
|
+
## Breaking changes
|
|
26
|
+
- rename `DuckDB::BindInfo` to `DuckDB::TableFunction::BindInfo`. `DuckDB::BindInfo` still works but emits a deprecation warning.
|
|
27
|
+
- rename `DuckDB::InitInfo` to `DuckDB::TableFunction::InitInfo`. `DuckDB::InitInfo` still works but emits a deprecation warning.
|
|
28
|
+
- rename `DuckDB::FunctionInfo` to `DuckDB::TableFunction::FunctionInfo`. `DuckDB::FunctionInfo` still works but emits a deprecation warning.
|
|
29
|
+
|
|
7
30
|
# 1.5.0.2 - 2026-03-22
|
|
8
31
|
|
|
9
32
|
- add `DuckDB.vector_size` to return the DuckDB vector size (number of rows processed per vectorized operation).
|
data/Dockerfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,46 +1,37 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
duckdb (1.5.0
|
|
4
|
+
duckdb (1.5.1.0)
|
|
5
5
|
bigdecimal (>= 3.1.4)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
|
-
addressable (2.8.9)
|
|
11
|
-
public_suffix (>= 2.0.2, < 8.0)
|
|
12
10
|
ast (2.4.3)
|
|
13
|
-
bigdecimal (4.0
|
|
11
|
+
bigdecimal (4.1.0)
|
|
14
12
|
csv (3.3.5)
|
|
15
13
|
drb (2.2.3)
|
|
16
|
-
json (2.19.
|
|
17
|
-
json-schema (6.2.0)
|
|
18
|
-
addressable (~> 2.8)
|
|
19
|
-
bigdecimal (>= 3.1, < 5)
|
|
14
|
+
json (2.19.3)
|
|
20
15
|
language_server-protocol (3.17.0.5)
|
|
21
16
|
lint_roller (1.1.0)
|
|
22
|
-
mcp (0.9.0)
|
|
23
|
-
json-schema (>= 4.1)
|
|
24
17
|
minitest (6.0.2)
|
|
25
18
|
drb (~> 2.0)
|
|
26
19
|
prism (~> 1.5)
|
|
27
20
|
parallel (1.27.0)
|
|
28
|
-
parser (3.3.
|
|
21
|
+
parser (3.3.11.1)
|
|
29
22
|
ast (~> 2.4.1)
|
|
30
23
|
racc
|
|
31
24
|
prism (1.9.0)
|
|
32
|
-
public_suffix (7.0.5)
|
|
33
25
|
racc (1.8.1)
|
|
34
26
|
rainbow (3.1.1)
|
|
35
27
|
rake (13.3.1)
|
|
36
28
|
rake-compiler (1.3.1)
|
|
37
29
|
rake
|
|
38
30
|
regexp_parser (2.11.3)
|
|
39
|
-
rubocop (1.
|
|
31
|
+
rubocop (1.86.0)
|
|
40
32
|
json (~> 2.3)
|
|
41
33
|
language_server-protocol (~> 3.17.0.2)
|
|
42
34
|
lint_roller (~> 1.1.0)
|
|
43
|
-
mcp (~> 0.6)
|
|
44
35
|
parallel (~> 1.10)
|
|
45
36
|
parser (>= 3.3.0.2)
|
|
46
37
|
rainbow (>= 2.2.2, < 4.0)
|
data/README.md
CHANGED
|
@@ -14,11 +14,9 @@ This gem `duckdb` is Ruby client for the [DuckDB](https://www.duckdb.org) databa
|
|
|
14
14
|
You must have [DuckDB](https://www.duckdb.org) engine installed in order to use this gem.
|
|
15
15
|
|
|
16
16
|
## Pre-requisite setup (Linux):
|
|
17
|
-
1.
|
|
17
|
+
1. Download the latest [C++ package release for DuckDB](https://duckdb.org/install/?platform=linux&environment=c).
|
|
18
18
|
|
|
19
|
-
2.
|
|
20
|
-
|
|
21
|
-
3. Move the files to their respective location:
|
|
19
|
+
2. Move the files to their respective location:
|
|
22
20
|
- Extract the `duckdb.h` and `duckdb.hpp` file to `/usr/local/include`.
|
|
23
21
|
- Extract the `libduckdb.so` file to `/usr/local/lib`.
|
|
24
22
|
|
|
@@ -28,7 +26,7 @@ You must have [DuckDB](https://www.duckdb.org) engine installed in order to use
|
|
|
28
26
|
sudo mv libduckdb/libduckdb.so /usr/local/lib
|
|
29
27
|
```
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
3. To create the necessary link, run `ldconfig` as root:
|
|
32
30
|
|
|
33
31
|
```sh
|
|
34
32
|
sudo ldconfig /usr/local/lib # adding a --verbose flag is optional - but this will let you know if the libduckdb.so library has been linked
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#include "ruby-duckdb.h"
|
|
2
|
+
|
|
3
|
+
VALUE cDuckDBClientContext;
|
|
4
|
+
|
|
5
|
+
static void deallocate(void *ctx);
|
|
6
|
+
static VALUE allocate(VALUE klass);
|
|
7
|
+
static size_t memsize(const void *p);
|
|
8
|
+
static VALUE rbduckdb_client_context_connection_id(VALUE self);
|
|
9
|
+
|
|
10
|
+
static const rb_data_type_t client_context_data_type = {
|
|
11
|
+
"DuckDB/ClientContext",
|
|
12
|
+
{NULL, deallocate, memsize,},
|
|
13
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
static void deallocate(void *ctx) {
|
|
17
|
+
rubyDuckDBClientContext *p = (rubyDuckDBClientContext *)ctx;
|
|
18
|
+
|
|
19
|
+
if (p->client_context) {
|
|
20
|
+
duckdb_destroy_client_context(&(p->client_context));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
xfree(p);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static VALUE allocate(VALUE klass) {
|
|
27
|
+
rubyDuckDBClientContext *ctx = xcalloc((size_t)1, sizeof(rubyDuckDBClientContext));
|
|
28
|
+
return TypedData_Wrap_Struct(klass, &client_context_data_type, ctx);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static size_t memsize(const void *p) {
|
|
32
|
+
return sizeof(rubyDuckDBClientContext);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
VALUE rbduckdb_client_context_new(duckdb_client_context client_context) {
|
|
36
|
+
rubyDuckDBClientContext *ctx;
|
|
37
|
+
VALUE obj = allocate(cDuckDBClientContext);
|
|
38
|
+
|
|
39
|
+
TypedData_Get_Struct(obj, rubyDuckDBClientContext, &client_context_data_type, ctx);
|
|
40
|
+
ctx->client_context = client_context;
|
|
41
|
+
|
|
42
|
+
return obj;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
rubyDuckDBClientContext *get_struct_client_context(VALUE obj) {
|
|
46
|
+
rubyDuckDBClientContext *ctx;
|
|
47
|
+
TypedData_Get_Struct(obj, rubyDuckDBClientContext, &client_context_data_type, ctx);
|
|
48
|
+
return ctx;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/*
|
|
52
|
+
* call-seq:
|
|
53
|
+
* client_context.connection_id -> Integer
|
|
54
|
+
*
|
|
55
|
+
* Returns the connection id of the client context.
|
|
56
|
+
*/
|
|
57
|
+
static VALUE rbduckdb_client_context_connection_id(VALUE self) {
|
|
58
|
+
rubyDuckDBClientContext *ctx;
|
|
59
|
+
TypedData_Get_Struct(self, rubyDuckDBClientContext, &client_context_data_type, ctx);
|
|
60
|
+
return ULL2NUM(duckdb_client_context_get_connection_id(ctx->client_context));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
void rbduckdb_init_duckdb_client_context(void) {
|
|
64
|
+
#if 0
|
|
65
|
+
VALUE mDuckDB = rb_define_module("DuckDB");
|
|
66
|
+
#endif
|
|
67
|
+
cDuckDBClientContext = rb_define_class_under(mDuckDB, "ClientContext", rb_cObject);
|
|
68
|
+
rb_define_alloc_func(cDuckDBClientContext, allocate);
|
|
69
|
+
rb_define_method(cDuckDBClientContext, "connection_id", rbduckdb_client_context_connection_id, 0);
|
|
70
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#ifndef RUBY_DUCKDB_CLIENT_CONTEXT_H
|
|
2
|
+
#define RUBY_DUCKDB_CLIENT_CONTEXT_H
|
|
3
|
+
|
|
4
|
+
struct _rubyDuckDBClientContext {
|
|
5
|
+
duckdb_client_context client_context;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
typedef struct _rubyDuckDBClientContext rubyDuckDBClientContext;
|
|
9
|
+
|
|
10
|
+
void rbduckdb_init_duckdb_client_context(void);
|
|
11
|
+
VALUE rbduckdb_client_context_new(duckdb_client_context client_context);
|
|
12
|
+
rubyDuckDBClientContext *get_struct_client_context(VALUE obj);
|
|
13
|
+
|
|
14
|
+
#endif
|
data/ext/duckdb/converter.h
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
#ifndef RUBY_DUCKDB_CONVERTER_H
|
|
2
2
|
#define RUBY_DUCKDB_CONVERTER_H
|
|
3
3
|
|
|
4
|
+
extern ID id__to_date;
|
|
5
|
+
extern ID id__to_time;
|
|
6
|
+
extern ID id__to_time_from_duckdb_time;
|
|
7
|
+
extern ID id__to_interval_from_vector;
|
|
8
|
+
extern ID id__to_hugeint_from_vector;
|
|
9
|
+
extern ID id__to_decimal_from_hugeint;
|
|
10
|
+
extern ID id__to_uuid_from_vector;
|
|
11
|
+
extern ID id__to_time_from_duckdb_timestamp_s;
|
|
12
|
+
extern ID id__to_time_from_duckdb_timestamp_ms;
|
|
13
|
+
extern ID id__to_time_from_duckdb_timestamp_ns;
|
|
14
|
+
extern ID id__to_time_from_duckdb_time_tz;
|
|
15
|
+
extern ID id__to_time_from_duckdb_timestamp_tz;
|
|
16
|
+
extern ID id__to_infinity;
|
|
17
|
+
|
|
18
|
+
VALUE rbduckdb_timestamp_s_to_ruby(duckdb_timestamp_s ts);
|
|
19
|
+
VALUE rbduckdb_timestamp_ms_to_ruby(duckdb_timestamp_ms ts);
|
|
20
|
+
VALUE rbduckdb_timestamp_ns_to_ruby(duckdb_timestamp_ns ts);
|
|
21
|
+
VALUE rbduckdb_time_tz_to_ruby(duckdb_time_tz tz);
|
|
22
|
+
VALUE rbduckdb_timestamp_tz_to_ruby(duckdb_timestamp ts);
|
|
23
|
+
VALUE rbduckdb_time_to_ruby(duckdb_time t);
|
|
24
|
+
VALUE rbduckdb_date_to_ruby(duckdb_date date);
|
|
25
|
+
VALUE rbduckdb_timestamp_to_ruby(duckdb_timestamp ts);
|
|
26
|
+
|
|
27
|
+
VALUE infinite_date_value(duckdb_date date);
|
|
28
|
+
VALUE infinite_timestamp_value(duckdb_timestamp timestamp);
|
|
29
|
+
VALUE infinite_timestamp_s_value(duckdb_timestamp_s timestamp_s);
|
|
30
|
+
VALUE infinite_timestamp_ms_value(duckdb_timestamp_ms timestamp_ms);
|
|
31
|
+
VALUE infinite_timestamp_ns_value(duckdb_timestamp_ns timestamp_ns);
|
|
32
|
+
|
|
4
33
|
void rbduckdb_init_duckdb_converter(void);
|
|
5
34
|
|
|
6
35
|
#endif
|
data/ext/duckdb/conveter.c
CHANGED
|
@@ -2,6 +2,168 @@
|
|
|
2
2
|
|
|
3
3
|
VALUE mDuckDBConverter;
|
|
4
4
|
|
|
5
|
+
ID id__to_date;
|
|
6
|
+
ID id__to_time;
|
|
7
|
+
ID id__to_time_from_duckdb_time;
|
|
8
|
+
ID id__to_interval_from_vector;
|
|
9
|
+
ID id__to_hugeint_from_vector;
|
|
10
|
+
ID id__to_decimal_from_hugeint;
|
|
11
|
+
ID id__to_uuid_from_vector;
|
|
12
|
+
ID id__to_time_from_duckdb_timestamp_s;
|
|
13
|
+
ID id__to_time_from_duckdb_timestamp_ms;
|
|
14
|
+
ID id__to_time_from_duckdb_timestamp_ns;
|
|
15
|
+
ID id__to_time_from_duckdb_time_tz;
|
|
16
|
+
ID id__to_time_from_duckdb_timestamp_tz;
|
|
17
|
+
ID id__to_infinity;
|
|
18
|
+
|
|
19
|
+
VALUE infinite_date_value(duckdb_date date) {
|
|
20
|
+
if (duckdb_is_finite_date(date) == false) {
|
|
21
|
+
return rb_funcall(mDuckDBConverter, id__to_infinity, 1,
|
|
22
|
+
INT2NUM(date.days)
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return Qnil;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
VALUE infinite_timestamp_value(duckdb_timestamp timestamp) {
|
|
29
|
+
if (duckdb_is_finite_timestamp(timestamp) == false) {
|
|
30
|
+
return rb_funcall(mDuckDBConverter, id__to_infinity, 1,
|
|
31
|
+
LL2NUM(timestamp.micros)
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
return Qnil;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
VALUE infinite_timestamp_s_value(duckdb_timestamp_s timestamp_s) {
|
|
38
|
+
if (duckdb_is_finite_timestamp_s(timestamp_s) == false) {
|
|
39
|
+
return rb_funcall(mDuckDBConverter, id__to_infinity, 1,
|
|
40
|
+
LL2NUM(timestamp_s.seconds)
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return Qnil;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
VALUE infinite_timestamp_ms_value(duckdb_timestamp_ms timestamp_ms) {
|
|
47
|
+
if (duckdb_is_finite_timestamp_ms(timestamp_ms) == false) {
|
|
48
|
+
return rb_funcall(mDuckDBConverter, id__to_infinity, 1,
|
|
49
|
+
LL2NUM(timestamp_ms.millis)
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
return Qnil;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
VALUE infinite_timestamp_ns_value(duckdb_timestamp_ns timestamp_ns) {
|
|
56
|
+
if (duckdb_is_finite_timestamp_ns(timestamp_ns) == false) {
|
|
57
|
+
return rb_funcall(mDuckDBConverter, id__to_infinity, 1,
|
|
58
|
+
LL2NUM(timestamp_ns.nanos)
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
return Qnil;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
VALUE rbduckdb_timestamp_s_to_ruby(duckdb_timestamp_s ts) {
|
|
65
|
+
VALUE obj = infinite_timestamp_s_value(ts);
|
|
66
|
+
if (obj != Qnil) {
|
|
67
|
+
return obj;
|
|
68
|
+
}
|
|
69
|
+
return rb_funcall(mDuckDBConverter, id__to_time_from_duckdb_timestamp_s, 1,
|
|
70
|
+
LL2NUM(ts.seconds)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
VALUE rbduckdb_timestamp_ms_to_ruby(duckdb_timestamp_ms ts) {
|
|
75
|
+
VALUE obj = infinite_timestamp_ms_value(ts);
|
|
76
|
+
if (obj != Qnil) {
|
|
77
|
+
return obj;
|
|
78
|
+
}
|
|
79
|
+
return rb_funcall(mDuckDBConverter, id__to_time_from_duckdb_timestamp_ms, 1,
|
|
80
|
+
LL2NUM(ts.millis)
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
VALUE rbduckdb_timestamp_ns_to_ruby(duckdb_timestamp_ns ts) {
|
|
85
|
+
VALUE obj = infinite_timestamp_ns_value(ts);
|
|
86
|
+
if (obj != Qnil) {
|
|
87
|
+
return obj;
|
|
88
|
+
}
|
|
89
|
+
return rb_funcall(mDuckDBConverter, id__to_time_from_duckdb_timestamp_ns, 1,
|
|
90
|
+
LL2NUM(ts.nanos)
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
VALUE rbduckdb_time_tz_to_ruby(duckdb_time_tz tz) {
|
|
95
|
+
duckdb_time_tz_struct data = duckdb_from_time_tz(tz);
|
|
96
|
+
return rb_funcall(mDuckDBConverter, id__to_time_from_duckdb_time_tz, 5,
|
|
97
|
+
INT2FIX(data.time.hour),
|
|
98
|
+
INT2FIX(data.time.min),
|
|
99
|
+
INT2FIX(data.time.sec),
|
|
100
|
+
INT2NUM(data.time.micros),
|
|
101
|
+
INT2NUM(data.offset)
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
VALUE rbduckdb_timestamp_tz_to_ruby(duckdb_timestamp ts) {
|
|
106
|
+
return rb_funcall(mDuckDBConverter, id__to_time_from_duckdb_timestamp_tz, 1,
|
|
107
|
+
LL2NUM(ts.micros)
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
VALUE rbduckdb_time_to_ruby(duckdb_time t) {
|
|
112
|
+
duckdb_time_struct data = duckdb_from_time(t);
|
|
113
|
+
return rb_funcall(mDuckDBConverter, id__to_time_from_duckdb_time, 4,
|
|
114
|
+
INT2FIX(data.hour),
|
|
115
|
+
INT2FIX(data.min),
|
|
116
|
+
INT2FIX(data.sec),
|
|
117
|
+
INT2NUM(data.micros)
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
VALUE rbduckdb_date_to_ruby(duckdb_date date) {
|
|
122
|
+
VALUE obj = infinite_date_value(date);
|
|
123
|
+
|
|
124
|
+
if (obj == Qnil) {
|
|
125
|
+
duckdb_date_struct date_st = duckdb_from_date(date);
|
|
126
|
+
obj = rb_funcall(mDuckDBConverter, id__to_date, 3,
|
|
127
|
+
INT2FIX(date_st.year),
|
|
128
|
+
INT2FIX(date_st.month),
|
|
129
|
+
INT2FIX(date_st.day)
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
return obj;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
VALUE rbduckdb_timestamp_to_ruby(duckdb_timestamp ts) {
|
|
136
|
+
VALUE obj = infinite_timestamp_value(ts);
|
|
137
|
+
|
|
138
|
+
if (obj == Qnil) {
|
|
139
|
+
duckdb_timestamp_struct data_st = duckdb_from_timestamp(ts);
|
|
140
|
+
obj = rb_funcall(mDuckDBConverter, id__to_time, 7,
|
|
141
|
+
INT2FIX(data_st.date.year),
|
|
142
|
+
INT2FIX(data_st.date.month),
|
|
143
|
+
INT2FIX(data_st.date.day),
|
|
144
|
+
INT2FIX(data_st.time.hour),
|
|
145
|
+
INT2FIX(data_st.time.min),
|
|
146
|
+
INT2FIX(data_st.time.sec),
|
|
147
|
+
INT2NUM(data_st.time.micros)
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
return obj;
|
|
151
|
+
}
|
|
152
|
+
|
|
5
153
|
void rbduckdb_init_duckdb_converter(void) {
|
|
6
154
|
mDuckDBConverter = rb_define_module_under(mDuckDB, "Converter");
|
|
155
|
+
|
|
156
|
+
id__to_date = rb_intern("_to_date");
|
|
157
|
+
id__to_time = rb_intern("_to_time");
|
|
158
|
+
id__to_time_from_duckdb_time = rb_intern("_to_time_from_duckdb_time");
|
|
159
|
+
id__to_interval_from_vector = rb_intern("_to_interval_from_vector");
|
|
160
|
+
id__to_hugeint_from_vector = rb_intern("_to_hugeint_from_vector");
|
|
161
|
+
id__to_decimal_from_hugeint = rb_intern("_to_decimal_from_hugeint");
|
|
162
|
+
id__to_uuid_from_vector = rb_intern("_to_uuid_from_vector");
|
|
163
|
+
id__to_time_from_duckdb_timestamp_s = rb_intern("_to_time_from_duckdb_timestamp_s");
|
|
164
|
+
id__to_time_from_duckdb_timestamp_ms = rb_intern("_to_time_from_duckdb_timestamp_ms");
|
|
165
|
+
id__to_time_from_duckdb_timestamp_ns = rb_intern("_to_time_from_duckdb_timestamp_ns");
|
|
166
|
+
id__to_time_from_duckdb_time_tz = rb_intern("_to_time_from_duckdb_time_tz");
|
|
167
|
+
id__to_time_from_duckdb_timestamp_tz = rb_intern("_to_time_from_duckdb_timestamp_tz");
|
|
168
|
+
id__to_infinity = rb_intern("_to_infinity");
|
|
7
169
|
}
|
data/ext/duckdb/duckdb.c
CHANGED
|
@@ -57,11 +57,14 @@ Init_duckdb_native(void) {
|
|
|
57
57
|
rbduckdb_init_duckdb_instance_cache();
|
|
58
58
|
rbduckdb_init_duckdb_value_impl();
|
|
59
59
|
rbduckdb_init_duckdb_scalar_function();
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
rbduckdb_init_duckdb_expression();
|
|
61
|
+
rbduckdb_init_duckdb_client_context();
|
|
62
|
+
rbduckdb_init_duckdb_scalar_function_bind_info();
|
|
63
63
|
rbduckdb_init_duckdb_vector();
|
|
64
64
|
rbduckdb_init_duckdb_data_chunk();
|
|
65
65
|
rbduckdb_init_memory_helper();
|
|
66
66
|
rbduckdb_init_duckdb_table_function();
|
|
67
|
+
rbduckdb_init_duckdb_table_function_bind_info();
|
|
68
|
+
rbduckdb_init_duckdb_table_function_init_info();
|
|
69
|
+
rbduckdb_init_duckdb_table_function_function_info();
|
|
67
70
|
}
|