duckdb 1.0.0.1 → 1.1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test_on_macos.yml +15 -3
- data/.github/workflows/test_on_ubuntu.yml +15 -3
- data/.github/workflows/test_on_windows.yml +2 -2
- data/CHANGELOG.md +64 -1
- data/Dockerfile +2 -2
- data/Gemfile.lock +6 -6
- data/README.md +0 -3
- data/benchmark/async_query.rb +0 -2
- data/benchmark/to_intern_ips.rb +0 -1
- data/duckdb.gemspec +1 -1
- data/ext/duckdb/duckdb.c +4 -0
- data/ext/duckdb/extconf.rb +6 -7
- data/ext/duckdb/pending_result.c +7 -0
- data/ext/duckdb/prepared_statement.c +35 -9
- data/ext/duckdb/result.c +246 -411
- data/ext/duckdb/ruby-duckdb.h +6 -0
- data/lib/duckdb/column.rb +2 -38
- data/lib/duckdb/config.rb +47 -49
- data/lib/duckdb/connection.rb +0 -1
- data/lib/duckdb/converter/int_to_sym.rb +127 -0
- data/lib/duckdb/converter.rb +68 -0
- data/lib/duckdb/database.rb +2 -4
- data/lib/duckdb/infinity.rb +8 -0
- data/lib/duckdb/pending_result.rb +16 -5
- data/lib/duckdb/prepared_statement.rb +29 -2
- data/lib/duckdb/result.rb +39 -78
- data/lib/duckdb/version.rb +1 -1
- data/lib/duckdb.rb +1 -0
- data/sample/async_query.rb +0 -1
- data/sample/async_query_stream.rb +0 -1
- metadata +6 -7
- data/benchmark/to_bigdecimal_ips.rb +0 -16
- data/benchmark/to_hugeint_ips.rb +0 -16
- data/benchmark/to_hugeint_profile.rb +0 -26
data/ext/duckdb/ruby-duckdb.h
CHANGED
@@ -15,6 +15,10 @@
|
|
15
15
|
#define HAVE_DUCKDB_H_GE_V1_0_0 1
|
16
16
|
#endif
|
17
17
|
|
18
|
+
#ifdef HAVE_DUCKDB_RESULT_ERROR_TYPE
|
19
|
+
#define HAVE_DUCKDB_H_GE_V1_1_0 1
|
20
|
+
#endif
|
21
|
+
|
18
22
|
#include "./error.h"
|
19
23
|
#include "./database.h"
|
20
24
|
#include "./connection.h"
|
@@ -38,5 +42,7 @@ extern VALUE cDuckDBConfig;
|
|
38
42
|
extern VALUE eDuckDBError;
|
39
43
|
extern VALUE mDuckDBConverter;
|
40
44
|
extern VALUE cDuckDBPreparedStatement;
|
45
|
+
extern VALUE PositiveInfinity;
|
46
|
+
extern VALUE NegativeInfinity;
|
41
47
|
|
42
48
|
#endif
|
data/lib/duckdb/column.rb
CHANGED
@@ -17,44 +17,8 @@ module DuckDB
|
|
17
17
|
# columns.first.type #=> :integer
|
18
18
|
#
|
19
19
|
def type
|
20
|
-
|
21
|
-
|
22
|
-
boolean
|
23
|
-
tinyint
|
24
|
-
smallint
|
25
|
-
integer
|
26
|
-
bigint
|
27
|
-
utinyint
|
28
|
-
usmallint
|
29
|
-
uinteger
|
30
|
-
ubigint
|
31
|
-
float
|
32
|
-
double
|
33
|
-
timestamp
|
34
|
-
date
|
35
|
-
time
|
36
|
-
interval
|
37
|
-
hugeint
|
38
|
-
varchar
|
39
|
-
blob
|
40
|
-
decimal
|
41
|
-
timestamp_s
|
42
|
-
timestamp_ms
|
43
|
-
timestamp_ns
|
44
|
-
enum
|
45
|
-
list
|
46
|
-
struct
|
47
|
-
map
|
48
|
-
uuid
|
49
|
-
json
|
50
|
-
]
|
51
|
-
if Gem::Version.new(DuckDB::LIBRARY_VERSION) == Gem::Version.new('0.10.0')
|
52
|
-
types[17, 0] = :uhugeint
|
53
|
-
end
|
54
|
-
index = _type
|
55
|
-
return :unknown if index >= types.size
|
56
|
-
|
57
|
-
types[index]
|
20
|
+
type_id = _type
|
21
|
+
DuckDB::Converter::IntToSym.type_to_sym(type_id)
|
58
22
|
end
|
59
23
|
end
|
60
24
|
end
|
data/lib/duckdb/config.rb
CHANGED
@@ -1,64 +1,62 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module DuckDB
|
4
|
-
|
5
|
-
|
4
|
+
# The DuckDB::Config encapsulates DuckDB Configuration.
|
5
|
+
#
|
6
|
+
# require 'duckdb'
|
7
|
+
# config = DuckDB::Config.new
|
8
|
+
# config['default_order'] = 'DESC'
|
9
|
+
# db = DuckDB::Database.open(nil, config)
|
10
|
+
# con = db.connect
|
11
|
+
# con.query('CREATE TABLE numbers (number INTEGER)')
|
12
|
+
# con.query('INSERT INTO numbers VALUES (2), (1), (4), (3)')
|
13
|
+
#
|
14
|
+
# # number is ordered by descending.
|
15
|
+
# r = con.query('SELECT number FROM numbers ORDER BY number)
|
16
|
+
# r.first.first # => 4
|
17
|
+
class Config
|
18
|
+
class << self
|
19
|
+
#
|
20
|
+
# returns available configuration name and the description.
|
21
|
+
# The return value is array object. The first element is the configuration
|
22
|
+
# name. The second is the description.
|
23
|
+
#
|
24
|
+
# key, desc = DuckDB::Config.key_description(0)
|
25
|
+
# key # => "access_mode"
|
26
|
+
# desc # => "Access mode of the database ([AUTOMATIC], READ_ONLY or READ_WRITE)"
|
27
|
+
#
|
28
|
+
alias key_description get_config_flag
|
29
|
+
|
30
|
+
#
|
31
|
+
# returns the Hash object of all available configuration names and
|
32
|
+
# the descriptions.
|
33
|
+
#
|
34
|
+
# configs = DuckDB::Config.key_descriptions
|
35
|
+
# configs['default_order'] # => "The order type used when none is specified ([ASC] or DESC)"
|
36
|
+
#
|
37
|
+
def key_descriptions
|
38
|
+
@key_descriptions ||= (0...size).each_with_object({}) do |i, hash|
|
39
|
+
key, description = key_description(i)
|
40
|
+
hash[key] = description
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# set configuration value
|
6
47
|
#
|
7
|
-
# require 'duckdb'
|
8
48
|
# config = DuckDB::Config.new
|
49
|
+
# # config.set_config('default_order', 'DESC')
|
9
50
|
# config['default_order'] = 'DESC'
|
51
|
+
#
|
10
52
|
# db = DuckDB::Database.open(nil, config)
|
11
53
|
# con = db.connect
|
12
54
|
# con.query('CREATE TABLE numbers (number INTEGER)')
|
13
55
|
# con.query('INSERT INTO numbers VALUES (2), (1), (4), (3)')
|
14
56
|
#
|
15
|
-
# #
|
57
|
+
# # numbers are ordered by descending.
|
16
58
|
# r = con.query('SELECT number FROM numbers ORDER BY number)
|
17
59
|
# r.first.first # => 4
|
18
|
-
|
19
|
-
class << self
|
20
|
-
#
|
21
|
-
# returns available configuration name and the description.
|
22
|
-
# The return value is array object. The first element is the configuration
|
23
|
-
# name. The second is the description.
|
24
|
-
#
|
25
|
-
# key, desc = DuckDB::Config.key_description(0)
|
26
|
-
# key # => "access_mode"
|
27
|
-
# desc # => "Access mode of the database ([AUTOMATIC], READ_ONLY or READ_WRITE)"
|
28
|
-
#
|
29
|
-
alias key_description get_config_flag
|
30
|
-
|
31
|
-
#
|
32
|
-
# returns the Hash object of all available configuration names and
|
33
|
-
# the descriptions.
|
34
|
-
#
|
35
|
-
# configs = DuckDB::Config.key_descriptions
|
36
|
-
# configs['default_order'] # => "The order type used when none is specified ([ASC] or DESC)"
|
37
|
-
#
|
38
|
-
def key_descriptions
|
39
|
-
@key_descriptions ||= (0...size).each_with_object({}) do |i, hash|
|
40
|
-
key, description = key_description(i)
|
41
|
-
hash[key] = description
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
#
|
47
|
-
# set configuration value
|
48
|
-
#
|
49
|
-
# config = DuckDB::Config.new
|
50
|
-
# # config.set_config('default_order', 'DESC')
|
51
|
-
# config['default_order'] = 'DESC'
|
52
|
-
#
|
53
|
-
# db = DuckDB::Database.open(nil, config)
|
54
|
-
# con = db.connect
|
55
|
-
# con.query('CREATE TABLE numbers (number INTEGER)')
|
56
|
-
# con.query('INSERT INTO numbers VALUES (2), (1), (4), (3)')
|
57
|
-
#
|
58
|
-
# # numbers are ordered by descending.
|
59
|
-
# r = con.query('SELECT number FROM numbers ORDER BY number)
|
60
|
-
# r.first.first # => 4
|
61
|
-
alias []= set_config
|
62
|
-
end
|
60
|
+
alias []= set_config
|
63
61
|
end
|
64
62
|
end
|
data/lib/duckdb/connection.rb
CHANGED
@@ -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
|
data/lib/duckdb/converter.rb
CHANGED
@@ -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)
|
@@ -10,9 +11,19 @@ module DuckDB
|
|
10
11
|
HALF_HUGEINT_BIT = 64
|
11
12
|
HALF_HUGEINT = 1 << HALF_HUGEINT_BIT
|
12
13
|
FLIP_HUGEINT = 1 << 63
|
14
|
+
EPOCH = Time.local(1970, 1, 1)
|
15
|
+
EPOCH_UTC = Time.new(1970, 1, 1, 0, 0, 0, 0)
|
13
16
|
|
14
17
|
module_function
|
15
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
|
+
|
16
27
|
def _to_date(year, month, day)
|
17
28
|
Date.new(year, month, day)
|
18
29
|
end
|
@@ -33,6 +44,63 @@ module DuckDB
|
|
33
44
|
)
|
34
45
|
end
|
35
46
|
|
47
|
+
def _to_time_from_duckdb_timestamp_s(time)
|
48
|
+
EPOCH + time
|
49
|
+
end
|
50
|
+
|
51
|
+
def _to_time_from_duckdb_timestamp_ms(time)
|
52
|
+
tm = EPOCH + (time / 1000)
|
53
|
+
Time.local(tm.year, tm.month, tm.day, tm.hour, tm.min, tm.sec, time % 1000 * 1000)
|
54
|
+
end
|
55
|
+
|
56
|
+
def _to_time_from_duckdb_timestamp_ns(time)
|
57
|
+
tm = EPOCH + (time / 1_000_000_000)
|
58
|
+
Time.local(tm.year, tm.month, tm.day, tm.hour, tm.min, tm.sec, time % 1_000_000_000 / 1000)
|
59
|
+
end
|
60
|
+
|
61
|
+
def _to_time_from_duckdb_time_tz(hour, min, sec, micro, timezone)
|
62
|
+
sign = '+'
|
63
|
+
if timezone.negative?
|
64
|
+
timezone = -timezone
|
65
|
+
sign = '-'
|
66
|
+
end
|
67
|
+
|
68
|
+
tzhour = timezone / 3600
|
69
|
+
tzmin = (timezone % 3600) / 60
|
70
|
+
|
71
|
+
Time.parse(
|
72
|
+
format(
|
73
|
+
'%<hour>02d:%<min>02d:%<sec>02d.%<micro>06d%<sign>s%<tzhour>02d:%<tzmin>02d',
|
74
|
+
hour: hour,
|
75
|
+
min: min,
|
76
|
+
sec: sec,
|
77
|
+
micro: micro,
|
78
|
+
sign: sign,
|
79
|
+
tzhour: tzhour,
|
80
|
+
tzmin: tzmin
|
81
|
+
)
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
def _to_time_from_duckdb_timestamp_tz(bits)
|
86
|
+
micro = bits % 1_000_000
|
87
|
+
sec = (bits / 1_000_000)
|
88
|
+
time = EPOCH_UTC + sec
|
89
|
+
|
90
|
+
Time.parse(
|
91
|
+
format(
|
92
|
+
'%<year>04d-%<mon>02d-%<day>02d %<hour>02d:%<min>02d:%<sec>02d.%<micro>06d +0000',
|
93
|
+
year: time.year,
|
94
|
+
mon: time.month,
|
95
|
+
day: time.day,
|
96
|
+
hour: time.hour,
|
97
|
+
min: time.min,
|
98
|
+
sec: time.sec,
|
99
|
+
micro: micro
|
100
|
+
)
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
36
104
|
def _to_hugeint_from_vector(lower, upper)
|
37
105
|
(upper << HALF_HUGEINT_BIT) + lower
|
38
106
|
end
|
data/lib/duckdb/database.rb
CHANGED
@@ -23,7 +23,7 @@ module DuckDB
|
|
23
23
|
#
|
24
24
|
class Database
|
25
25
|
private_class_method :_open
|
26
|
-
private_class_method :_open_ext
|
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
|
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
|
@@ -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
|
-
#
|
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 [
|
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
|
-
|
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
|
-
|
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
|
-
|
42
|
+
true
|
67
43
|
end
|
68
44
|
|
69
45
|
def use_chunk_each?
|
70
|
-
|
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
|
76
|
-
|
77
|
-
return _chunk_stream unless block_given?
|
52
|
+
if streaming?
|
53
|
+
return _chunk_stream unless block_given?
|
78
54
|
|
79
|
-
|
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
|
-
|
87
|
-
return to_enum { row_size } unless block_given?
|
57
|
+
return chunk_each unless block_given?
|
88
58
|
|
89
|
-
|
90
|
-
yield row(row_index)
|
91
|
-
end
|
59
|
+
chunk_each { |row| yield row }
|
92
60
|
end
|
93
61
|
end
|
94
62
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
-
|
105
|
-
|
106
|
-
|
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
|
data/lib/duckdb/version.rb
CHANGED