click_house 2.1.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -1
- data/Gemfile.lock +1 -1
- data/Gemfile_faraday1.lock +1 -1
- data/Gemfile_faraday2.lock +1 -1
- data/README.md +4 -0
- data/lib/click_house/connection.rb +3 -2
- data/lib/click_house/extend/connection_inserting.rb +1 -1
- data/lib/click_house/extend/connection_selective.rb +10 -1
- data/lib/click_house/middleware/logging.rb +23 -39
- data/lib/click_house/middleware/response_base.rb +4 -4
- data/lib/click_house/middleware/summary_middleware.rb +26 -0
- data/lib/click_house/middleware.rb +1 -0
- data/lib/click_house/response/factory.rb +22 -14
- data/lib/click_house/response/result_set.rb +17 -10
- data/lib/click_house/response/summary.rb +109 -0
- data/lib/click_house/response.rb +1 -1
- data/lib/click_house/util.rb +7 -0
- data/lib/click_house/version.rb +1 -1
- metadata +3 -2
- data/lib/click_house/response/execution.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 364117bb31fd3478fcf00d981b61205aa9fb864abbfeb9f9bdf253e53a0917fa
|
4
|
+
data.tar.gz: d0b0d7a21175a9c2e044a88351ddd6d107b1875769ae737d3e547e41e01d93d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 481ba8166f2300302c1a0836e336097e97a25015fbe5a5cf8e8fb5912b2170d50a2a1bc25178deb8b4a4b17d63e5638d0200bbca5a84c6a237de694ecf5f4d76
|
7
|
+
data.tar.gz: ba051b743929517452507d54f98de6d57de724b4400d1cf9db02666a48c5b00d4dbd00a3ffab6b5f2f9c3a7db78c15f84ae36523e2ee76946526fe131722ee05
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
|
+
# 2.1.1
|
2
|
+
* Fix logging with symbolized keys JSON
|
3
|
+
* Unknown formats return raw `Response::ResultSelt` like regular JSON query
|
4
|
+
|
1
5
|
# 2.1.0
|
2
|
-
* `ClickHouse.connection.insert` now returns `ClickHouse::Response::
|
6
|
+
* `ClickHouse.connection.insert` now returns `ClickHouse::Response::Summary` object
|
3
7
|
with methods `headers`, `summary`, `written_rows`, `written_bytes`, etc...
|
4
8
|
* `ClickHouse.connection.insert(columns: ["id"], values: [1])` now uses `JSONCompactEachRow` by default
|
5
9
|
(to increase JSON serialization speed)
|
data/Gemfile.lock
CHANGED
data/Gemfile_faraday1.lock
CHANGED
data/Gemfile_faraday2.lock
CHANGED
data/README.md
CHANGED
@@ -138,12 +138,16 @@ Select all type-casted result set
|
|
138
138
|
@result = ClickHouse.connection.select_all('SELECT * FROM visits')
|
139
139
|
|
140
140
|
# all enumerable methods are delegated like #each, #map, #select etc
|
141
|
+
# results of #to_a is type casted
|
141
142
|
@result.to_a #=> [{"date"=>#<Date: 2000-01-01>, "id"=>1}]
|
142
143
|
|
143
144
|
# you can access raw data
|
144
145
|
@result.meta #=> [{"name"=>"date", "type"=>"Date"}, {"name"=>"id", "type"=>"UInt32"}]
|
145
146
|
@result.data #=> [{"date"=>"2000-01-01", "id"=>1}, {"date"=>"2000-01-02", "id"=>2}]
|
146
147
|
@result.statistics #=> {"elapsed"=>0.0002271, "rows_read"=>2, "bytes_read"=>12}
|
148
|
+
@result.summary #=> ClickHouse::Response::Summary
|
149
|
+
@result.headers #=> {"x-clickhouse-query-id"=>"9bf5f604-31fc-4eff-a4b5-277f2c71d199"}
|
150
|
+
@result.types #=> [Hash<String|Symbol, ClickHouse::Ast::Statement>]
|
147
151
|
```
|
148
152
|
|
149
153
|
### Select Value
|
@@ -65,8 +65,9 @@ module ClickHouse
|
|
65
65
|
|
66
66
|
conn.response Middleware::RaiseError
|
67
67
|
conn.response Middleware::Logging, logger: config.logger!
|
68
|
-
conn.response
|
69
|
-
conn.response
|
68
|
+
conn.response Middleware::SummaryMiddleware, options: { config: config } # should be after logger
|
69
|
+
conn.response config.json_parser, content_type: %r{application/json}, options: { config: config }
|
70
|
+
conn.response Middleware::ParseCsv, content_type: %r{text/csv}, options: { config: config }
|
70
71
|
conn.adapter config.adapter
|
71
72
|
end
|
72
73
|
end
|
@@ -46,7 +46,7 @@ module ClickHouse
|
|
46
46
|
return insert_compact(table, columns: columns, values: values, format: format)
|
47
47
|
end
|
48
48
|
|
49
|
-
Response::Factory.empty_exec
|
49
|
+
Response::Factory.empty_exec(config)
|
50
50
|
end
|
51
51
|
# rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
52
52
|
|
@@ -11,7 +11,16 @@ module ClickHouse
|
|
11
11
|
|
12
12
|
def select_value(sql)
|
13
13
|
response = get(body: sql, query: { default_format: 'JSON' })
|
14
|
-
|
14
|
+
got = Response::Factory.response(response, config).first
|
15
|
+
|
16
|
+
case got
|
17
|
+
when Hash
|
18
|
+
Array(got).dig(0, -1) # get a value of a first key for JSON format
|
19
|
+
when Array
|
20
|
+
got[0] # for CSV format
|
21
|
+
else
|
22
|
+
got # for RowBinary format
|
23
|
+
end
|
15
24
|
end
|
16
25
|
|
17
26
|
def select_one(sql)
|
@@ -5,36 +5,32 @@ module ClickHouse
|
|
5
5
|
class Logging < Faraday::Middleware
|
6
6
|
Faraday::Response.register_middleware self => self
|
7
7
|
|
8
|
-
|
8
|
+
EMPTY = ''
|
9
|
+
GET = :get
|
9
10
|
|
10
|
-
attr_reader :logger, :starting
|
11
|
+
attr_reader :logger, :starting
|
11
12
|
|
12
13
|
def initialize(app = nil, logger:)
|
13
14
|
@logger = logger
|
14
15
|
super(app)
|
15
16
|
end
|
16
17
|
|
17
|
-
def call(
|
18
|
+
def call(env)
|
18
19
|
@starting = timestamp
|
19
|
-
|
20
|
-
@app.call(environment).on_complete(&method(:on_complete))
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def log_body?
|
26
|
-
logger.level == Logger::DEBUG
|
20
|
+
super
|
27
21
|
end
|
28
22
|
|
29
23
|
# rubocop:disable Layout/LineLength
|
30
24
|
def on_complete(env)
|
31
|
-
summary =
|
32
|
-
logger.info("\e[1m[35mSQL (#{duration_stats_log(
|
33
|
-
logger.debug(
|
34
|
-
logger.info("\e[1m[36mRead: #{summary.
|
25
|
+
summary = SummaryMiddleware.extract(env)
|
26
|
+
logger.info("\e[1m[35mSQL (#{duration_stats_log(summary)})\e[0m #{query(env)};")
|
27
|
+
logger.debug(env.request_body) if log_body?(env)
|
28
|
+
logger.info("\e[1m[36mRead: #{summary.read_rows} rows, #{summary.read_bytes_pretty}. Written: #{summary.written_rows} rows, #{summary.written_bytes_pretty}\e[0m")
|
35
29
|
end
|
36
30
|
# rubocop:enable Layout/LineLength
|
37
31
|
|
32
|
+
private
|
33
|
+
|
38
34
|
def duration
|
39
35
|
timestamp - starting
|
40
36
|
end
|
@@ -43,37 +39,25 @@ module ClickHouse
|
|
43
39
|
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
44
40
|
end
|
45
41
|
|
46
|
-
|
47
|
-
|
42
|
+
# @return [Boolean]
|
43
|
+
def log_body?(env)
|
44
|
+
return unless logger.debug?
|
45
|
+
return if env.method == GET # GET queries logs body as a statement
|
46
|
+
return if env.request_body.nil? || env.request_body == EMPTY
|
47
|
+
|
48
|
+
true
|
48
49
|
end
|
49
50
|
|
50
51
|
def query(env)
|
51
|
-
if
|
52
|
-
|
52
|
+
if env.method == GET
|
53
|
+
env.request_body
|
53
54
|
else
|
54
|
-
CGI.parse(env.url.query.to_s).dig('query', 0) || '[NO QUERY]'
|
55
|
+
String(CGI.parse(env.url.query.to_s).dig('query', 0) || '[NO QUERY]').chomp
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
58
|
-
def duration_stats_log(
|
59
|
-
|
60
|
-
clickhouse_elapsed = body['statistics'].fetch('elapsed') if body.is_a?(Hash) && body.key?('statistics')
|
61
|
-
|
62
|
-
[
|
63
|
-
"Total: #{Util::Pretty.measure(elapsed * 1000)}",
|
64
|
-
("CH: #{Util::Pretty.measure(clickhouse_elapsed * 1000)}" if clickhouse_elapsed)
|
65
|
-
].compact.join(', ')
|
66
|
-
end
|
67
|
-
|
68
|
-
def extract_summary(headers)
|
69
|
-
JSON.parse(headers.fetch('x-clickhouse-summary', '{}')).tap do |summary|
|
70
|
-
summary[:read_rows] = summary['read_rows']
|
71
|
-
summary[:read_bytes] = Util::Pretty.size(summary['read_bytes'].to_i)
|
72
|
-
summary[:written_rows] = summary['written_rows']
|
73
|
-
summary[:written_bytes] = Util::Pretty.size(summary['written_bytes'].to_i)
|
74
|
-
end
|
75
|
-
rescue JSON::ParserError
|
76
|
-
{}
|
59
|
+
def duration_stats_log(summary)
|
60
|
+
"Total: #{Util::Pretty.measure(duration * 1000)}, CH: #{summary.elapsed_pretty}"
|
77
61
|
end
|
78
62
|
end
|
79
63
|
end
|
@@ -5,12 +5,12 @@ module ClickHouse
|
|
5
5
|
class ResponseBase < Faraday::Middleware
|
6
6
|
CONTENT_TYPE_HEADER = 'content-type'
|
7
7
|
|
8
|
-
attr_reader :
|
8
|
+
attr_reader :options
|
9
9
|
attr_reader :content_type
|
10
10
|
|
11
|
-
def initialize(app = nil,
|
11
|
+
def initialize(app = nil, options: {}, content_type: nil, preserve_raw: false)
|
12
12
|
super(app)
|
13
|
-
@
|
13
|
+
@options = options
|
14
14
|
@content_type = content_type
|
15
15
|
@preserve_raw = preserve_raw
|
16
16
|
on_setup
|
@@ -32,7 +32,7 @@ module ClickHouse
|
|
32
32
|
|
33
33
|
# @return [Config]
|
34
34
|
def config
|
35
|
-
|
35
|
+
options.fetch(:config)
|
36
36
|
end
|
37
37
|
|
38
38
|
private
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ClickHouse
|
4
|
+
module Middleware
|
5
|
+
class SummaryMiddleware < ResponseBase
|
6
|
+
Faraday::Response.register_middleware self => self
|
7
|
+
|
8
|
+
KEY = :summary
|
9
|
+
|
10
|
+
# @param env [Faraday::Env]
|
11
|
+
# @return [Response::Summary]
|
12
|
+
def self.extract(env)
|
13
|
+
env.custom_members.fetch(KEY)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param env [Faraday::Env]
|
17
|
+
def on_complete(env)
|
18
|
+
env.custom_members[KEY] = Response::Summary.new(
|
19
|
+
config,
|
20
|
+
headers: env.response_headers,
|
21
|
+
body: env.body.is_a?(Hash) ? env.body : {}
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module ClickHouse
|
4
4
|
module Middleware
|
5
5
|
autoload :ResponseBase, 'click_house/middleware/response_base'
|
6
|
+
autoload :SummaryMiddleware, 'click_house/middleware/summary_middleware'
|
6
7
|
autoload :Logging, 'click_house/middleware/logging'
|
7
8
|
autoload :ParseCsv, 'click_house/middleware/parse_csv'
|
8
9
|
autoload :ParseJsonOj, 'click_house/middleware/parse_json_oj'
|
@@ -5,38 +5,46 @@ module ClickHouse
|
|
5
5
|
class Factory
|
6
6
|
KEY_META = 'meta'
|
7
7
|
KEY_DATA = 'data'
|
8
|
-
KEY_TOTALS = 'totals'
|
9
|
-
KEY_STATISTICS = 'statistics'
|
10
|
-
KEY_ROWS_BEFORE_LIMIT_AT_LEAST = 'rows_before_limit_at_least'
|
11
8
|
|
12
|
-
# @return [
|
9
|
+
# @return [ResultSet]
|
13
10
|
# @params faraday [Faraday::Response]
|
14
11
|
# @params config [Config]
|
15
12
|
def self.response(faraday, config)
|
16
13
|
body = faraday.body
|
17
14
|
|
18
|
-
|
19
|
-
|
15
|
+
# wrap to be able to use connection#select_one, connection#select_value
|
16
|
+
# with other formats like binary
|
17
|
+
return raw(faraday, config) unless body.is_a?(Hash)
|
18
|
+
return raw(faraday, config) unless body.key?(config.key(KEY_META)) && body.key?(config.key(KEY_DATA))
|
20
19
|
|
21
20
|
ResultSet.new(
|
22
21
|
config: config,
|
23
22
|
meta: body.fetch(config.key(KEY_META)),
|
24
23
|
data: body.fetch(config.key(KEY_DATA)),
|
25
|
-
|
26
|
-
statistics: body[config.key(KEY_STATISTICS)],
|
27
|
-
rows_before_limit_at_least: body[config.key(KEY_ROWS_BEFORE_LIMIT_AT_LEAST)]
|
24
|
+
summary: Middleware::SummaryMiddleware.extract(faraday.env)
|
28
25
|
)
|
29
26
|
end
|
30
27
|
|
31
|
-
# @return [
|
28
|
+
# @return [ResultSet]
|
29
|
+
# Rae ResultSet (without type casting)
|
30
|
+
def self.raw(faraday, config)
|
31
|
+
ResultSet.raw(
|
32
|
+
config: config,
|
33
|
+
data: Util.array(faraday.body),
|
34
|
+
summary: Middleware::SummaryMiddleware.extract(faraday.env)
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Result of execution
|
39
|
+
# @return [Response::Summary]
|
32
40
|
# @params faraday [Faraday::Response]
|
33
41
|
def self.exec(faraday)
|
34
|
-
|
42
|
+
Middleware::SummaryMiddleware.extract(faraday.env)
|
35
43
|
end
|
36
44
|
|
37
|
-
# @return [Response::
|
38
|
-
def self.empty_exec
|
39
|
-
|
45
|
+
# @return [Response::Summary]
|
46
|
+
def self.empty_exec(config)
|
47
|
+
Summary.new(config)
|
40
48
|
end
|
41
49
|
end
|
42
50
|
end
|
@@ -13,24 +13,31 @@ module ClickHouse
|
|
13
13
|
:inspect, :each, :fetch, :length, :count, :size,
|
14
14
|
:first, :last, :[], :to_h
|
15
15
|
|
16
|
-
|
16
|
+
def_delegators :summary,
|
17
|
+
:statistics, :headers,
|
18
|
+
:totals, :rows_before_limit_at_least
|
19
|
+
|
20
|
+
attr_reader :config, :meta, :data, :summary
|
21
|
+
|
22
|
+
class << self
|
23
|
+
# @param config [Config]
|
24
|
+
# @return [ResultSet]
|
25
|
+
def raw(config:, data:, summary:)
|
26
|
+
new(config: config, data: data, to_a: data, meta: [], summary: summary)
|
27
|
+
end
|
28
|
+
end
|
17
29
|
|
18
30
|
# @param config [Config]
|
19
31
|
# @param meta [Array]
|
20
32
|
# @param data [Array]
|
21
|
-
# @param
|
22
|
-
|
23
|
-
# Hash in JSON format and Array in JSONCompact
|
24
|
-
# rubocop:disable Metrics/ParameterLists
|
25
|
-
def initialize(config:, meta:, data:, totals: nil, statistics: nil, rows_before_limit_at_least: nil)
|
33
|
+
# @param summary [Response::Summary]
|
34
|
+
def initialize(config:, meta:, data:, summary:, to_a: nil)
|
26
35
|
@config = config
|
27
36
|
@meta = meta
|
28
37
|
@data = data
|
29
|
-
@
|
30
|
-
@
|
31
|
-
@statistics = Hash(statistics)
|
38
|
+
@summary = summary
|
39
|
+
@to_a = to_a
|
32
40
|
end
|
33
|
-
# rubocop:enable Metrics/ParameterLists
|
34
41
|
|
35
42
|
# @return [Array, Hash]
|
36
43
|
# @param data [Array, Hash]
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ClickHouse
|
4
|
+
module Response
|
5
|
+
class Summary
|
6
|
+
SUMMARY_HEADER = 'x-clickhouse-summary'
|
7
|
+
KEY_TOTALS = 'totals'
|
8
|
+
KEY_STATISTICS = 'statistics'
|
9
|
+
KEY_ROWS_BEFORE_LIMIT_AT_LEAST = 'rows_before_limit_at_least'
|
10
|
+
KEY_STAT_ELAPSED = 'elapsed'
|
11
|
+
|
12
|
+
attr_reader :config,
|
13
|
+
:headers,
|
14
|
+
:summary,
|
15
|
+
# {:elapsed=>0.387287e-3, :rows_read=>0, :bytes_read=>0}}
|
16
|
+
:statistics,
|
17
|
+
:totals,
|
18
|
+
:rows_before_limit_at_least
|
19
|
+
|
20
|
+
# @param config [Config]
|
21
|
+
# @param headers [Faraday::Utils::Headers]
|
22
|
+
# @param body [Hash]
|
23
|
+
# TOTALS [Array|Hash|NilClass] Support for 'GROUP BY WITH TOTALS' modifier
|
24
|
+
# https://clickhouse.tech/docs/en/sql-reference/statements/select/group-by/#with-totals-modifier
|
25
|
+
# Hash in JSON format and Array in JSONCompact
|
26
|
+
def initialize(config, headers: Faraday::Utils::Headers.new, body: {})
|
27
|
+
@headers = headers
|
28
|
+
@config = config
|
29
|
+
@statistics = body.fetch(config.key(KEY_STATISTICS), {})
|
30
|
+
@totals = body[config.key(KEY_TOTALS)]
|
31
|
+
@rows_before_limit_at_least = body[config.key(KEY_ROWS_BEFORE_LIMIT_AT_LEAST)]
|
32
|
+
@summary = parse_summary(headers[SUMMARY_HEADER])
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Integer]
|
36
|
+
def read_rows
|
37
|
+
summary[config.key('read_rows')].to_i
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Integer]
|
41
|
+
def read_bytes
|
42
|
+
summary[config.key('read_bytes')].to_i
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [String]
|
46
|
+
def read_bytes_pretty
|
47
|
+
Util::Pretty.size(read_bytes)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Integer]
|
51
|
+
def written_rows
|
52
|
+
summary[config.key('written_rows')].to_i
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Integer]
|
56
|
+
def written_bytes
|
57
|
+
summary[config.key('written_bytes')].to_i
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [String]
|
61
|
+
def written_bytes_pretty
|
62
|
+
Util::Pretty.size(written_bytes)
|
63
|
+
end
|
64
|
+
|
65
|
+
# @return [Integer]
|
66
|
+
def total_rows_to_read
|
67
|
+
summary[config.key('total_rows_to_read')].to_i
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [Integer]
|
71
|
+
def result_rows
|
72
|
+
summary[config.key('result_rows')].to_i
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Integer]
|
76
|
+
def result_bytes
|
77
|
+
summary[config.key('result_bytes')].to_i
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return [Float]
|
81
|
+
def elapsed
|
82
|
+
statistics[config.key(KEY_STAT_ELAPSED)].to_f
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [String]
|
86
|
+
def elapsed_pretty
|
87
|
+
Util::Pretty.measure(elapsed * 1000)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# @return [Hash]
|
93
|
+
# {
|
94
|
+
# "read_rows" => "1",
|
95
|
+
# "read_bytes" => "23",
|
96
|
+
# "written_rows" => "1",
|
97
|
+
# "written_bytes" => "23",
|
98
|
+
# "total_rows_to_read" => "0",
|
99
|
+
# "result_rows" => "1",
|
100
|
+
# "result_bytes" => "23",
|
101
|
+
# }
|
102
|
+
def parse_summary(value)
|
103
|
+
return {} if value.nil? || value.empty?
|
104
|
+
|
105
|
+
JSON.parse(value)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/click_house/response.rb
CHANGED
data/lib/click_house/util.rb
CHANGED
data/lib/click_house/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: click_house
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aliaksandr Shylau
|
@@ -200,10 +200,11 @@ files:
|
|
200
200
|
- lib/click_house/middleware/parse_json_oj.rb
|
201
201
|
- lib/click_house/middleware/raise_error.rb
|
202
202
|
- lib/click_house/middleware/response_base.rb
|
203
|
+
- lib/click_house/middleware/summary_middleware.rb
|
203
204
|
- lib/click_house/response.rb
|
204
|
-
- lib/click_house/response/execution.rb
|
205
205
|
- lib/click_house/response/factory.rb
|
206
206
|
- lib/click_house/response/result_set.rb
|
207
|
+
- lib/click_house/response/summary.rb
|
207
208
|
- lib/click_house/serializer.rb
|
208
209
|
- lib/click_house/serializer/base.rb
|
209
210
|
- lib/click_house/serializer/json_oj_serializer.rb
|
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ClickHouse
|
4
|
-
module Response
|
5
|
-
class Execution
|
6
|
-
SUMMARY_HEADER = 'x-clickhouse-summary'
|
7
|
-
|
8
|
-
attr_reader :headers, :summary
|
9
|
-
|
10
|
-
# @param headers [Faraday::Utils::Headers]
|
11
|
-
def initialize(headers: Faraday::Utils::Headers.new)
|
12
|
-
@headers = headers
|
13
|
-
@summary = parse_summary(headers[SUMMARY_HEADER])
|
14
|
-
end
|
15
|
-
|
16
|
-
# @return [Integer]
|
17
|
-
def read_rows
|
18
|
-
summary['read_rows'].to_i
|
19
|
-
end
|
20
|
-
|
21
|
-
# @return [Integer]
|
22
|
-
def read_bytes
|
23
|
-
summary['read_bytes'].to_i
|
24
|
-
end
|
25
|
-
|
26
|
-
# @return [Integer]
|
27
|
-
def written_rows
|
28
|
-
summary['written_rows'].to_i
|
29
|
-
end
|
30
|
-
|
31
|
-
# @return [Integer]
|
32
|
-
def written_bytes
|
33
|
-
summary['written_bytes'].to_i
|
34
|
-
end
|
35
|
-
|
36
|
-
# @return [Integer]
|
37
|
-
def total_rows_to_read
|
38
|
-
summary['total_rows_to_read'].to_i
|
39
|
-
end
|
40
|
-
|
41
|
-
# @return [Integer]
|
42
|
-
def result_rows
|
43
|
-
summary['result_rows'].to_i
|
44
|
-
end
|
45
|
-
|
46
|
-
# @return [Integer]
|
47
|
-
def result_bytes
|
48
|
-
summary['result_bytes'].to_i
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
# @return [Hash]
|
54
|
-
# {
|
55
|
-
# "read_rows" => "1",
|
56
|
-
# "read_bytes" => "23",
|
57
|
-
# "written_rows" => "1",
|
58
|
-
# "written_bytes" => "23",
|
59
|
-
# "total_rows_to_read" => "0",
|
60
|
-
# "result_rows" => "1",
|
61
|
-
# "result_bytes" => "23",
|
62
|
-
# }
|
63
|
-
def parse_summary(value)
|
64
|
-
return {} if value.nil? || value.empty?
|
65
|
-
|
66
|
-
JSON.parse(value)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|