duckdb 1.0.0.2 → 1.1.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.
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DuckDB
4
+ module Converter
5
+ module IntToSym
6
+ STATEMENT_TYPES = %i[
7
+ invalid
8
+ select
9
+ insert
10
+ update
11
+ explain
12
+ delete
13
+ prepare
14
+ create
15
+ execute
16
+ alter
17
+ transaction
18
+ copy
19
+ analyze
20
+ variable_set
21
+ create_func
22
+ drop
23
+ export
24
+ pragma
25
+ vacuum
26
+ call
27
+ set
28
+ load
29
+ relation
30
+ extension
31
+ logical_plan
32
+ attach
33
+ detach
34
+ multi
35
+ ].freeze
36
+
37
+ HASH_TYPES = if Gem::Version.new(DuckDB::LIBRARY_VERSION) == Gem::Version.new('0.10.0')
38
+ {
39
+ 0 => :invalid,
40
+ 1 => :boolean,
41
+ 2 => :tinyint,
42
+ 3 => :smallint,
43
+ 4 => :integer,
44
+ 5 => :bigint,
45
+ 6 => :utinyint,
46
+ 7 => :usmallint,
47
+ 8 => :uinteger,
48
+ 9 => :ubigint,
49
+ 10 => :float,
50
+ 11 => :double,
51
+ 12 => :timestamp,
52
+ 13 => :date,
53
+ 14 => :time,
54
+ 15 => :interval,
55
+ 16 => :hugeint,
56
+ 17 => :uhugeint,
57
+ 18 => :varchar,
58
+ 19 => :blob,
59
+ 20 => :decimal,
60
+ 21 => :timestamp_s,
61
+ 22 => :timestamp_ms,
62
+ 23 => :timestamp_ns,
63
+ 24 => :enum,
64
+ 25 => :list,
65
+ 26 => :struct,
66
+ 27 => :map,
67
+ 28 => :uuid,
68
+ 29 => :union,
69
+ 30 => :bit,
70
+ 31 => :time_tz,
71
+ 32 => :timestamp_tz
72
+ }.freeze
73
+ else
74
+ {
75
+ 0 => :invalid,
76
+ 1 => :boolean,
77
+ 2 => :tinyint,
78
+ 3 => :smallint,
79
+ 4 => :integer,
80
+ 5 => :bigint,
81
+ 6 => :utinyint,
82
+ 7 => :usmallint,
83
+ 8 => :uinteger,
84
+ 9 => :ubigint,
85
+ 10 => :float,
86
+ 11 => :double,
87
+ 12 => :timestamp,
88
+ 13 => :date,
89
+ 14 => :time,
90
+ 15 => :interval,
91
+ 16 => :hugeint,
92
+ 32 => :uhugeint,
93
+ 17 => :varchar,
94
+ 18 => :blob,
95
+ 19 => :decimal,
96
+ 20 => :timestamp_s,
97
+ 21 => :timestamp_ms,
98
+ 22 => :timestamp_ns,
99
+ 23 => :enum,
100
+ 24 => :list,
101
+ 25 => :struct,
102
+ 26 => :map,
103
+ 33 => :array,
104
+ 27 => :uuid,
105
+ 28 => :union,
106
+ 29 => :bit,
107
+ 30 => :time_tz,
108
+ 31 => :timestamp_tz
109
+ }.freeze
110
+ end
111
+
112
+ module_function
113
+
114
+ def statement_type_to_sym(val)
115
+ raise DuckDB::Error, "Unknown statement type: #{val}" if val >= STATEMENT_TYPES.size
116
+
117
+ STATEMENT_TYPES[val]
118
+ end
119
+
120
+ def type_to_sym(val)
121
+ raise DuckDB::Error, "Unknown type: #{val}" unless HASH_TYPES.key?(val)
122
+
123
+ HASH_TYPES[val]
124
+ end
125
+ end
126
+ end
127
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'date'
4
4
  require_relative 'interval'
5
+ require_relative 'converter/int_to_sym'
5
6
 
6
7
  module DuckDB
7
8
  QueryProgress = Struct.new(:percentage, :rows_processed, :total_rows_to_process)
@@ -15,6 +16,14 @@ module DuckDB
15
16
 
16
17
  module_function
17
18
 
19
+ def _to_infinity(value)
20
+ if value.positive?
21
+ DuckDB::Infinity::POSITIVE
22
+ else
23
+ DuckDB::Infinity::NEGATIVE
24
+ end
25
+ end
26
+
18
27
  def _to_date(year, month, day)
19
28
  Date.new(year, month, day)
20
29
  end
@@ -23,7 +23,7 @@ module DuckDB
23
23
  #
24
24
  class Database
25
25
  private_class_method :_open
26
- private_class_method :_open_ext if defined?(DuckDB::Config)
26
+ private_class_method :_open_ext
27
27
 
28
28
  class << self
29
29
  ##
@@ -55,10 +55,8 @@ module DuckDB
55
55
  private
56
56
 
57
57
  def _db_open(dbpath, config)
58
- if defined?(DuckDB::Config) && config
58
+ if config
59
59
  _open_ext(dbpath, config)
60
- elsif config
61
- _open(dbpath, config)
62
60
  else
63
61
  _open(dbpath)
64
62
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DuckDB
4
+ module Infinity
5
+ POSITIVE = 'infinity'
6
+ NEGATIVE = '-infinity'
7
+ end
8
+ end
@@ -8,8 +8,6 @@ module DuckDB
8
8
  #
9
9
  # require 'duckdb'
10
10
  #
11
- # DuckDB::Result.use_chunk_each = true
12
- #
13
11
  # db = DuckDB::Database.open
14
12
  # con = db.connect
15
13
  # stmt = con.prepared_statement(VERY_SLOW_QUERY)
@@ -24,8 +22,7 @@ module DuckDB
24
22
  STATES = %i[ready not_ready error no_tasks].freeze
25
23
 
26
24
  # returns the state of the pending result.
27
- # The result can be :ready, :not_ready, :error, :no_tasks.
28
- # (:no_tasks is available only with duckdb 0.9.0 or later.)
25
+ # the result can be :ready, :not_ready, :error, :no_tasks.
29
26
  #
30
27
  # :ready means the result is ready to be fetched, and
31
28
  # you can call `execute_pending` to get the result.
@@ -33,9 +30,23 @@ module DuckDB
33
30
  # :not_ready means the result is not ready yet, so
34
31
  # you need to call `execute_task`.
35
32
  #
36
- # @return [Symbol] :ready, :not_ready, :error, :no_tasks
33
+ # @return [symbol] :ready, :not_ready, :error, :no_tasks
37
34
  def state
38
35
  STATES[_state]
39
36
  end
37
+
38
+ # returns the state of the pending result.
39
+ # the result can be :ready, :not_ready, :error, :no_tasks.
40
+ #
41
+ # :ready means the result is ready to be fetched, and
42
+ # you can call `execute_pending` to get the result.
43
+ #
44
+ # :not_ready or :no_tasks might mean the pending result
45
+ # is not executed yet, so you need to call `execute_task`.
46
+ #
47
+ # @return [symbol] :ready, :not_ready, :error, :no_tasks
48
+ def execute_check_state
49
+ STATES[_execute_check_state]
50
+ end
40
51
  end
41
52
  end
@@ -27,11 +27,38 @@ module DuckDB
27
27
  end
28
28
 
29
29
  def pending_prepared_stream
30
- raise DuckDB::Error, 'DuckDB::Result.use_chunk_each must be true.' unless DuckDB::Result.use_chunk_each?
31
-
32
30
  PendingResult.new(self, true)
33
31
  end
34
32
 
33
+ # returns statement type. The return value is one of the following symbols:
34
+ # :invalid, :select, :insert, :update, :explain, :delete, :prepare, :create,
35
+ # :execute, :alter, :transaction, :copy, :analyze, :variable_set, :create_func,
36
+ # :drop, :export, :pragma, :vacuum, :call, :set, :load, :relation, :extension,
37
+ # :logical_plan, :attach, :detach, :multi
38
+ #
39
+ # require 'duckdb'
40
+ # db = DuckDB::Database.open('duckdb_database')
41
+ # con = db.connect
42
+ # stmt = con.prepared_statement('SELECT * FROM users')
43
+ # stmt.statement_type # => :select
44
+ def statement_type
45
+ i = _statement_type
46
+ Converter::IntToSym.statement_type_to_sym(i)
47
+ end
48
+
49
+ # returns parameter type. The argument must be index of parameter.
50
+ #
51
+ # require 'duckdb'
52
+ # db = DuckDB::Database.open
53
+ # con = db.connect
54
+ # con.execute('CREATE TABLE users (id INTEGER, name VARCHAR(255))')
55
+ # stmt = con.prepared_statement('SELECT * FROM users WHERE id = ?')
56
+ # stmt.param_type(1) # => :integer
57
+ def param_type(index)
58
+ i = _param_type(index)
59
+ Converter::IntToSym.type_to_sym(i)
60
+ end
61
+
35
62
  # binds all parameters with SQL prepared statement.
36
63
  #
37
64
  # require 'duckdb'
data/lib/duckdb/result.rb CHANGED
@@ -24,86 +24,71 @@ module DuckDB
24
24
  # end
25
25
  class Result
26
26
  include Enumerable
27
- TO_METHODS = if Gem::Version.new(DuckDB::LIBRARY_VERSION) == Gem::Version.new('0.10.0')
28
- Hash.new(:_to_string).merge(
29
- 1 => :_to_boolean,
30
- 3 => :_to_smallint,
31
- 4 => :_to_integer,
32
- 5 => :_to_bigint,
33
- 10 => :_to_float,
34
- 11 => :_to_double,
35
- 16 => :_to_hugeint_internal,
36
- 19 => :_to_blob,
37
- 20 => :_to_decimal_internal
38
- ).freeze
39
- else
40
- Hash.new(:_to_string).merge(
41
- 1 => :_to_boolean,
42
- 3 => :_to_smallint,
43
- 4 => :_to_integer,
44
- 5 => :_to_bigint,
45
- 10 => :_to_float,
46
- 11 => :_to_double,
47
- 16 => :_to_hugeint_internal,
48
- 18 => :_to_blob,
49
- 19 => :_to_decimal_internal
50
- ).freeze
51
- end
27
+ RETURN_TYPES = %i[invalid changed_rows nothing query_result].freeze
52
28
 
53
29
  alias column_size column_count
54
30
  alias row_size row_count
55
31
 
56
- @use_chunk_each = true
57
-
58
32
  class << self
59
33
  def new
60
34
  raise DuckDB::Error, 'DuckDB::Result cannot be instantiated directly.'
61
35
  end
62
36
 
63
37
  def use_chunk_each=(value)
64
- warn('`changing DuckDB::Result.use_chunk_each to false` will be deprecated.') if value == false
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.')
65
41
 
66
- @use_chunk_each = value
42
+ true
67
43
  end
68
44
 
69
45
  def use_chunk_each?
70
- !!@use_chunk_each
46
+ warn('`DuckDB::Result.use_chunk_each?` will be deprecated.')
47
+ true
71
48
  end
72
49
  end
73
50
 
74
51
  def each
75
- if self.class.use_chunk_each?
76
- if streaming?
77
- return _chunk_stream unless block_given?
52
+ if streaming?
53
+ return _chunk_stream unless block_given?
78
54
 
79
- _chunk_stream { |row| yield row }
80
- else
81
- return chunk_each unless block_given?
82
-
83
- chunk_each { |row| yield row }
84
- end
55
+ _chunk_stream { |row| yield row }
85
56
  else
86
- warn('this `each` behavior will be deprecated in the future. set `DuckDB::Result.use_chunk_each = true` to use new `each` behavior.')
87
- return to_enum { row_size } unless block_given?
57
+ return chunk_each unless block_given?
88
58
 
89
- row_count.times do |row_index|
90
- yield row(row_index)
91
- end
59
+ chunk_each { |row| yield row }
92
60
  end
93
61
  end
94
62
 
95
- def row(row_index)
96
- warn("#{self.class}##{__method__} will be deprecated. set `DuckDB::Result.use_chunk_each = true`.")
97
- row = []
98
- column_count.times do |col_index|
99
- row << (_null?(row_index, col_index) ? nil : to_value(row_index, col_index))
100
- end
101
- row
63
+ # returns return type. The return value is one of the following symbols:
64
+ # :invalid, :changed_rows, :nothing, :query_result
65
+ #
66
+ # require 'duckdb'
67
+ # db = DuckDB::Database.open('duckdb_database')
68
+ # con = db.connect
69
+ # result = con.execute('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
70
+ # result.return_type # => :nothing
71
+ def return_type
72
+ i = _return_type
73
+ raise DuckDB::Error, "Unknown return type: #{i}" if i >= RETURN_TYPES.size
74
+
75
+ RETURN_TYPES[i]
102
76
  end
103
77
 
104
- def to_value(row_index, col_index)
105
- warn("#{self.class}##{__method__} will be deprecated. set `DuckDB::Result.use_chunk_each = true`.")
106
- send(TO_METHODS[_column_type(col_index)], row_index, col_index)
78
+ # returns statement type. The return value is one of the following symbols:
79
+ # :invalid, :select, :insert, :update, :explain, :delete, :prepare, :create,
80
+ # :execute, :alter, :transaction, :copy, :analyze, :variable_set, :create_func,
81
+ # :drop, :export, :pragma, :vacuum, :call, :set, :load, :relation, :extension,
82
+ # :logical_plan, :attach, :detach, :multi
83
+ #
84
+ # require 'duckdb'
85
+ # db = DuckDB::Database.open('duckdb_database')
86
+ # con = db.connect
87
+ # result = con.execute('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
88
+ # result.statement_type # => :create
89
+ def statement_type
90
+ i = _statement_type
91
+ Converter::IntToSym.statement_type_to_sym(i)
107
92
  end
108
93
 
109
94
  def enum_dictionary_values(col_index)
@@ -113,29 +98,5 @@ module DuckDB
113
98
  end
114
99
  values
115
100
  end
116
-
117
- private
118
-
119
- def _to_hugeint(row, col)
120
- warn("#{self.class}##{__method__} will be deprecated.")
121
- _to_string(row, col).to_i
122
- end
123
-
124
- def _to_hugeint_internal(row, col)
125
- warn("#{self.class}##{__method__} will be deprecated.")
126
- lower, upper = __to_hugeint_internal(row, col)
127
- Converter._to_hugeint_from_vector(lower, upper)
128
- end
129
-
130
- def _to_decimal(row, col)
131
- warn("#{self.class}##{__method__} will be deprecated.")
132
- BigDecimal(_to_string(row, col))
133
- end
134
-
135
- def _to_decimal_internal(row, col)
136
- warn("#{self.class}##{__method__} will be deprecated.")
137
- lower, upper, width, scale = __to_decimal_internal(row, col)
138
- Converter._to_decimal_from_hugeint(width, scale, upper, lower)
139
- end
140
101
  end
141
102
  end
@@ -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.0.0.2'
6
+ VERSION = '1.1.0.1'
7
7
  end
data/lib/duckdb.rb CHANGED
@@ -12,6 +12,7 @@ require 'duckdb/pending_result'
12
12
  require 'duckdb/appender'
13
13
  require 'duckdb/config'
14
14
  require 'duckdb/column'
15
+ require 'duckdb/infinity'
15
16
 
16
17
  # DuckDB provides Ruby interface of DuckDB.
17
18
  module DuckDB
@@ -1,6 +1,5 @@
1
1
  require 'duckdb'
2
2
 
3
- DuckDB::Result.use_chunk_each = true
4
3
  DuckDB::Database.open do |db|
5
4
  db.connect do |con|
6
5
  con.query('SET threads=1')
@@ -1,6 +1,5 @@
1
1
  require 'duckdb'
2
2
 
3
- DuckDB::Result.use_chunk_each = true
4
3
  DuckDB::Database.open do |db|
5
4
  db.connect do |con|
6
5
  con.query('SET threads=1')
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.0.0.2
4
+ version: 1.1.0.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-06-23 00:00:00.000000000 Z
11
+ date: 2024-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bigdecimal
@@ -106,9 +106,6 @@ files:
106
106
  - benchmark/async_query.rb
107
107
  - benchmark/converter_hugeint_ips.rb
108
108
  - benchmark/get_converter_module_ips.rb
109
- - benchmark/to_bigdecimal_ips.rb
110
- - benchmark/to_hugeint_ips.rb
111
- - benchmark/to_hugeint_profile.rb
112
109
  - benchmark/to_intern_ips.rb
113
110
  - bin/console
114
111
  - bin/setup
@@ -150,7 +147,9 @@ files:
150
147
  - lib/duckdb/config.rb
151
148
  - lib/duckdb/connection.rb
152
149
  - lib/duckdb/converter.rb
150
+ - lib/duckdb/converter/int_to_sym.rb
153
151
  - lib/duckdb/database.rb
152
+ - lib/duckdb/infinity.rb
154
153
  - lib/duckdb/interval.rb
155
154
  - lib/duckdb/library_version.rb
156
155
  - lib/duckdb/pending_result.rb
@@ -174,14 +173,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
174
173
  requirements:
175
174
  - - ">="
176
175
  - !ruby/object:Gem::Version
177
- version: 3.0.0
176
+ version: 3.1.0
178
177
  required_rubygems_version: !ruby/object:Gem::Requirement
179
178
  requirements:
180
179
  - - ">="
181
180
  - !ruby/object:Gem::Version
182
181
  version: '0'
183
182
  requirements: []
184
- rubygems_version: 3.5.11
183
+ rubygems_version: 3.5.16
185
184
  signing_key:
186
185
  specification_version: 4
187
186
  summary: This module is Ruby binding for DuckDB database engine.
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'duckdb'
5
- require 'benchmark/ips'
6
-
7
- db = DuckDB::Database.open
8
- con = db.connect
9
- con.query('CREATE TABLE decimals (decimal_value DECIMAL(38, 3))')
10
- con.query('INSERT INTO decimals VALUES (1234567890123.456)')
11
- result = con.query('SELECT decimal_value FROM decimals')
12
-
13
- Benchmark.ips do |x|
14
- x.report('_to_decimal') { result.send(:_to_decimal, 0, 0) }
15
- x.report('_to_decimal_internal') { result.send(:_to_decimal_internal, 0, 0) }
16
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'duckdb'
5
- require 'benchmark/ips'
6
-
7
- db = DuckDB::Database.open
8
- con = db.connect
9
- con.query('CREATE TABLE hugeints (hugeint_value HUGEINT)')
10
- con.query('INSERT INTO hugeints VALUES (123456789012345678901234567890123456789)')
11
- result = con.query('SELECT hugeint_value FROM hugeints')
12
-
13
- Benchmark.ips do |x|
14
- x.report('_to_hugeint') { result.send(:_to_hugeint, 0, 0) }
15
- x.report('_to_hugeint_internal') { result.send(:_to_hugeint_internal, 0, 0) }
16
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'duckdb'
5
- require 'stackprof'
6
-
7
- db = DuckDB::Database.open
8
- con = db.connect
9
- con.query('CREATE TABLE hugeints (hugeint_value HUGEINT)')
10
- con.query('INSERT INTO hugeints VALUES (123456789012345678901234567890123456789)')
11
- result = con.query('SELECT hugeint_value FROM hugeints')
12
-
13
- def profile(name, &block)
14
- profile = StackProf.run(mode: :wall, interval: 1_000) do
15
- 2_000_000.times(&block)
16
- end
17
-
18
- result = StackProf::Report.new(profile)
19
- puts
20
- puts "=== #{name} ==="
21
- result.print_text
22
- puts
23
- end
24
-
25
- profile(:_to_hugeint) { result.send(:_to_hugeint, 0, 0) }
26
- profile(:_to_hugeint_internal) { result.send(:_to_hugeint_internal, 0, 0) }