duckdb 1.0.0.2 → 1.1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.0'
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.0
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-15 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) }