click_house 1.3.6 → 1.5.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c142ebfe52364b3762dbd35faf1e2d9bff6b84debda46e87334ce63a7bfeee42
4
- data.tar.gz: b54a1894aeac9b28abcadb5a92c2430e897f39fe6434be1eed7c7521b3145976
3
+ metadata.gz: 3dbe7ae01f5130dc0d18d9f9456ad75c2fdcc04bfe815debac344c93ce9bd00e
4
+ data.tar.gz: 4f7c8ab45593d9d37744ea9125c202052a99f582cd0887e251af790973c8a22a
5
5
  SHA512:
6
- metadata.gz: 37847807690dc35d21089b5bdda28ca6090411d84456df59704af3a4f924b87d04bb863dec4505c5c832f18a69d44440705ba57b18894706c2ef8cc6ac1b758a
7
- data.tar.gz: 1f5a6ab57d06afee3c20beeb7b91335ba380efc7266cba548d4c9fa1d62bd0ff85a1a57fb9ee760d5bd24b988fe46512b66e8520f1f9d5e3972930f1ff377a67
6
+ metadata.gz: f865c9753769cfa587ce59e428d45a664d1b976b535418e86bba7688ab3b0255177d9de7201479a683635c7376ae0958ad7803490328f55f003ba10ec098c2fc
7
+ data.tar.gz: ae3cf74cc163b842f9e27d49c84165b94858fe9b91461aa6a0bfde7404d9c9175a663a099c75e9eaf4e05ec8a1bc2dbf1840e0ed1f26f48590dc217dd6a8b4e1
@@ -8,13 +8,13 @@ jobs:
8
8
 
9
9
  services:
10
10
  clickhouse:
11
- image: yandex/clickhouse-server:20.12.3.3
11
+ image: yandex/clickhouse-server:21.3
12
12
  ports:
13
13
  - 8123:8123
14
14
 
15
15
  strategy:
16
16
  matrix:
17
- ruby-version: [2.7, 2.6, 2.5]
17
+ ruby-version: [3.0, 2.7, 2.6, 2.5, 2.4]
18
18
 
19
19
  steps:
20
20
  - uses: actions/checkout@v2
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
+ /.idea/
3
4
  /_yardoc/
4
5
  /coverage/
5
6
  /pkg/
data/.rubocop.yml CHANGED
@@ -13,9 +13,9 @@ AllCops:
13
13
  Bundler/OrderedGems:
14
14
  Enabled: false
15
15
 
16
- # ============================== Documentation ======================
17
- Style/Documentation:
18
- Enabled: false
16
+ # ============================== Gemspec ======================
17
+ Gemspec/DateAssignment:
18
+ Enabled: true
19
19
 
20
20
  # =============================== Performance =======================
21
21
  Performance/AncestorsInclude:
@@ -46,6 +46,10 @@ Performance/ConstantRegexp:
46
46
  Enabled: true
47
47
  Performance/MethodObjectAsBlock:
48
48
  Enabled: false
49
+ Performance/RedundantEqualityComparisonBlock:
50
+ Enabled: true
51
+ Performance/RedundantSplitRegexpArgument:
52
+ Enabled: true
49
53
 
50
54
  # ============================== Metrics ============================
51
55
  Metrics/ClassLength:
@@ -105,6 +109,10 @@ Layout/EmptyLinesAroundAttributeAccessor:
105
109
  Enabled: true
106
110
  Layout/SpaceAroundMethodCallOperator:
107
111
  Enabled: true
112
+ Layout/SpaceBeforeBrackets:
113
+ Enabled: true
114
+ Lint/AmbiguousAssignment:
115
+ Enabled: true
108
116
 
109
117
  # ============================== Style ==============================
110
118
  Style/RescueModifier:
@@ -217,6 +225,16 @@ Style/SwapValues:
217
225
  Enabled: true
218
226
  Style/RedundantArgument:
219
227
  Enabled: true
228
+ Style/HashExcept:
229
+ Enabled: true
230
+ Style/EndlessMethod:
231
+ Enabled: true
232
+ Style/IfWithBooleanLiteralBranches:
233
+ Enabled: true
234
+ Style/HashConversion:
235
+ Enabled: true
236
+ Style/Documentation:
237
+ Enabled: false
220
238
 
221
239
  # ============================== Lint ==============================
222
240
  Lint/DuplicateMethods:
@@ -287,3 +305,17 @@ Lint/UnmodifiedReduceAccumulator:
287
305
  Enabled: true
288
306
  Lint/UnexpectedBlockArity:
289
307
  Enabled: true
308
+ Lint/DeprecatedConstants:
309
+ Enabled: true
310
+ Lint/LambdaWithoutLiteralBlock:
311
+ Enabled: true
312
+ Lint/NumberedParameterAssignment:
313
+ Enabled: true
314
+ Lint/OrAssignmentToConstant:
315
+ Enabled: true
316
+ Lint/RedundantDirGlobSort:
317
+ Enabled: true
318
+ Lint/SymbolConversion:
319
+ Enabled: true
320
+ Lint/TripleQuotes:
321
+ Enabled: true
data/CHANGELOG.md CHANGED
@@ -1,8 +1,26 @@
1
+ # 1.5.0
2
+ * add support for 'WITH TOTALS' modifier in response
3
+ * send SQL in GET request's body [#12](https://github.com/shlima/click_house/pull/12)
4
+ * add support of 'WITH TOTALS' on a resulting set
5
+
6
+ # 1.4.0
7
+ * fix decimal type casting [#11](https://github.com/shlima/click_house/issues/11)
8
+
9
+ # 1.3.9
10
+ * add `ClickHouse.connection.add_index`, `ClickHouse.connection.drop_index`
11
+
12
+ # 1.3.8
13
+ * fix `DateTime` casting for queries like `ClickHouse.connection.select_value('select NOW()')`
14
+ * fix resulting set console inspection
15
+
16
+ # 1.3.7
17
+ * specify required ruby version [#10](https://github.com/shlima/click_house/issues/10)
18
+
1
19
  # 1.3.6
2
20
  * fix ruby 2.7 warning `maybe ** should be added to the call` on `ClickHouse.connection.databases`
3
21
 
4
22
  # 1.3.5
5
- * added `ClickHouse.connexction.explain("sql")`
23
+ * added `ClickHouse.connection.explain("sql")`
6
24
 
7
25
  # 1.3.4
8
26
  * added `ClickHouse.type_names(nullable: false)`
data/Gemfile.lock CHANGED
@@ -1,63 +1,69 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- click_house (1.3.6)
4
+ click_house (1.5.0)
5
5
  faraday
6
6
  faraday_middleware
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- ast (2.4.1)
11
+ ast (2.4.2)
12
12
  coderay (1.1.3)
13
13
  diff-lcs (1.4.4)
14
- faraday (1.1.0)
14
+ faraday (1.4.1)
15
+ faraday-excon (~> 1.1)
16
+ faraday-net_http (~> 1.0)
17
+ faraday-net_http_persistent (~> 1.1)
15
18
  multipart-post (>= 1.2, < 3)
16
- ruby2_keywords
19
+ ruby2_keywords (>= 0.0.4)
20
+ faraday-excon (1.1.0)
21
+ faraday-net_http (1.0.1)
22
+ faraday-net_http_persistent (1.1.0)
17
23
  faraday_middleware (1.0.0)
18
24
  faraday (~> 1.0)
19
25
  method_source (1.0.0)
20
26
  multipart-post (2.1.1)
21
27
  parallel (1.20.1)
22
- parser (2.7.2.0)
28
+ parser (3.0.0.0)
23
29
  ast (~> 2.4.1)
24
- pry (0.13.1)
30
+ pry (0.14.0)
25
31
  coderay (~> 1.1)
26
32
  method_source (~> 1.0)
27
33
  rainbow (3.0.0)
28
- rake (13.0.1)
29
- regexp_parser (2.0.0)
34
+ rake (13.0.3)
35
+ regexp_parser (2.1.1)
30
36
  rexml (3.2.4)
31
37
  rspec (3.10.0)
32
38
  rspec-core (~> 3.10.0)
33
39
  rspec-expectations (~> 3.10.0)
34
40
  rspec-mocks (~> 3.10.0)
35
- rspec-core (3.10.0)
41
+ rspec-core (3.10.1)
36
42
  rspec-support (~> 3.10.0)
37
- rspec-expectations (3.10.0)
43
+ rspec-expectations (3.10.1)
38
44
  diff-lcs (>= 1.2.0, < 2.0)
39
45
  rspec-support (~> 3.10.0)
40
- rspec-mocks (3.10.0)
46
+ rspec-mocks (3.10.2)
41
47
  diff-lcs (>= 1.2.0, < 2.0)
42
48
  rspec-support (~> 3.10.0)
43
- rspec-support (3.10.0)
44
- rubocop (1.5.2)
49
+ rspec-support (3.10.2)
50
+ rubocop (1.11.0)
45
51
  parallel (~> 1.10)
46
- parser (>= 2.7.1.5)
52
+ parser (>= 3.0.0.0)
47
53
  rainbow (>= 2.2.2, < 4.0)
48
54
  regexp_parser (>= 1.8, < 3.0)
49
55
  rexml
50
56
  rubocop-ast (>= 1.2.0, < 2.0)
51
57
  ruby-progressbar (~> 1.7)
52
- unicode-display_width (>= 1.4.0, < 2.0)
53
- rubocop-ast (1.3.0)
58
+ unicode-display_width (>= 1.4.0, < 3.0)
59
+ rubocop-ast (1.4.1)
54
60
  parser (>= 2.7.1.5)
55
- rubocop-performance (1.9.1)
61
+ rubocop-performance (1.10.1)
56
62
  rubocop (>= 0.90.0, < 2.0)
57
63
  rubocop-ast (>= 0.4.0)
58
- ruby-progressbar (1.10.1)
59
- ruby2_keywords (0.0.2)
60
- unicode-display_width (1.7.0)
64
+ ruby-progressbar (1.11.0)
65
+ ruby2_keywords (0.0.4)
66
+ unicode-display_width (2.0.0)
61
67
 
62
68
  PLATFORMS
63
69
  ruby
@@ -72,4 +78,4 @@ DEPENDENCIES
72
78
  rubocop-performance
73
79
 
74
80
  BUNDLED WITH
75
- 2.1.4
81
+ 2.2.14
data/README.md CHANGED
@@ -7,7 +7,6 @@
7
7
  [![Gem Version](https://badge.fury.io/rb/click_house.svg)](https://badge.fury.io/rb/click_house)
8
8
 
9
9
  ```bash
10
- # Requires Ruby >= 2.5
11
10
  gem install click_house
12
11
  ```
13
12
 
@@ -105,6 +104,9 @@ ClickHouse.connection.truncate_tables(['table_1', 'table_2'], if_exists: true, c
105
104
  ClickHouse.connection.truncate_tables # will truncate all tables in database
106
105
  ClickHouse.connection.rename_table('old_name', 'new_name', cluster: nil)
107
106
  ClickHouse.connection.rename_table(%w[table_1 table_2], %w[new_1 new_2], cluster: nil)
107
+ ClickHouse.connection.alter_table('table', 'DROP COLUMN user_id', cluster: nil)
108
+ ClickHouse.connection.add_index('table', 'ix', 'has(b, a)', type: 'minmax', granularity: 2, cluster: nil)
109
+ ClickHouse.connection.drop_index('table', 'ix', cluster: nil)
108
110
 
109
111
  ClickHouse.connection.select_all('SELECT * FROM visits')
110
112
  ClickHouse.connection.select_one('SELECT * FROM visits LIMIT 1')
@@ -498,6 +500,10 @@ class ClickHouseRecord < ActiveRecord::Base
498
500
  def select_all
499
501
  agent.select_all(current_scope.to_sql)
500
502
  end
503
+
504
+ def explain
505
+ agent.explain(current_scope.to_sql)
506
+ end
501
507
  end
502
508
  end
503
509
  ````
data/click_house.gemspec CHANGED
@@ -10,6 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.summary = 'Modern Ruby database driver for ClickHouse'
11
11
  spec.description = 'Yandex ClickHouse database interface for Ruby'
12
12
  spec.homepage = 'https://github.com/shlima/click_house'
13
+ spec.required_ruby_version = '>= 2.4.0'
13
14
 
14
15
  # Specify which files should be added to the gem when it is released.
15
16
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
data/docker-compose.yml CHANGED
@@ -2,7 +2,7 @@ version: '3.5'
2
2
 
3
3
  services:
4
4
  clickhouse:
5
- image: yandex/clickhouse-server:20.12.3.3
5
+ image: yandex/clickhouse-server:21.3
6
6
  ports:
7
7
  - "8123:8123"
8
8
  - "9000:9000"
data/lib/click_house.rb CHANGED
@@ -34,7 +34,7 @@ module ClickHouse
34
34
  add_type column, Type::StringType.new
35
35
  end
36
36
 
37
- ['DateTime(%s)'].each do |column|
37
+ %w[DateTime DateTime(%s)].each do |column|
38
38
  add_type column, Type::DateTimeType.new
39
39
  end
40
40
 
@@ -49,11 +49,15 @@ module ClickHouse
49
49
  end
50
50
 
51
51
  def logger!
52
- @logger || Logger.new(IO::NULL)
52
+ @logger || null_logger
53
53
  end
54
54
 
55
55
  def url!
56
56
  @url || "#{scheme}://#{host}:#{port}"
57
57
  end
58
+
59
+ def null_logger
60
+ @null_logger ||= Logger.new(IO::NULL)
61
+ end
58
62
  end
59
63
  end
@@ -21,8 +21,25 @@ module ClickHouse
21
21
  post(body, query: { query: query }, database: database)
22
22
  end
23
23
 
24
- def get(path = '/', query: {}, database: config.database)
25
- transport.get(compose(path, query.merge(database: database)))
24
+ # @param path [String] Clickhouse HTTP endpoint, e.g. /ping, /replica_status
25
+ # @param body [String] SQL to run
26
+ # @param database [String|NilClass] database to use, nil to skip
27
+ # @param query [Hash] other CH settings to send through params, e.g. max_rows_to_read=1
28
+ # @example get(body: 'select number from system.numbers limit 100', query: { max_rows_to_read: 10 })
29
+ # @return [Faraday::Response]
30
+ def get(path = '/', body: '', query: {}, database: config.database)
31
+ # backward compatibility since
32
+ # https://github.com/shlima/click_house/pull/12/files#diff-9c6f3f06d3b575731eae4b6b95ddbcdcc20452c432b8f6e87a3a8e8645818107R24
33
+ if query.is_a?(String)
34
+ query = { query: query }
35
+ config.logger!.warn('since v1.4.0 use connection.get(body: "SELECT 1") instead of connection.get(query: "SELECT 1")')
36
+ end
37
+
38
+ transport.get(path) do |conn|
39
+ conn.params = query.merge(database: database).compact
40
+ conn.params[:send_progress_in_http_headers] = 1 unless body.empty?
41
+ conn.body = body
42
+ end
26
43
  end
27
44
 
28
45
  def post(body = nil, query: {}, database: config.database)
@@ -66,6 +66,33 @@ module ClickHouse
66
66
 
67
67
  execute(format(template, pattern)).success?
68
68
  end
69
+
70
+ def add_index(
71
+ table_name,
72
+ name,
73
+ expression,
74
+ type:,
75
+ granularity: nil,
76
+ after: nil,
77
+ cluster: nil
78
+ )
79
+ template = 'ADD INDEX %<name>s %<expression>s TYPE %<type>s GRANULARITY %<granularity>d %<after>s'
80
+ pattern = {
81
+ name: name,
82
+ expression: expression,
83
+ type: type,
84
+ granularity: granularity,
85
+ after: Util::Statement.ensure(after, "AFTER #{after}"),
86
+ }
87
+
88
+ alter_table(table_name, format(template, pattern), cluster: cluster)
89
+ end
90
+
91
+ def drop_index(table_name, name, cluster: nil)
92
+ alter_table(table_name, <<~SQL, cluster: cluster)
93
+ DROP INDEX #{name}
94
+ SQL
95
+ end
69
96
  end
70
97
  end
71
98
  end
@@ -6,9 +6,11 @@ module ClickHouse
6
6
  EXPLAIN = 'EXPLAIN'
7
7
  EXPLAIN_RE = /\A(\s*#{EXPLAIN})/io.freeze
8
8
 
9
- def explain(sql, io: $stdout)
9
+ # @return String
10
+ def explain(sql, io: StringIO.new)
10
11
  res = execute("#{EXPLAIN} #{sql.gsub(EXPLAIN_RE, '')}")
11
- io << res.body
12
+ io.puts(res.body)
13
+ io.string
12
14
  end
13
15
  end
14
16
  end
@@ -4,8 +4,7 @@ module ClickHouse
4
4
  module Extend
5
5
  module ConnectionHealthy
6
6
  def ping
7
- # without +send_progress_in_http_headers: nil+ DB::Exception: Empty query returns
8
- get(database: nil, query: { send_progress_in_http_headers: nil }).success?
7
+ get('/ping', database: nil).success?
9
8
  end
10
9
 
11
10
  def replicas_status
@@ -5,17 +5,17 @@ module ClickHouse
5
5
  module ConnectionSelective
6
6
  # @return [ResultSet]
7
7
  def select_all(sql)
8
- response = execute(Util::Statement.format(sql, 'JSON'))
8
+ response = get(body: Util::Statement.format(sql, 'JSON'))
9
9
  Response::Factory[response]
10
10
  end
11
11
 
12
12
  def select_value(sql)
13
- response = execute(Util::Statement.format(sql, 'JSON'))
13
+ response = get(body: Util::Statement.format(sql, 'JSON'))
14
14
  Array(Response::Factory[response].first).dig(0, -1)
15
15
  end
16
16
 
17
17
  def select_one(sql)
18
- response = execute(Util::Statement.format(sql, 'JSON'))
18
+ response = get(body: Util::Statement.format(sql, 'JSON'))
19
19
  Response::Factory[response].first
20
20
  end
21
21
  end
@@ -29,11 +29,8 @@ module ClickHouse
29
29
  # rubocop:disable Layout/LineLength
30
30
  def on_complete(env)
31
31
  summary = extract_summary(env.response_headers)
32
- elapsed = duration
33
- query = CGI.parse(env.url.query.to_s).dig('query', 0) || '[NO QUERY]'
34
-
35
- logger.info("\e[1mSQL (#{Util::Pretty.measure(elapsed)})\e[0m #{query};")
36
- logger.debug(body) if body
32
+ logger.info("\e[1mSQL (#{duration_stats_log(env.body)})\e[0m #{query(env)};")
33
+ logger.debug(body) if body && !query_in_body?(env)
37
34
  logger.info("\e[1mRead: #{summary.fetch(:read_rows)} rows, #{summary.fetch(:read_bytes)}. Written: #{summary.fetch(:written_rows)} rows, #{summary.fetch(:written_bytes)}\e[0m")
38
35
  end
39
36
  # rubocop:enable Layout/LineLength
@@ -46,6 +43,28 @@ module ClickHouse
46
43
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
47
44
  end
48
45
 
46
+ def query_in_body?(env)
47
+ env.method == :get
48
+ end
49
+
50
+ def query(env)
51
+ if query_in_body?(env)
52
+ body
53
+ else
54
+ CGI.parse(env.url.query.to_s).dig('query', 0) || '[NO QUERY]'
55
+ end
56
+ end
57
+
58
+ def duration_stats_log(body)
59
+ elapsed = duration
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
+
49
68
  def extract_summary(headers)
50
69
  JSON.parse(headers.fetch('x-clickhouse-summary', '{}')).tap do |summary|
51
70
  summary[:read_rows] = summary['read_rows']
@@ -10,7 +10,12 @@ module ClickHouse
10
10
 
11
11
  return body if !body.is_a?(Hash) || !(body.key?('meta') && body.key?('data'))
12
12
 
13
- ResultSet.new(meta: body.fetch('meta'), data: body.fetch('data'), statistics: body['statistics'])
13
+ ResultSet.new(
14
+ meta: body.fetch('meta'),
15
+ data: body.fetch('data'),
16
+ totals: body['totals'],
17
+ statistics: body['statistics']
18
+ )
14
19
  end
15
20
  end
16
21
  end
@@ -11,9 +11,10 @@ module ClickHouse
11
11
  NULLABLE_TYPE_RE = /#{NULLABLE}\((.+)\)/i.freeze
12
12
 
13
13
  def_delegators :to_a,
14
- :each, :fetch, :length, :count, :size, :first, :last, :[], :to_h
14
+ :inspect, :each, :fetch, :length, :count, :size,
15
+ :first, :last, :[], :to_h
15
16
 
16
- attr_reader :meta, :data, :statistics
17
+ attr_reader :meta, :data, :totals, :statistics
17
18
 
18
19
  class << self
19
20
  # @return [Array<String, Array>]
@@ -47,9 +48,13 @@ module ClickHouse
47
48
 
48
49
  # @param meta [Array]
49
50
  # @param data [Array]
50
- def initialize(meta:, data:, statistics: nil)
51
+ # @param totals [Array|Hash|NilClass] Support for 'GROUP BY WITH TOTALS' modifier
52
+ # https://clickhouse.tech/docs/en/sql-reference/statements/select/group-by/#with-totals-modifier
53
+ # Hash in JSON format and Array in JSONCompact
54
+ def initialize(meta:, data:, totals: nil, statistics: nil)
51
55
  @meta = meta
52
56
  @data = data
57
+ @totals = totals
53
58
  @statistics = Hash(statistics)
54
59
  end
55
60
 
@@ -72,10 +77,6 @@ module ClickHouse
72
77
  }
73
78
  end
74
79
  end
75
-
76
- def inspect
77
- to_a
78
- end
79
80
  end
80
81
  end
81
82
  end
@@ -4,11 +4,11 @@ module ClickHouse
4
4
  module Type
5
5
  class DecimalType < BaseType
6
6
  def cast(value, precision = Float::DIG, _scale = nil)
7
- BigDecimal(value, precision.to_f)
7
+ BigDecimal(value, precision.to_i)
8
8
  end
9
9
 
10
10
  def serialize(value, precision = Float::DIG, _scale = nil)
11
- BigDecimal(value, precision.to_f) unless value.nil?
11
+ BigDecimal(value, precision.to_i).to_f unless value.nil?
12
12
  end
13
13
  end
14
14
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ClickHouse
4
- VERSION = '1.3.6'
4
+ VERSION = '1.5.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: click_house
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.6
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aliaksandr Shylau
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-10 00:00:00.000000000 Z
11
+ date: 2021-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -203,14 +203,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
203
203
  requirements:
204
204
  - - ">="
205
205
  - !ruby/object:Gem::Version
206
- version: '0'
206
+ version: 2.4.0
207
207
  required_rubygems_version: !ruby/object:Gem::Requirement
208
208
  requirements:
209
209
  - - ">="
210
210
  - !ruby/object:Gem::Version
211
211
  version: '0'
212
212
  requirements: []
213
- rubygems_version: 3.1.2
213
+ rubygems_version: 3.2.15
214
214
  signing_key:
215
215
  specification_version: 4
216
216
  summary: Modern Ruby database driver for ClickHouse