duckdb 1.5.2.0 → 1.5.2.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/duckdb.gemspec +37 -0
  4. data/ext/duckdb/aggregate_function.c +61 -100
  5. data/ext/duckdb/aggregate_function.h +2 -2
  6. data/ext/duckdb/appender.c +76 -35
  7. data/ext/duckdb/appender.h +1 -1
  8. data/ext/duckdb/client_context.c +5 -5
  9. data/ext/duckdb/client_context.h +2 -2
  10. data/ext/duckdb/column.c +13 -13
  11. data/ext/duckdb/column.h +1 -1
  12. data/ext/duckdb/connection.c +40 -41
  13. data/ext/duckdb/connection.h +2 -2
  14. data/ext/duckdb/converter.h +1 -7
  15. data/ext/duckdb/conveter.c +6 -6
  16. data/ext/duckdb/data_chunk.c +22 -22
  17. data/ext/duckdb/data_chunk.h +2 -2
  18. data/ext/duckdb/database.c +10 -10
  19. data/ext/duckdb/database.h +1 -1
  20. data/ext/duckdb/duckdb.c +17 -17
  21. data/ext/duckdb/expression.c +8 -8
  22. data/ext/duckdb/expression.h +1 -1
  23. data/ext/duckdb/extconf.rb +4 -3
  24. data/ext/duckdb/extracted_statements.c +15 -15
  25. data/ext/duckdb/extracted_statements.h +1 -1
  26. data/ext/duckdb/instance_cache.c +10 -10
  27. data/ext/duckdb/instance_cache.h +1 -1
  28. data/ext/duckdb/logical_type.c +94 -133
  29. data/ext/duckdb/logical_type.h +2 -2
  30. data/ext/duckdb/memory_helper.c +28 -28
  31. data/ext/duckdb/pending_result.c +27 -27
  32. data/ext/duckdb/pending_result.h +2 -2
  33. data/ext/duckdb/prepared_statement.c +103 -103
  34. data/ext/duckdb/prepared_statement.h +2 -2
  35. data/ext/duckdb/result.c +33 -33
  36. data/ext/duckdb/result.h +2 -3
  37. data/ext/duckdb/ruby-duckdb.h +4 -0
  38. data/ext/duckdb/scalar_function.c +3 -3
  39. data/ext/duckdb/table_description.c +1 -1
  40. data/ext/duckdb/table_function.c +3 -3
  41. data/ext/duckdb/table_function_bind_info.c +1 -1
  42. data/ext/duckdb/value.c +62 -50
  43. data/ext/duckdb/value.h +2 -2
  44. data/ext/duckdb/vector.c +20 -20
  45. data/ext/duckdb/vector.h +2 -2
  46. data/lib/duckdb/aggregate_function.rb +202 -3
  47. data/lib/duckdb/appender.rb +74 -0
  48. data/lib/duckdb/connection.rb +1 -16
  49. data/lib/duckdb/converter.rb +5 -0
  50. data/lib/duckdb/logical_type.rb +1 -3
  51. data/lib/duckdb/prepared_statement.rb +1 -1
  52. data/lib/duckdb/table_function.rb +0 -1
  53. data/lib/duckdb/value.rb +19 -0
  54. data/lib/duckdb/version.rb +1 -1
  55. metadata +2 -2
  56. data/lib/duckdb/duckdb_native.so +0 -0
@@ -93,6 +93,80 @@ module DuckDB
93
93
  raise_appender_error('failed to close')
94
94
  end
95
95
 
96
+ # :call-seq:
97
+ # appender.add_column(column_name) -> self
98
+ #
99
+ # Specifies a column to append to, allowing selective column insertion.
100
+ # Columns not added will use their default values or be computed from
101
+ # generated column expressions.
102
+ # Raises DuckDB::Error if the column does not exist in the table.
103
+ #
104
+ # require 'duckdb'
105
+ # db = DuckDB::Database.open
106
+ # con = db.connect
107
+ # con.query('CREATE TABLE t (id UUID PRIMARY KEY DEFAULT uuidv4(), name VARCHAR)')
108
+ # appender = con.appender('t')
109
+ # appender.add_column('name')
110
+ # appender
111
+ # .append_varchar('Alice')
112
+ # .end_row
113
+ # .flush
114
+ def add_column(column)
115
+ return self if _add_column(column)
116
+
117
+ raise_appender_error('failed to add_column')
118
+ end
119
+
120
+ # :call-seq:
121
+ # appender.clear_columns -> self
122
+ #
123
+ # Clears the list of columns previously set by #add_column, so that all
124
+ # columns of the table become active again. Any previously appended rows
125
+ # are flushed before the column list is reset; if the flush fails (e.g.
126
+ # a constraint violation), this method raises DuckDB::Error.
127
+ #
128
+ # require 'duckdb'
129
+ # db = DuckDB::Database.open
130
+ # con = db.connect
131
+ # con.query('CREATE TABLE t (id UUID PRIMARY KEY DEFAULT uuidv4(), name VARCHAR)')
132
+ # appender = con.appender('t')
133
+ # appender.add_column('name')
134
+ # appender
135
+ # .append_varchar('Alice')
136
+ # .end_row
137
+ # .flush
138
+ # appender.clear_columns
139
+ # # all table columns are active again
140
+ def clear_columns
141
+ return self if _clear_columns
142
+
143
+ raise_appender_error('failed to clear_columns')
144
+ end
145
+
146
+ if DuckDB::Appender.private_method_defined?(:_clear)
147
+ # :call-seq:
148
+ # appender.clear -> self
149
+ #
150
+ # Clears all unflushed data from the appender, discarding any appended rows
151
+ # that have not yet been flushed to the table.
152
+ #
153
+ # require 'duckdb'
154
+ # db = DuckDB::Database.open
155
+ # con = db.connect
156
+ # con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
157
+ # appender = con.appender('users')
158
+ # appender
159
+ # .append_int32(1)
160
+ # .append_varchar('Alice')
161
+ # .end_row
162
+ # .clear # discards the row above without flushing to the table
163
+ def clear
164
+ return self if _clear
165
+
166
+ raise_appender_error('failed to clear')
167
+ end
168
+ end
169
+
96
170
  # call-seq:
97
171
  # appender.append_bool(val) -> self
98
172
  #
@@ -34,7 +34,7 @@ module DuckDB
34
34
 
35
35
  def query_multi_sql(sql)
36
36
  stmts = ExtractedStatements.new(self, sql)
37
- return query_sql(sql) if stmts.size == 1
37
+ return _query_sql(sql) if stmts.size == 1
38
38
 
39
39
  result = nil
40
40
  stmts.each do |stmt|
@@ -276,7 +276,6 @@ module DuckDB
276
276
  def register_table_function(table_function)
277
277
  raise ArgumentError, 'table_function must be a TableFunction' unless table_function.is_a?(TableFunction)
278
278
 
279
- check_threads
280
279
  _register_table_function(table_function)
281
280
  end
282
281
 
@@ -291,12 +290,10 @@ module DuckDB
291
290
  # @param columns [Hash{String => DuckDB::LogicalType}, nil] optional column schema override;
292
291
  # if omitted, the adapter determines the columns (e.g. from headers or inference)
293
292
  # @raise [ArgumentError] if no adapter is registered for the object's class
294
- # @raise [DuckDB::Error] if threads setting is not 1
295
293
  # @return [void]
296
294
  #
297
295
  # @example Expose a CSV as a table
298
296
  # require 'csv'
299
- # con.execute('SET threads=1')
300
297
  # DuckDB::TableFunction.add_table_adapter(CSV, CSVTableAdapter.new)
301
298
  # csv = CSV.new(File.read('data.csv'), headers: true)
302
299
  # con.expose_as_table(csv, 'csv_table')
@@ -318,18 +315,6 @@ module DuckDB
318
315
 
319
316
  private
320
317
 
321
- def check_threads
322
- result = execute("SELECT current_setting('threads')")
323
- thread_count = result.first.first.to_i
324
-
325
- return unless thread_count > 1
326
-
327
- raise DuckDB::Error,
328
- 'Functions with Ruby callbacks require single-threaded execution. ' \
329
- "Current threads setting: #{thread_count}. " \
330
- "Execute 'SET threads=1' before registering functions."
331
- end
332
-
333
318
  def run_appender_block(appender, &)
334
319
  return appender unless block_given?
335
320
 
@@ -18,6 +18,7 @@ module DuckDB
18
18
  RANGE_UINT64 = 0..18_446_744_073_709_551_615
19
19
  RANGE_HUGEINT = (-(1 << 127)..((1 << 127) - 1))
20
20
  RANGE_UHUGEINT = (0..((1 << 128) - 1))
21
+ RANGE_DECIMAL_WIDTH = 1..38
21
22
 
22
23
  HALF_HUGEINT_BIT = 64
23
24
  HALF_HUGEINT = 1 << HALF_HUGEINT_BIT
@@ -122,6 +123,10 @@ module DuckDB
122
123
  value >> HALF_HUGEINT_BIT
123
124
  end
124
125
 
126
+ def _decimal_width(value)
127
+ value.to_s('F').gsub(/[^0-9]/, '').length
128
+ end
129
+
125
130
  def _to_decimal_from_hugeint(width, scale, upper, lower = nil)
126
131
  v = lower.nil? ? upper : _to_hugeint_from_vector(lower, upper)
127
132
  _to_decimal_from_value(width, scale, v)
@@ -2,8 +2,6 @@
2
2
 
3
3
  module DuckDB
4
4
  class LogicalType # rubocop:disable Metrics/ClassLength
5
- RANGE_DECIMAL_WIDTH = 1..38
6
-
7
5
  alias :alias get_alias
8
6
  alias :alias= set_alias
9
7
 
@@ -171,7 +169,7 @@ module DuckDB
171
169
  # decimal_type.width #=> 18
172
170
  # decimal_type.scale #=> 3
173
171
  def create_decimal(width, scale)
174
- raise DuckDB::Error, 'width must be between 1 and 38' unless RANGE_DECIMAL_WIDTH.cover?(width)
172
+ raise DuckDB::Error, 'width must be between 1 and 38' unless Converter::RANGE_DECIMAL_WIDTH.cover?(width)
175
173
  raise DuckDB::Error, "scale must be between 0 and width(#{width})" unless (0..width).cover?(scale)
176
174
 
177
175
  _create_decimal_type(width, scale)
@@ -281,7 +281,7 @@ module DuckDB
281
281
  def bind_decimal(index, value)
282
282
  decimal = _parse_deciaml(value)
283
283
  lower, upper = decimal_to_hugeint(decimal)
284
- width = decimal.to_s('F').gsub(/[^0-9]/, '').length
284
+ width = _decimal_width(decimal)
285
285
  _bind_decimal(index, lower, upper, width, decimal.scale)
286
286
  end
287
287
 
@@ -163,7 +163,6 @@ module DuckDB
163
163
  #
164
164
  # # Register and use:
165
165
  # DuckDB::TableFunction.add_table_adapter(CSV, CSVTableAdapter.new)
166
- # con.execute('SET threads=1')
167
166
  # con.expose_as_table(csv, 'csv_table')
168
167
  # con.query('SELECT * FROM csv_table()').to_a
169
168
  #
data/lib/duckdb/value.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'bigdecimal'
4
+
3
5
  module DuckDB
4
6
  class Value
5
7
  class << self
@@ -219,6 +221,23 @@ module DuckDB
219
221
  _create_uhugeint(lower, upper)
220
222
  end
221
223
 
224
+ # Creates a DuckDB::Value of DECIMAL type.
225
+ #
226
+ # value = DuckDB::Value.create_decimal(BigDecimal('12345.678'))
227
+ #
228
+ # @param value [BigDecimal] the decimal value.
229
+ # @return [DuckDB::Value] the created Value object.
230
+ # @raise [ArgumentError] if +value+ is not a BigDecimal or its width is out of range (1..38).
231
+ def create_decimal(value)
232
+ check_type!(value, BigDecimal)
233
+
234
+ width = _decimal_width(value)
235
+ check_range!(width, RANGE_DECIMAL_WIDTH, 'DECIMAL width')
236
+
237
+ lower, upper = decimal_to_hugeint(value)
238
+ _create_decimal(lower, upper, width, value.scale)
239
+ end
240
+
222
241
  private
223
242
 
224
243
  def check_range!(value, range, type_name)
@@ -3,5 +3,5 @@
3
3
  module DuckDB
4
4
  # The version string of ruby-duckdb.
5
5
  # Currently, ruby-duckdb is NOT semantic versioning.
6
- VERSION = '1.5.2.0'
6
+ VERSION = '1.5.2.1'
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duckdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.2.0
4
+ version: 1.5.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masaki Suketa
@@ -40,6 +40,7 @@ files:
40
40
  - Rakefile
41
41
  - bin/console
42
42
  - bin/setup
43
+ - duckdb.gemspec
43
44
  - ext/duckdb/aggregate_function.c
44
45
  - ext/duckdb/aggregate_function.h
45
46
  - ext/duckdb/appender.c
@@ -120,7 +121,6 @@ files:
120
121
  - lib/duckdb/converter/int_to_sym.rb
121
122
  - lib/duckdb/data_chunk.rb
122
123
  - lib/duckdb/database.rb
123
- - lib/duckdb/duckdb_native.so
124
124
  - lib/duckdb/expression.rb
125
125
  - lib/duckdb/extracted_statements.rb
126
126
  - lib/duckdb/function_type_validation.rb
Binary file