duckdb 1.1.3.1 → 1.2.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/make_documents.yml +34 -0
- data/.github/workflows/test_on_macos.yml +2 -3
- data/.github/workflows/test_on_ubuntu.yml +2 -2
- data/.github/workflows/test_on_windows.yml +2 -2
- data/.gitignore +1 -0
- data/.rdoc_options +22 -0
- data/CHANGELOG.md +63 -0
- data/Dockerfile +2 -2
- data/Gemfile.lock +14 -12
- data/README.md +2 -1
- data/duckdb.gemspec +1 -0
- data/ext/duckdb/appender.c +140 -173
- data/ext/duckdb/blob.c +3 -0
- data/ext/duckdb/column.c +33 -3
- data/ext/duckdb/config.c +3 -0
- data/ext/duckdb/connection.c +6 -0
- data/ext/duckdb/database.c +6 -0
- data/ext/duckdb/duckdb.c +1 -0
- data/ext/duckdb/error.c +3 -0
- data/ext/duckdb/extconf.rb +5 -8
- data/ext/duckdb/extracted_statements.c +3 -0
- data/ext/duckdb/logical_type.c +323 -0
- data/ext/duckdb/logical_type.h +13 -0
- data/ext/duckdb/pending_result.c +5 -0
- data/ext/duckdb/prepared_statement.c +64 -6
- data/ext/duckdb/result.c +17 -45
- data/ext/duckdb/ruby-duckdb.h +6 -8
- data/lib/duckdb/appender.rb +458 -56
- data/lib/duckdb/column.rb +0 -2
- data/lib/duckdb/interval.rb +12 -10
- data/lib/duckdb/logical_type.rb +110 -0
- data/lib/duckdb/pending_result.rb +1 -1
- data/lib/duckdb/prepared_statement.rb +18 -1
- data/lib/duckdb/result.rb +16 -16
- data/lib/duckdb/version.rb +1 -1
- data/lib/duckdb.rb +1 -0
- metadata +9 -6
data/lib/duckdb/interval.rb
CHANGED
@@ -24,11 +24,11 @@ module DuckDB
|
|
24
24
|
# con.query('CREATE TABLE intervals (interval_value INTERVAL)')
|
25
25
|
# appender = con.appender('intervals')
|
26
26
|
# appender
|
27
|
-
# .begin_row
|
28
27
|
# .append_interval(interval)
|
29
28
|
# .end_row
|
30
29
|
# .flush
|
31
30
|
class Interval
|
31
|
+
# :stopdoc:
|
32
32
|
ISO8601_REGEXP = Regexp.compile(
|
33
33
|
'(?<negativ>-{0,1})P
|
34
34
|
(?<year>-{0,1}\d+Y){0,1}
|
@@ -40,6 +40,8 @@ module DuckDB
|
|
40
40
|
((?<sec>-{0,1}\d+)\.{0,1}(?<usec>\d*)S){0,1}',
|
41
41
|
Regexp::EXTENDED
|
42
42
|
)
|
43
|
+
private_constant :ISO8601_REGEXP
|
44
|
+
# :startdoc:
|
43
45
|
|
44
46
|
class << self
|
45
47
|
# parses the ISO8601 format string and return the Interval object.
|
@@ -93,7 +95,7 @@ module DuckDB
|
|
93
95
|
|
94
96
|
private
|
95
97
|
|
96
|
-
def matched_to_i(matched)
|
98
|
+
def matched_to_i(matched) # :nodoc:
|
97
99
|
sign = to_sign(matched)
|
98
100
|
sec = to_sec(matched)
|
99
101
|
usec = to_usec(matched)
|
@@ -104,35 +106,35 @@ module DuckDB
|
|
104
106
|
sign.positive? ? value : value.map { |v| v * sign }
|
105
107
|
end
|
106
108
|
|
107
|
-
def to_sign(matched)
|
109
|
+
def to_sign(matched) # :nodoc:
|
108
110
|
matched[:negativ] == '-' ? -1 : 1
|
109
111
|
end
|
110
112
|
|
111
|
-
def to_year(matched)
|
113
|
+
def to_year(matched) # :nodoc:
|
112
114
|
matched[:year].to_i
|
113
115
|
end
|
114
116
|
|
115
|
-
def to_month(matched)
|
117
|
+
def to_month(matched) # :nodoc:
|
116
118
|
matched[:month].to_i
|
117
119
|
end
|
118
120
|
|
119
|
-
def to_day(matched)
|
121
|
+
def to_day(matched) # :nodoc:
|
120
122
|
matched[:day].to_i
|
121
123
|
end
|
122
124
|
|
123
|
-
def to_hour(matched)
|
125
|
+
def to_hour(matched) # :nodoc:
|
124
126
|
matched[:hour].to_i
|
125
127
|
end
|
126
128
|
|
127
|
-
def to_min(matched)
|
129
|
+
def to_min(matched) # :nodoc:
|
128
130
|
matched[:min].to_i
|
129
131
|
end
|
130
132
|
|
131
|
-
def to_sec(matched)
|
133
|
+
def to_sec(matched) # :nodoc:
|
132
134
|
matched[:sec].to_i
|
133
135
|
end
|
134
136
|
|
135
|
-
def to_usec(matched)
|
137
|
+
def to_usec(matched) # :nodoc:
|
136
138
|
matched[:usec].to_s.ljust(6, '0')[0, 6].to_i
|
137
139
|
end
|
138
140
|
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DuckDB
|
4
|
+
class LogicalType
|
5
|
+
# returns logical type's type symbol
|
6
|
+
# `:unknown` means that the logical type's type is unknown/unsupported by ruby-duckdb.
|
7
|
+
# `:invalid` means that the logical type's type is invalid in duckdb.
|
8
|
+
#
|
9
|
+
# require 'duckdb'
|
10
|
+
# db = DuckDB::Database.open
|
11
|
+
# con = db.connect
|
12
|
+
# con.query('CREATE TABLE climates (id INTEGER, temperature DECIMAIL)')
|
13
|
+
#
|
14
|
+
# users = con.query('SELECT * FROM climates')
|
15
|
+
# columns = users.columns
|
16
|
+
# columns.second.logical_type.type #=> :decimal
|
17
|
+
def type
|
18
|
+
type_id = _type
|
19
|
+
DuckDB::Converter::IntToSym.type_to_sym(type_id)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Iterates over each union member name.
|
23
|
+
#
|
24
|
+
# When a block is provided, this method yields each union member name in
|
25
|
+
# order. It also returns the total number of members yielded.
|
26
|
+
#
|
27
|
+
# union_logical_type.each_member_name do |name|
|
28
|
+
# puts "Union member: #{name}"
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# If no block is given, an Enumerator is returned, which can be used to
|
32
|
+
# retrieve all member names.
|
33
|
+
#
|
34
|
+
# names = union_logical_type.each_member_name.to_a
|
35
|
+
# # => ["member1", "member2"]
|
36
|
+
def each_member_name
|
37
|
+
return to_enum(__method__) {member_count} unless block_given?
|
38
|
+
|
39
|
+
member_count.times do |i|
|
40
|
+
yield member_name_at(i)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Iterates over each union member type.
|
45
|
+
#
|
46
|
+
# When a block is provided, this method yields each union member logical
|
47
|
+
# type in order. It also returns the total number of members yielded.
|
48
|
+
#
|
49
|
+
# union_logical_type.each_member_type do |logical_type|
|
50
|
+
# puts "Union member: #{logical_type.type}"
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# If no block is given, an Enumerator is returned, which can be used to
|
54
|
+
# retrieve all member logical types.
|
55
|
+
#
|
56
|
+
# names = union_logical_type.each_member_type.map(&:type)
|
57
|
+
# # => [:varchar, :integer]
|
58
|
+
def each_member_type
|
59
|
+
return to_enum(__method__) {member_count} unless block_given?
|
60
|
+
|
61
|
+
member_count.times do |i|
|
62
|
+
yield member_type_at(i)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Iterates over each struct child name.
|
67
|
+
#
|
68
|
+
# When a block is provided, this method yields each struct child name in
|
69
|
+
# order. It also returns the total number of children yielded.
|
70
|
+
#
|
71
|
+
# struct_logical_type.each_child_name do |name|
|
72
|
+
# puts "Struct child: #{name}"
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# If no block is given, an Enumerator is returned, which can be used to
|
76
|
+
# retrieve all child names.
|
77
|
+
#
|
78
|
+
# names = struct_logical_type.each_child_name.to_a
|
79
|
+
# # => ["child1", "child2"]
|
80
|
+
def each_child_name
|
81
|
+
return to_enum(__method__) {child_count} unless block_given?
|
82
|
+
|
83
|
+
child_count.times do |i|
|
84
|
+
yield child_name_at(i)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Iterates over each struct child type.
|
89
|
+
#
|
90
|
+
# When a block is provided, this method yields each struct child type in
|
91
|
+
# order. It also returns the total number of children yielded.
|
92
|
+
#
|
93
|
+
# struct_logical_type.each_child_type do |logical_type|
|
94
|
+
# puts "Struct child type: #{logical_type.type}"
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# If no block is given, an Enumerator is returned, which can be used to
|
98
|
+
# retrieve all child logical types.
|
99
|
+
#
|
100
|
+
# types = struct_logical_type.each_child_type.map(&:type)
|
101
|
+
# # => [:integer, :varchar]
|
102
|
+
def each_child_type
|
103
|
+
return to_enum(__method__) {child_count} unless block_given?
|
104
|
+
|
105
|
+
child_count.times do |i|
|
106
|
+
yield child_type_at(i)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -19,7 +19,7 @@ module DuckDB
|
|
19
19
|
# end
|
20
20
|
# result = pending_result.execute_pending
|
21
21
|
class PendingResult
|
22
|
-
STATES = %i[ready not_ready error no_tasks].freeze
|
22
|
+
STATES = %i[ready not_ready error no_tasks].freeze # :nodoc:
|
23
23
|
|
24
24
|
# returns the state of the pending result.
|
25
25
|
# the result can be :ready, :not_ready, :error, :no_tasks.
|
@@ -135,7 +135,7 @@ module DuckDB
|
|
135
135
|
# require 'duckdb'
|
136
136
|
# db = DuckDB::Database.open('duckdb_database')
|
137
137
|
# con = db.connect
|
138
|
-
# sql ='SELECT name FROM users WHERE
|
138
|
+
# sql ='SELECT name FROM users WHERE hugeint_col = ?'
|
139
139
|
# stmt = PreparedStatement.new(con, sql)
|
140
140
|
# stmt.bind_hugeint_internal(1, 1_234_567_890_123_456_789_012_345)
|
141
141
|
def bind_hugeint_internal(index, value)
|
@@ -143,6 +143,23 @@ module DuckDB
|
|
143
143
|
_bind_hugeint(index, lower, upper)
|
144
144
|
end
|
145
145
|
|
146
|
+
# binds i-th parameter with SQL prepared statement.
|
147
|
+
# The first argument is index of parameter.
|
148
|
+
# The index of first parameter is 1 not 0.
|
149
|
+
# The second argument value must be Integer value.
|
150
|
+
# This method uses duckdb_bind_uhugeint internally.
|
151
|
+
#
|
152
|
+
# require 'duckdb'
|
153
|
+
# db = DuckDB::Database.open('duckdb_database')
|
154
|
+
# con = db.connect
|
155
|
+
# sql ='SELECT name FROM users WHERE uhugeint_col = ?'
|
156
|
+
# stmt = PreparedStatement.new(con, sql)
|
157
|
+
# stmt.bind_uhugeint(1, (2**128) - 1)
|
158
|
+
def bind_uhugeint(index, value)
|
159
|
+
lower, upper = integer_to_hugeint(value)
|
160
|
+
_bind_uhugeint(index, lower, upper)
|
161
|
+
end
|
162
|
+
|
146
163
|
# binds i-th parameter with SQL prepared statement.
|
147
164
|
# The first argument is index of parameter.
|
148
165
|
# The index of first parameter is 1 not 0.
|
data/lib/duckdb/result.rb
CHANGED
@@ -27,39 +27,39 @@ module DuckDB
|
|
27
27
|
RETURN_TYPES = %i[invalid changed_rows nothing query_result].freeze
|
28
28
|
|
29
29
|
alias column_size column_count
|
30
|
-
|
30
|
+
|
31
|
+
@use_chunk_each = false
|
31
32
|
|
32
33
|
class << self
|
33
34
|
def new
|
34
35
|
raise DuckDB::Error, 'DuckDB::Result cannot be instantiated directly.'
|
35
36
|
end
|
36
37
|
|
37
|
-
|
38
|
-
raise('`changing DuckDB::Result.use_chunk_each to false` was deprecated.') unless value
|
39
|
-
|
40
|
-
warn('`DuckDB::Result.use_chunk_each=` will be deprecated.')
|
41
|
-
|
42
|
-
true
|
43
|
-
end
|
38
|
+
attr_writer :use_chunk_each
|
44
39
|
|
45
|
-
def use_chunk_each?
|
46
|
-
|
47
|
-
true
|
40
|
+
def use_chunk_each?
|
41
|
+
@use_chunk_each
|
48
42
|
end
|
49
43
|
end
|
50
44
|
|
51
45
|
def each(&)
|
52
|
-
if
|
53
|
-
return _chunk_stream unless block_given?
|
54
|
-
|
55
|
-
_chunk_stream(&)
|
56
|
-
else
|
46
|
+
if self.class.use_chunk_each?
|
57
47
|
return chunk_each unless block_given?
|
58
48
|
|
59
49
|
chunk_each(&)
|
50
|
+
else
|
51
|
+
return _chunk_stream unless block_given?
|
52
|
+
|
53
|
+
_chunk_stream(&)
|
60
54
|
end
|
61
55
|
end
|
62
56
|
|
57
|
+
# :nodoc:
|
58
|
+
def chunk_each(&)
|
59
|
+
warn 'DuckDB::Result#chunk_each will be deprecated.'
|
60
|
+
_chunk_each(&)
|
61
|
+
end
|
62
|
+
|
63
63
|
# returns return type. The return value is one of the following symbols:
|
64
64
|
# :invalid, :changed_rows, :nothing, :query_result
|
65
65
|
#
|
data/lib/duckdb/version.rb
CHANGED
data/lib/duckdb.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: duckdb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masaki Suketa
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-03-29 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: bigdecimal
|
@@ -91,10 +90,12 @@ extra_rdoc_files: []
|
|
91
90
|
files:
|
92
91
|
- ".gitattributes"
|
93
92
|
- ".github/FUNDING.yml"
|
93
|
+
- ".github/workflows/make_documents.yml"
|
94
94
|
- ".github/workflows/test_on_macos.yml"
|
95
95
|
- ".github/workflows/test_on_ubuntu.yml"
|
96
96
|
- ".github/workflows/test_on_windows.yml"
|
97
97
|
- ".gitignore"
|
98
|
+
- ".rdoc_options"
|
98
99
|
- CHANGELOG.md
|
99
100
|
- CONTRIBUTION.md
|
100
101
|
- Dockerfile
|
@@ -131,6 +132,8 @@ files:
|
|
131
132
|
- ext/duckdb/extconf.rb
|
132
133
|
- ext/duckdb/extracted_statements.c
|
133
134
|
- ext/duckdb/extracted_statements.h
|
135
|
+
- ext/duckdb/logical_type.c
|
136
|
+
- ext/duckdb/logical_type.h
|
134
137
|
- ext/duckdb/pending_result.c
|
135
138
|
- ext/duckdb/pending_result.h
|
136
139
|
- ext/duckdb/prepared_statement.c
|
@@ -153,6 +156,7 @@ files:
|
|
153
156
|
- lib/duckdb/infinity.rb
|
154
157
|
- lib/duckdb/interval.rb
|
155
158
|
- lib/duckdb/library_version.rb
|
159
|
+
- lib/duckdb/logical_type.rb
|
156
160
|
- lib/duckdb/pending_result.rb
|
157
161
|
- lib/duckdb/prepared_statement.rb
|
158
162
|
- lib/duckdb/result.rb
|
@@ -163,10 +167,10 @@ homepage: https://github.com/suketa/ruby-duckdb
|
|
163
167
|
licenses:
|
164
168
|
- MIT
|
165
169
|
metadata:
|
170
|
+
rubygems_mfa_required: 'true'
|
166
171
|
homepage_uri: https://github.com/suketa/ruby-duckdb
|
167
172
|
source_code_uri: https://github.com/suketa/ruby-duckdb
|
168
173
|
changelog_uri: https://github.com/suketa/ruby-duckdb/blob/master/CHANGELOG.md
|
169
|
-
post_install_message:
|
170
174
|
rdoc_options: []
|
171
175
|
require_paths:
|
172
176
|
- lib
|
@@ -181,8 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
181
185
|
- !ruby/object:Gem::Version
|
182
186
|
version: '0'
|
183
187
|
requirements: []
|
184
|
-
rubygems_version: 3.
|
185
|
-
signing_key:
|
188
|
+
rubygems_version: 3.6.2
|
186
189
|
specification_version: 4
|
187
190
|
summary: This module is Ruby binding for DuckDB database engine.
|
188
191
|
test_files: []
|