duckdb-polars 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f9cddc685bb883a6dfbac6e9286db555782da12ccced9981957b44635185b8e5
4
+ data.tar.gz: dd27aa1692d841371a833ac04b0e56854c27ab6464d0eef9f38efb248e432470
5
+ SHA512:
6
+ metadata.gz: 3256b6d4d76664fb8e86dbcf5ed3da1350c4864e4e27056f83e5251a59d9a9f0b4b8add3c22369abf1160f393c466152d9770099f126eaca7937480ce97be5ee
7
+ data.tar.gz: dbb07b8a4d11527f59a4372e47c9c6ae63454c3d6d736d7a64f66c6ea6ca45dbb1aaf62aa07980a2340037644bc9fe6c34e44cf2dcb2d7af4200f35ac02168de
@@ -0,0 +1,41 @@
1
+ # Copilot Instructions
2
+
3
+ ## Commands
4
+
5
+ ```sh
6
+ bundle exec rake # run full test suite (default task also runs clobber first)
7
+ bundle exec rake test # run tests only
8
+ bundle exec ruby -Ilib:test test/duckdb/polars/data_frame/table_adapter_test.rb # run a single test file
9
+ bundle exec rubocop # lint
10
+ ```
11
+
12
+ ## Architecture
13
+
14
+ This gem (`duckdb-polars`) bridges [ruby-duckdb](https://github.com/suketa/ruby-duckdb) and [polars-df](https://github.com/ankane/polars-ruby) by registering a `TableAdapter` that allows a `Polars::DataFrame` to be exposed as a queryable DuckDB table via `DuckDB::TableFunction`.
15
+
16
+ ### Entry points
17
+
18
+ - `lib/duckdb/polars-df.rb` — the hyphenated filename is the gem's `require` entry point (matches the gem name); it simply delegates to `lib/duckdb/polars.rb`
19
+ - `lib/duckdb/polars.rb` — loads `version.rb` and the `TableAdapter`
20
+
21
+ ### Core class: `DuckDB::Polars::DataFrame::TableAdapter`
22
+
23
+ - `TableAdapter.register!` — registers an instance with `DuckDB::TableFunction.add_table_adapter(::Polars::DataFrame, ...)`, so that calling `connection.expose_as_table(df, 'name')` on a `Polars::DataFrame` automatically uses this adapter
24
+ - `#call(data_frame, name, columns:)` — creates a `DuckDB::TableFunction` from the DataFrame; `columns` is a hash of `{ column_name => DuckDB::LogicalType }` and defaults to inferred types via `infer_columns`
25
+ - Row iteration is implemented as a closure with a mutable `counter` local variable; the proc resets `counter` to `0` when called after exhausting all rows
26
+
27
+ ### Type mapping: `DuckDB::Polars::TypeMappings`
28
+
29
+ Maps Polars types to DuckDB types. Currently maps `Polars::Int64 → :bigint` and `Polars::String → :varchar`; all other types fall back to `:varchar`. Add entries to `TO_DUCKDB_TYPES` to support additional types.
30
+
31
+ ### Test conventions
32
+
33
+ - Tests must call `@con.execute('SET threads=1')` before invoking any `TableFunction`; DuckDB's table function execution requires single-threaded mode
34
+ - All query results reflect the inferred DuckDB types: `Int64` columns return as integers, `String` columns as strings, etc. Assertions compare native Ruby types (e.g., `assert_equal [1, 'Alice', 30], result[0]`)
35
+
36
+ ## Conventions
37
+
38
+ - All files use `# frozen_string_literal: true`
39
+ - RuboCop is configured with `rubocop-minitest` and `rubocop-rake` plugins; max line length is 120
40
+ - Ruby ≥ 3.3 required; use modern syntax (numbered block parameters, hash shorthand, etc.)
41
+ - The `Naming/FileName` cop is disabled for `lib/duckdb/polars-df.rb` to allow the hyphenated filename
@@ -0,0 +1,40 @@
1
+ name: Linter
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ types:
9
+ - opened
10
+ - synchronize
11
+ - reopened
12
+
13
+ concurrency:
14
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
15
+ cancel-in-progress: true
16
+
17
+ jobs:
18
+ rubocop:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Download duckdb
24
+ run: |
25
+ curl -sLO https://github.com/duckdb/duckdb/releases/download/v1.4.4/libduckdb-linux-amd64.zip
26
+ mkdir -p duckdb-v1.4.4
27
+ unzip libduckdb-linux-amd64.zip -d duckdb-v1.4.4
28
+
29
+ - name: Set up Ruby
30
+ uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: '3.3'
33
+
34
+ - name: bundle install
35
+ run: |
36
+ bundle config build.duckdb "--with-duckdb-include=${GITHUB_WORKSPACE}/duckdb-v1.4.4 --with-duckdb-lib=${GITHUB_WORKSPACE}/duckdb-v1.4.4"
37
+ bundle install --jobs 4 --retry 3
38
+
39
+ - name: Run RuboCop
40
+ run: bundle exec rubocop
@@ -0,0 +1,76 @@
1
+ name: Test
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ types:
9
+ - opened
10
+ - synchronize
11
+ - reopened
12
+
13
+ concurrency:
14
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
15
+ cancel-in-progress: true
16
+
17
+ jobs:
18
+ test:
19
+ runs-on: ${{ matrix.os }}
20
+ timeout-minutes: 30
21
+ strategy:
22
+ matrix:
23
+ os: [ubuntu-latest, macos-latest]
24
+ ruby: ['3.3', '3.4']
25
+ duckdb: ['1.4.4']
26
+ include:
27
+ - os: ubuntu-latest
28
+ duckdb_asset: libduckdb-linux-amd64.zip
29
+ - os: macos-latest
30
+ duckdb_asset: libduckdb-osx-universal.zip
31
+
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+
35
+ - name: duckdb cache
36
+ id: duckdb-cache
37
+ uses: actions/cache@v4
38
+ with:
39
+ path: duckdb-v${{ matrix.duckdb }}
40
+ key: ${{ runner.os }}-duckdb-v${{ matrix.duckdb }}
41
+
42
+ - name: Download duckdb ${{ matrix.duckdb }}
43
+ if: steps.duckdb-cache.outputs.cache-hit != 'true'
44
+ run: |
45
+ curl -sLO https://github.com/duckdb/duckdb/releases/download/v${{ matrix.duckdb }}/${{ matrix.duckdb_asset }}
46
+ mkdir -p duckdb-v${{ matrix.duckdb }}
47
+ unzip ${{ matrix.duckdb_asset }} -d duckdb-v${{ matrix.duckdb }}
48
+
49
+ - name: Set up Ruby ${{ matrix.ruby }}
50
+ uses: ruby/setup-ruby@v1
51
+ with:
52
+ ruby-version: ${{ matrix.ruby }}
53
+
54
+ - name: bundle install
55
+ run: |
56
+ bundle config build.duckdb "--with-duckdb-include=${GITHUB_WORKSPACE}/duckdb-v${{ matrix.duckdb }} --with-duckdb-lib=${GITHUB_WORKSPACE}/duckdb-v${{ matrix.duckdb }}"
57
+ bundle install --jobs 4 --retry 3
58
+
59
+ - name: Run tests (Linux)
60
+ if: runner.os == 'Linux'
61
+ run: |
62
+ export LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/duckdb-v${{ matrix.duckdb }}:${LD_LIBRARY_PATH}
63
+ bundle exec rake test
64
+
65
+ - name: Run tests (macOS)
66
+ if: runner.os == 'macOS'
67
+ run: |
68
+ export DYLD_LIBRARY_PATH=${GITHUB_WORKSPACE}/duckdb-v${{ matrix.duckdb }}:${DYLD_LIBRARY_PATH}
69
+ bundle exec rake test
70
+
71
+ post-test:
72
+ name: All tests passed
73
+ runs-on: ubuntu-latest
74
+ needs: test
75
+ steps:
76
+ - run: echo ok
data/.rubocop.yml ADDED
@@ -0,0 +1,35 @@
1
+ plugins:
2
+ - rubocop-minitest
3
+ - rubocop-rake
4
+
5
+ AllCops:
6
+ NewCops: enable
7
+ TargetRubyVersion: 3.3
8
+ Exclude:
9
+ - 'vendor/**/*'
10
+ - 'tmp/**/*'
11
+ - 'pkg/**/*'
12
+
13
+ Naming/FileName:
14
+ Exclude:
15
+ - 'lib/duckdb/polars-df.rb'
16
+ Metrics/BlockLength:
17
+ Exclude:
18
+ - 'test/**/*'
19
+ - 'duckdb.gemspec'
20
+
21
+ Metrics/ClassLength:
22
+ Exclude:
23
+ - 'test/**/*_test.rb'
24
+ - 'lib/duckdb/prepared_statement.rb'
25
+ - 'lib/duckdb/appender.rb'
26
+
27
+ Metrics/ModuleLength:
28
+ Exclude:
29
+ - 'lib/duckdb/converter.rb'
30
+
31
+ Style/Documentation:
32
+ Enabled: false
33
+
34
+ Layout/LineLength:
35
+ Max: 120
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ # Unreleased
6
+
7
+ # 0.0.1 - 2026-03-08
8
+ - add DuckDB::Polars::DataFrame::TableAdapter
9
+
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ gem 'minitest', '~> 6.0'
8
+ gem 'rake', '~> 13.0'
9
+ gem 'rubocop', require: false
10
+ gem 'rubocop-minitest', require: false
11
+ gem 'rubocop-rake', require: false
data/Gemfile.lock ADDED
@@ -0,0 +1,110 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ duckdb-polars (0.0.1)
5
+ duckdb (>= 1.4.4.0)
6
+ polars-df (>= 0.25.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ addressable (2.8.9)
12
+ public_suffix (>= 2.0.2, < 8.0)
13
+ ast (2.4.3)
14
+ bigdecimal (4.0.1)
15
+ drb (2.2.3)
16
+ duckdb (1.4.4.0)
17
+ bigdecimal (>= 3.1.4)
18
+ json (2.19.0)
19
+ json-schema (6.2.0)
20
+ addressable (~> 2.8)
21
+ bigdecimal (>= 3.1, < 5)
22
+ language_server-protocol (3.17.0.5)
23
+ lint_roller (1.1.0)
24
+ mcp (0.8.0)
25
+ json-schema (>= 4.1)
26
+ minitest (6.0.2)
27
+ drb (~> 2.0)
28
+ prism (~> 1.5)
29
+ parallel (1.27.0)
30
+ parser (3.3.10.2)
31
+ ast (~> 2.4.1)
32
+ racc
33
+ polars-df (0.25.0-x86_64-linux)
34
+ bigdecimal
35
+ prism (1.9.0)
36
+ public_suffix (7.0.5)
37
+ racc (1.8.1)
38
+ rainbow (3.1.1)
39
+ rake (13.3.1)
40
+ regexp_parser (2.11.3)
41
+ rubocop (1.85.1)
42
+ json (~> 2.3)
43
+ language_server-protocol (~> 3.17.0.2)
44
+ lint_roller (~> 1.1.0)
45
+ mcp (~> 0.6)
46
+ parallel (~> 1.10)
47
+ parser (>= 3.3.0.2)
48
+ rainbow (>= 2.2.2, < 4.0)
49
+ regexp_parser (>= 2.9.3, < 3.0)
50
+ rubocop-ast (>= 1.49.0, < 2.0)
51
+ ruby-progressbar (~> 1.7)
52
+ unicode-display_width (>= 2.4.0, < 4.0)
53
+ rubocop-ast (1.49.0)
54
+ parser (>= 3.3.7.2)
55
+ prism (~> 1.7)
56
+ rubocop-minitest (0.39.1)
57
+ lint_roller (~> 1.1)
58
+ rubocop (>= 1.75.0, < 2.0)
59
+ rubocop-ast (>= 1.38.0, < 2.0)
60
+ rubocop-rake (0.7.1)
61
+ lint_roller (~> 1.1)
62
+ rubocop (>= 1.72.1)
63
+ ruby-progressbar (1.13.0)
64
+ unicode-display_width (3.2.0)
65
+ unicode-emoji (~> 4.1)
66
+ unicode-emoji (4.2.0)
67
+
68
+ PLATFORMS
69
+ x86_64-linux
70
+
71
+ DEPENDENCIES
72
+ duckdb-polars!
73
+ minitest (~> 6.0)
74
+ rake (~> 13.0)
75
+ rubocop
76
+ rubocop-minitest
77
+ rubocop-rake
78
+
79
+ CHECKSUMS
80
+ addressable (2.8.9) sha256=cc154fcbe689711808a43601dee7b980238ce54368d23e127421753e46895485
81
+ ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
82
+ bigdecimal (4.0.1) sha256=8b07d3d065a9f921c80ceaea7c9d4ae596697295b584c296fe599dd0ad01c4a7
83
+ drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373
84
+ duckdb (1.4.4.0) sha256=11ef69d0987eb237bfa2ab295301c437a55ff8d014d92abb510e757c9193b51c
85
+ duckdb-polars (0.0.1)
86
+ json (2.19.0) sha256=bc5202f083618b3af7aba3184146ec9d820f8f6de261838b577173475e499d9a
87
+ json-schema (6.2.0) sha256=e8bff46ed845a22c1ab2bd0d7eccf831c01fe23bb3920caa4c74db4306813666
88
+ language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
89
+ lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
90
+ mcp (0.8.0) sha256=ae8bd146bb8e168852866fd26f805f52744f6326afb3211e073f78a95e0c34fb
91
+ minitest (6.0.2) sha256=db6e57956f6ecc6134683b4c87467d6dd792323c7f0eea7b93f66bd284adbc3d
92
+ parallel (1.27.0) sha256=4ac151e1806b755fb4e2dc2332cbf0e54f2e24ba821ff2d3dcf86bf6dc4ae130
93
+ parser (3.3.10.2) sha256=6f60c84aa4bdcedb6d1a2434b738fe8a8136807b6adc8f7f53b97da9bc4e9357
94
+ polars-df (0.25.0-x86_64-linux) sha256=f18e1080203187ecd7f0a1f7789c2dec90cc5ddc54d58e53e070db9c3d4b6dda
95
+ prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
96
+ public_suffix (7.0.5) sha256=1a8bb08f1bbea19228d3bed6e5ed908d1cb4f7c2726d18bd9cadf60bc676f623
97
+ racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
98
+ rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
99
+ rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c
100
+ regexp_parser (2.11.3) sha256=ca13f381a173b7a93450e53459075c9b76a10433caadcb2f1180f2c741fc55a4
101
+ rubocop (1.85.1) sha256=3dbcf9e961baa4c376eeeb2a03913dca5e3987033b04d38fa538aa1e7406cc77
102
+ rubocop-ast (1.49.0) sha256=49c3676d3123a0923d333e20c6c2dbaaae2d2287b475273fddee0c61da9f71fd
103
+ rubocop-minitest (0.39.1) sha256=998398d6da4026d297f0f9bf709a1eac5f2b6947c24431f94af08138510cf7ed
104
+ rubocop-rake (0.7.1) sha256=3797f2b6810c3e9df7376c26d5f44f3475eda59eb1adc38e6f62ecf027cbae4d
105
+ ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
106
+ unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
107
+ unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
108
+
109
+ BUNDLED WITH
110
+ 4.0.4
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 suketa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # ruby-duckdb-polars
2
+
3
+ ## Description
4
+
5
+ This gem `duckdb-polars` provides a Polars DataFrame table adapter for [ruby-duckdb](https://github.com/suketa/ruby-duckdb).
6
+ You can query Ruby's `Polars::DataFrame` objects using SQL through DuckDB by using this gem.
7
+ This gem is a sample implementation of a `DuckDB::TableFunction`.
8
+
9
+ ## Requirement
10
+
11
+ - Ruby >= 3.3
12
+ - [duckdb](https://github.com/suketa/ruby-duckdb)
13
+ - [polars-df](https://github.com/ankane/polars-ruby)
14
+
15
+ ## How to install
16
+
17
+ ```sh
18
+ gem install duckdb-polars
19
+ ```
20
+
21
+ Or add the following line to your `Gemfile`:
22
+
23
+ ```ruby
24
+ gem 'duckdb-polars'
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ### Basic usage
30
+
31
+ ```ruby
32
+ require 'duckdb'
33
+ require 'duckdb/polars-df'
34
+
35
+ db = DuckDB::Database.open
36
+ con = db.connect
37
+
38
+ df = Polars::DataFrame.new(
39
+ {
40
+ id: [1, 2, 3],
41
+ name: %w[Alice Bob Charlie],
42
+ age: [30, 25, 35]
43
+ }
44
+ )
45
+
46
+ DuckDB::Polars::DataFrame::TableAdapter.register!
47
+
48
+ con.execute('SET threads=1') # currently the Polars table adapter is not thread-safe, so we set threads to 1
49
+ con.expose_as_table(df, 'polars_table')
50
+ result = con.query('SELECT * FROM polars_table()')
51
+ result.each do |row|
52
+ puts row.inspect
53
+ end
54
+ # => [1, "Alice", 30]
55
+ # => [2, "Bob", 25]
56
+ # => [3, "Charlie", 35]
57
+ ```
58
+
59
+ ### Specifying column types
60
+
61
+ By default, columns are inferred from the DataFrame's schema (`Int64` → `BIGINT`, `String` → `VARCHAR`; all other types fall back to `VARCHAR`). You can override column types using the `columns` option.
62
+
63
+ ```ruby
64
+ require 'duckdb'
65
+ require 'duckdb/polars-df'
66
+
67
+ db = DuckDB::Database.open
68
+ con = db.connect
69
+
70
+ df = Polars::DataFrame.new(
71
+ {
72
+ id: [1, 2, 3],
73
+ name: %w[Alice Bob Charlie],
74
+ age: [30, 25, 35]
75
+ }
76
+ )
77
+
78
+ DuckDB::Polars::DataFrame::TableAdapter.register!
79
+
80
+ con.execute('SET threads=1') # currently the Polars table adapter is not thread-safe, so we set threads to 1
81
+ con.expose_as_table(
82
+ df, 'polars_table',
83
+ columns: {
84
+ 'id' => :bigint,
85
+ 'name' => :varchar,
86
+ 'age' => :bigint
87
+ }
88
+ )
89
+
90
+ result = con.query('SELECT * FROM polars_table()')
91
+ result.each do |row|
92
+ puts row.inspect
93
+ end
94
+ # => [1, "Alice", 30]
95
+ # => [2, "Bob", 25]
96
+ # => [3, "Charlie", 35]
97
+ ```
98
+
99
+ ## License
100
+
101
+ [MIT License](LICENSE).
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
+
6
+ test_config = lambda do |t|
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/*_test.rb']
10
+ end
11
+
12
+ Rake::TestTask.new(:test, &test_config)
13
+ task default: %i[clobber test]
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'duckdb/polars/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'duckdb-polars'
9
+ spec.version = DuckDB::Polars::VERSION
10
+ spec.authors = ['Masaki Suketa']
11
+ spec.email = ['masaki.suketa@nifty.ne.jp']
12
+
13
+ spec.summary = 'This module provides Polars table adapter for duckdb.'
14
+ spec.description = 'This module provides Polars table adapter for duckdb. ' \
15
+ 'You can access Polars::DataFrame as duckdb table by using this module.'
16
+ spec.homepage = 'https://github.com/suketa/ruby-duckdb-polars'
17
+ spec.license = 'MIT'
18
+
19
+ spec.metadata['rubygems_mfa_required'] = 'true'
20
+ spec.metadata['homepage_uri'] = spec.homepage
21
+ spec.metadata['source_code_uri'] = 'https://github.com/suketa/ruby-duckdb-polars'
22
+ spec.metadata['changelog_uri'] = 'https://github.com/suketa/ruby-duckdb-polars/blob/master/CHANGELOG.md'
23
+
24
+ # Specify which files should be added to the gem when it is released.
25
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
26
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
27
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
28
+ end
29
+ spec.require_paths = ['lib']
30
+ spec.required_ruby_version = '>= 3.3.0'
31
+ spec.add_dependency 'duckdb', '>= 1.4.4.0'
32
+ spec.add_dependency 'polars-df', '>= 0.25.0'
33
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'duckdb'
4
+ require 'polars-df'
5
+ require_relative '../type_mappings'
6
+
7
+ module DuckDB
8
+ module Polars
9
+ module DataFrame
10
+ class TableAdapter
11
+ class << self
12
+ def register!
13
+ DuckDB::TableFunction.add_table_adapter(::Polars::DataFrame, new)
14
+ end
15
+ end
16
+
17
+ def call(data_frame, name, columns: nil)
18
+ columns ||= infer_columns(data_frame)
19
+ DuckDB::TableFunction.create(name:, columns:, &execute_block(data_frame))
20
+ end
21
+
22
+ private
23
+
24
+ def execute_block(data_frame)
25
+ counter = 0
26
+ height = data_frame.height
27
+ width = data_frame.width
28
+ proc do |_func_info, output|
29
+ next counter = 0 if counter >= height
30
+
31
+ write_row(data_frame, output, counter, width)
32
+ counter += 1
33
+ 1
34
+ end
35
+ end
36
+
37
+ def write_row(data_frame, output, counter, width)
38
+ width.times do |index|
39
+ type = output.get_vector(index).logical_type
40
+ output.set_value(index, 0, DuckDB.cast(data_frame[counter, index], type))
41
+ end
42
+ end
43
+
44
+ def infer_columns(data_frame)
45
+ data_frame.schema.to_h { |name, polars_type| [name, DuckDB::Polars::TypeMappings.to_duckdb(polars_type)] }
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'polars-df'
4
+
5
+ module DuckDB
6
+ module Polars
7
+ module TypeMappings
8
+ TO_DUCKDB_TYPES = {
9
+ ::Polars::Int64 => :bigint,
10
+ ::Polars::String => :varchar
11
+ }.freeze
12
+
13
+ def self.to_duckdb(polars_type)
14
+ TO_DUCKDB_TYPES[polars_type.class] || :varchar
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DuckDB
4
+ module Polars
5
+ # The version string of ruby-duckdb-csv.
6
+ VERSION = '0.0.1'
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'polars'
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'polars/version'
4
+ require_relative 'polars/type_mappings'
5
+ require_relative 'polars/data_frame/table_adapter'
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: duckdb-polars
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Masaki Suketa
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: duckdb
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 1.4.4.0
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 1.4.4.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: polars-df
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.25.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 0.25.0
40
+ description: This module provides Polars table adapter for duckdb. You can access
41
+ Polars::DataFrame as duckdb table by using this module.
42
+ email:
43
+ - masaki.suketa@nifty.ne.jp
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".github/copilot-instructions.md"
49
+ - ".github/workflows/linter.yml"
50
+ - ".github/workflows/test.yml"
51
+ - ".rubocop.yml"
52
+ - CHANGELOG.md
53
+ - Gemfile
54
+ - Gemfile.lock
55
+ - LICENSE
56
+ - README.md
57
+ - Rakefile
58
+ - duckdb-polars.gemspec
59
+ - lib/duckdb/polars-df.rb
60
+ - lib/duckdb/polars.rb
61
+ - lib/duckdb/polars/data_frame/table_adapter.rb
62
+ - lib/duckdb/polars/type_mappings.rb
63
+ - lib/duckdb/polars/version.rb
64
+ homepage: https://github.com/suketa/ruby-duckdb-polars
65
+ licenses:
66
+ - MIT
67
+ metadata:
68
+ rubygems_mfa_required: 'true'
69
+ homepage_uri: https://github.com/suketa/ruby-duckdb-polars
70
+ source_code_uri: https://github.com/suketa/ruby-duckdb-polars
71
+ changelog_uri: https://github.com/suketa/ruby-duckdb-polars/blob/master/CHANGELOG.md
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: 3.3.0
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubygems_version: 4.0.3
87
+ specification_version: 4
88
+ summary: This module provides Polars table adapter for duckdb.
89
+ test_files: []