click_house 2.1.1 → 2.1.2

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: 364117bb31fd3478fcf00d981b61205aa9fb864abbfeb9f9bdf253e53a0917fa
4
- data.tar.gz: d0b0d7a21175a9c2e044a88351ddd6d107b1875769ae737d3e547e41e01d93d1
3
+ metadata.gz: f311abaedb0ef60cbfc25cabaae1223d266b9e5b83f677b1267c5e8b1b56048e
4
+ data.tar.gz: 58696f010c09d829038670e703126d28be343471b45fed0c07a05727d7ba0e95
5
5
  SHA512:
6
- metadata.gz: 481ba8166f2300302c1a0836e336097e97a25015fbe5a5cf8e8fb5912b2170d50a2a1bc25178deb8b4a4b17d63e5638d0200bbca5a84c6a237de694ecf5f4d76
7
- data.tar.gz: ba051b743929517452507d54f98de6d57de724b4400d1cf9db02666a48c5b00d4dbd00a3ffab6b5f2f9c3a7db78c15f84ae36523e2ee76946526fe131722ee05
6
+ metadata.gz: 35b8b80d3beca3ed584f29dd532d7a4e525dbc355d1cca5bca3d21d32f294ed6ba95b24ef01a6d4930ef195cbe9ab98ee0517a9620ffb1aa45c06353ddf557f1
7
+ data.tar.gz: 4ba73ab43c95300c19994e90b2ee7cade877490655ec07962c1dae1175968e36eb51a5711fe2ea8da49a934acacf6414d02052e9f6594914c591be8d6cac43fe
data/.rubocop.yml CHANGED
@@ -7,6 +7,7 @@ AllCops:
7
7
  Exclude:
8
8
  - 'click_house.gemspec'
9
9
  - 'bin/*'
10
+ - 'lib/click_house/benchmark/*'
10
11
  - 'spec/**/*'
11
12
  - 'vendor/**/*'
12
13
  TargetRubyVersion: 2.7
data/CHANGELOG.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # 2.1.1
2
2
  * Fix logging with symbolized keys JSON
3
3
  * Unknown formats return raw `Response::ResultSelt` like regular JSON query
4
+ * Added methods `statistics`, `summary`, `headers` and `types` to `Response::ResultSet`
4
5
 
5
6
  # 2.1.0
6
7
  * `ClickHouse.connection.insert` now returns `ClickHouse::Response::Summary` object
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- click_house (2.1.1)
4
+ click_house (2.1.2)
5
5
  activesupport
6
6
  faraday (>= 1.7, < 3)
7
7
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- click_house (2.1.1)
4
+ click_house (2.1.2)
5
5
  activesupport
6
6
  faraday (>= 1.7, < 3)
7
7
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- click_house (2.1.1)
4
+ click_house (2.1.2)
5
5
  activesupport
6
6
  faraday (>= 1.7, < 3)
7
7
 
data/README.md CHANGED
@@ -138,12 +138,15 @@ 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
+ # results of #to_a is TYPE CASTED
142
142
  @result.to_a #=> [{"date"=>#<Date: 2000-01-01>, "id"=>1}]
143
143
 
144
+ # raw results (WITHOUT type casting)
145
+ # much faster if selecting a large amount of data
146
+ @result.data #=> [{"date"=>"2000-01-01", "id"=>1}, {"date"=>"2000-01-02", "id"=>2}]
147
+
144
148
  # you can access raw data
145
149
  @result.meta #=> [{"name"=>"date", "type"=>"Date"}, {"name"=>"id", "type"=>"UInt32"}]
146
- @result.data #=> [{"date"=>"2000-01-01", "id"=>1}, {"date"=>"2000-01-02", "id"=>2}]
147
150
  @result.statistics #=> {"elapsed"=>0.0002271, "rows_read"=>2, "bytes_read"=>12}
148
151
  @result.summary #=> ClickHouse::Response::Summary
149
152
  @result.headers #=> {"x-clickhouse-query-id"=>"9bf5f604-31fc-4eff-a4b5-277f2c71d199"}
@@ -59,6 +59,17 @@ module ClickHouse
59
59
  @arguments ||= []
60
60
  end
61
61
 
62
+ # @return [Array]
63
+ # cached argument values to increase the casting perfomance
64
+ def argument_values
65
+ @argument_values ||= arguments.map(&:value)
66
+ end
67
+
68
+ def argument_first!
69
+ # TODO: raise an error if multiple arguments
70
+ @argument_first ||= arguments.first
71
+ end
72
+
62
73
  def placeholder
63
74
  return @placeholder if defined?(@placeholder)
64
75
 
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'benchmark'
5
+ require 'pry'
6
+ require_relative '../../click_house'
7
+
8
+
9
+ ClickHouse.config.json_serializer = ClickHouse::Serializer::JsonOjSerializer
10
+ ClickHouse.config.json_parser = ClickHouse::Middleware::ParseJsonOj
11
+ ClickHouse.connection.drop_table('benchmark', if_exists: true)
12
+ ClickHouse.connection.execute <<~SQL
13
+ CREATE TABLE benchmark(
14
+ int Nullable(Int8),
15
+ date Nullable(Date),
16
+ array Array(String),
17
+ map Map(String, IPv4)
18
+ ) ENGINE Memory
19
+ SQL
20
+
21
+ INPUT = Array.new(200_000, {
22
+ 'int' => 21341234,
23
+ 'date' => Date.new(2022, 1, 1),
24
+ 'array' => ['foo'],
25
+ 'map' => {'ip' => IPAddr.new('127.0.0.1')}
26
+ })
27
+
28
+ Benchmark.bm do |x|
29
+ x.report('insert: no casting') do
30
+ ClickHouse.connection.insert('benchmark', INPUT)
31
+ end
32
+
33
+ x.report('insert: with casting') do
34
+ schema = ClickHouse.connection.table_schema('benchmark')
35
+ ClickHouse.connection.insert('benchmark', schema.serialize(INPUT))
36
+ end
37
+
38
+ x.report('select: no casting') do
39
+ ClickHouse.connection.select_all('SELECT * FROM benchmark').data
40
+ end
41
+
42
+ x.report('select: with casting') do
43
+ ClickHouse.connection.select_all('SELECT * FROM benchmark').to_a
44
+ end
45
+ end
@@ -113,7 +113,7 @@ module ClickHouse
113
113
  return cast_map(stmt, Hash(value)) if stmt.caster.map?
114
114
  return cast_tuple(stmt, Array(value)) if stmt.caster.tuple?
115
115
 
116
- stmt.caster.cast(value, *stmt.arguments.map(&:value))
116
+ stmt.caster.cast(value, *stmt.argument_values)
117
117
  end
118
118
 
119
119
  # @return [Hash]
@@ -131,8 +131,7 @@ module ClickHouse
131
131
  # @param stmt [Ast::Statement]
132
132
  def cast_container(stmt, value)
133
133
  stmt.caster.cast_each(value) do |item|
134
- # TODO: raise an error if multiple arguments
135
- cast_type(stmt.arguments.first, item)
134
+ cast_type(stmt.argument_first!, item)
136
135
  end
137
136
  end
138
137
 
@@ -149,14 +148,13 @@ module ClickHouse
149
148
  return serialize_map(stmt, value) if stmt.caster.map?
150
149
  return serialize_tuple(stmt, Array(value)) if stmt.caster.tuple?
151
150
 
152
- stmt.caster.serialize(value, *stmt.arguments.map(&:value))
151
+ stmt.caster.serialize(value, *stmt.argument_values)
153
152
  end
154
153
 
155
154
  # @param stmt [Ast::Statement]
156
155
  def serialize_container(stmt, value)
157
- stmt.caster.cast_each(value) do |item|
158
- # TODO: raise an error if multiple arguments
159
- serialize_type(stmt.arguments.first, item)
156
+ stmt.caster.serialize_each(value) do |item|
157
+ serialize_type(stmt.argument_first!, item)
160
158
  end
161
159
  end
162
160
 
@@ -3,16 +3,37 @@
3
3
  module ClickHouse
4
4
  module Type
5
5
  class DateTime64Type < BaseType
6
- def cast(value, _precision = nil, tz = nil)
6
+ BASE_FORMAT = '%Y-%m-%d %H:%M:%S'
7
+ CAST_FORMAT = "#{BASE_FORMAT}.%N"
8
+ SERIALIZE_FORMATS = {
9
+ 0 => BASE_FORMAT,
10
+ 1 => "#{BASE_FORMAT}.%1N",
11
+ 2 => "#{BASE_FORMAT}.%2N",
12
+ 3 => "#{BASE_FORMAT}.%3N",
13
+ 4 => "#{BASE_FORMAT}.%4N",
14
+ 5 => "#{BASE_FORMAT}.%5N",
15
+ 6 => "#{BASE_FORMAT}.%6N",
16
+ 7 => "#{BASE_FORMAT}.%7N",
17
+ 8 => "#{BASE_FORMAT}.%8N",
18
+ 9 => "#{BASE_FORMAT}.%9N",
19
+ }.freeze
20
+
21
+ # Tick size (precision):
22
+ # 10-precision seconds.
23
+ # Valid range: [ 0 : 9 ].
24
+ # Typically are used - 3 (milliseconds), 6 (microseconds), 9 (nanoseconds).
25
+ def cast(value, precision = 0, tz = nil)
26
+ format = precision.zero? ? BASE_FORMAT : CAST_FORMAT
27
+
7
28
  if tz
8
- Time.find_zone(tz).parse(value)
29
+ Time.find_zone(tz).strptime(value, format)
9
30
  else
10
- Time.parse(value)
31
+ Time.strptime(value, format)
11
32
  end
12
33
  end
13
34
 
14
35
  def serialize(value, precision = 3, _tz = nil)
15
- value.strftime("%Y-%m-%d %H:%M:%S.%#{precision}N")
36
+ value.strftime(SERIALIZE_FORMATS.fetch(precision))
16
37
  end
17
38
  end
18
39
  end
@@ -3,16 +3,18 @@
3
3
  module ClickHouse
4
4
  module Type
5
5
  class DateTimeType < BaseType
6
+ FORMAT = '%Y-%m-%d %H:%M:%S'
7
+
6
8
  def cast(value, tz = nil)
7
9
  if tz
8
- Time.find_zone(tz).parse(value)
10
+ Time.find_zone(tz).strptime(value, FORMAT)
9
11
  else
10
- Time.parse(value)
12
+ Time.strptime(value, FORMAT)
11
13
  end
12
14
  end
13
15
 
14
16
  def serialize(value, *)
15
- value.strftime('%Y-%m-%d %H:%M:%S')
17
+ value.strftime(FORMAT)
16
18
  end
17
19
  end
18
20
  end
@@ -3,12 +3,14 @@
3
3
  module ClickHouse
4
4
  module Type
5
5
  class DateType < BaseType
6
+ FORMAT = '%Y-%m-%d'
7
+
6
8
  def cast(value)
7
- Date.parse(value)
9
+ Date.strptime(value, FORMAT)
8
10
  end
9
11
 
10
12
  def serialize(value)
11
- value.strftime('%Y-%m-%d')
13
+ value.strftime(FORMAT)
12
14
  end
13
15
  end
14
16
  end
@@ -4,11 +4,11 @@ module ClickHouse
4
4
  module Type
5
5
  class IntegerType < BaseType
6
6
  def cast(value)
7
- Integer(value) unless value.nil?
7
+ Integer(value)
8
8
  end
9
9
 
10
10
  def serialize(value)
11
- value.to_i unless value.nil?
11
+ value.to_i
12
12
  end
13
13
  end
14
14
  end
@@ -4,11 +4,11 @@ module ClickHouse
4
4
  module Type
5
5
  class IPType < BaseType
6
6
  def cast(value)
7
- IPAddr.new(value) unless value.nil?
7
+ IPAddr.new(value)
8
8
  end
9
9
 
10
10
  def serialize(value)
11
- value.to_s unless value.nil?
11
+ value.to_s
12
12
  end
13
13
  end
14
14
  end
@@ -4,7 +4,11 @@ module ClickHouse
4
4
  module Type
5
5
  class LowCardinalityType < BaseType
6
6
  def cast_each(value, *_argv)
7
- yield(value) unless value.nil?
7
+ yield(value)
8
+ end
9
+
10
+ def serialize_each(value, *_argv)
11
+ yield(value)
8
12
  end
9
13
 
10
14
  def container?
@@ -7,6 +7,10 @@ module ClickHouse
7
7
  yield(value) unless value.nil?
8
8
  end
9
9
 
10
+ def serialize_each(value, *_argv)
11
+ yield(value) unless value.nil?
12
+ end
13
+
10
14
  def container?
11
15
  true
12
16
  end
@@ -4,11 +4,11 @@ module ClickHouse
4
4
  module Type
5
5
  class StringType < BaseType
6
6
  def cast(value, *)
7
- value.to_s unless value.nil?
7
+ value.to_s
8
8
  end
9
9
 
10
10
  def serialize(value, *)
11
- value.to_s unless value.nil?
11
+ value.to_s
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 = '2.1.1'
4
+ VERSION = '2.1.2'
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: 2.1.1
4
+ version: 2.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aliaksandr Shylau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-20 00:00:00.000000000 Z
11
+ date: 2022-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -175,6 +175,7 @@ files:
175
175
  - lib/click_house/ast/parser.rb
176
176
  - lib/click_house/ast/statement.rb
177
177
  - lib/click_house/ast/ticker.rb
178
+ - lib/click_house/benchmark/casting.rb
178
179
  - lib/click_house/benchmark/map_join.rb
179
180
  - lib/click_house/config.rb
180
181
  - lib/click_house/connection.rb