click_house 2.1.1 → 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
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