click_house 1.0.0 → 1.1.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 +4 -4
- data/.gitignore +1 -0
- data/Makefile +4 -1
- data/README.md +63 -0
- data/bin/release.sh +5 -0
- data/lib/click_house.rb +5 -0
- data/lib/click_house/connection.rb +1 -0
- data/lib/click_house/errors.rb +1 -0
- data/lib/click_house/extend.rb +1 -0
- data/lib/click_house/extend/connection_altering.rb +47 -0
- data/lib/click_house/extend/connection_table.rb +37 -3
- data/lib/click_house/response/result_set.rb +1 -1
- data/lib/click_house/type.rb +2 -0
- data/lib/click_house/type/array_type.rb +38 -0
- data/lib/click_house/type/string_type.rb +15 -0
- data/lib/click_house/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e21fcc0831f8f6612fac22c8e64eebb78b6e6f5d5d371c6db57dbfc0556610fd
|
|
4
|
+
data.tar.gz: 792ac875a51e3f545b9b49b55618a4161183056b82cad7e213d05ef46974d69c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bca7f416a90d0d92046c8ac171511110fe2c02329e67260279b36a475bf2b59a0c65051c3f25f1f12f5ceb26bdabc659a94a75fea499fa0de65a9d3473d85156
|
|
7
|
+
data.tar.gz: 5eee878068a827c4875a65a4435b44c87adc2fbe83b824bbb143e9086dc6ae2aad5fe4a07d43efc3fcb5bf8c2cc56003d7ca56d7fc9a4cf17db717bff90caa41
|
data/.gitignore
CHANGED
data/Makefile
CHANGED
data/README.md
CHANGED
|
@@ -28,7 +28,9 @@ Despite we have full compatibility of protocol of different versions of client a
|
|
|
28
28
|
* [Usage](#usage)
|
|
29
29
|
* [Queries](#queries)
|
|
30
30
|
* [Insert](#insert)
|
|
31
|
+
* [Insert an Array](#insert-an-array)
|
|
31
32
|
* [Create a table](#create-a-table)
|
|
33
|
+
* [Alter table](#alter-table)
|
|
32
34
|
* [Type casting](#type-casting)
|
|
33
35
|
* [Using with a connection pool](#using-with-a-connection-pool)
|
|
34
36
|
* [Using with Rails](#using-with-rails)
|
|
@@ -89,6 +91,11 @@ ClickHouse.connection.describe_table('visits') #=> [{"name"=>"id", "type"=>"Fixe
|
|
|
89
91
|
ClickHouse.connection.table_exists?('visits', temporary: nil) #=> true
|
|
90
92
|
ClickHouse.connection.drop_table('visits', if_exists: true, temporary: nil, cluster: nil)
|
|
91
93
|
ClickHouse.connection.create_table(*) # see <Create a table> section
|
|
94
|
+
ClickHouse.connection.truncate_table('name', if_exists: true, cluster: nil)
|
|
95
|
+
ClickHouse.connection.truncate_tables(['table_1', 'table_2'], if_exists: true, cluster: nil)
|
|
96
|
+
ClickHouse.connection.truncate_tables # will truncate all tables in database
|
|
97
|
+
ClickHouse.connection.rename_table('old_name', 'new_name', cluster: nil)
|
|
98
|
+
ClickHouse.connection.rename_table(%w[table_1 table_2], %w[new_1 new_2], cluster: nil)
|
|
92
99
|
```
|
|
93
100
|
|
|
94
101
|
## Queries
|
|
@@ -174,6 +181,24 @@ ClickHouse.connection.insert('table', columns: %i[id name], values: [[1, 'Mercur
|
|
|
174
181
|
#=> true
|
|
175
182
|
```
|
|
176
183
|
|
|
184
|
+
## Insert an Array
|
|
185
|
+
|
|
186
|
+
Serializing an Array of strings is pretty low level at the moment but it works (and thanks for that).
|
|
187
|
+
Array of numeric types works as expected without pre-serialization
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
string_type = ClickHouse::Type::StringType.new
|
|
191
|
+
array_of_string = ClickHouse::Type::ArrayType.new(string_type)
|
|
192
|
+
|
|
193
|
+
data = [
|
|
194
|
+
{ id: 1, tags: array_of_string.serialize(%w[ruby redis rails node]) }
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
subject.insert('rspec', columns: data.first.keys) do |buffer|
|
|
198
|
+
buffer.concat(data.map(&:values))
|
|
199
|
+
end
|
|
200
|
+
```
|
|
201
|
+
|
|
177
202
|
## Create a table
|
|
178
203
|
### Create table using DSL
|
|
179
204
|
|
|
@@ -253,6 +278,27 @@ ClickHouse.connection.execute <<~SQL
|
|
|
253
278
|
SQL
|
|
254
279
|
```
|
|
255
280
|
|
|
281
|
+
## Alter table
|
|
282
|
+
### Alter table with DSL
|
|
283
|
+
```ruby
|
|
284
|
+
ClickHouse.connection.add_column('table', 'column_name', :UInt64, default: nil, after: nil, cluster: nil)
|
|
285
|
+
ClickHouse.connection.drop_column('table', 'column_name', if_exists: nil, cluster: nil)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Alter table with SQL
|
|
289
|
+
|
|
290
|
+
```ruby
|
|
291
|
+
# By SQL in argument
|
|
292
|
+
ClickHouse.connection.alter_table('table', 'DROP COLUMN user_id', cluster: nil)
|
|
293
|
+
|
|
294
|
+
# By SQL in a block
|
|
295
|
+
ClickHouse.connection.alter_table('table', cluster: nil) do
|
|
296
|
+
<<~SQL
|
|
297
|
+
DROP COLUMN user_id
|
|
298
|
+
SQL
|
|
299
|
+
end
|
|
300
|
+
```
|
|
301
|
+
|
|
256
302
|
## Type casting
|
|
257
303
|
|
|
258
304
|
By default gem provides all necessary type casting, but you may overwrite or define
|
|
@@ -404,6 +450,23 @@ scope = Visit.with_os.select('COUNT(*) as counter').group(:ipv4)
|
|
|
404
450
|
ClickHouse.connection.select_all(scope.to_sql)
|
|
405
451
|
````
|
|
406
452
|
|
|
453
|
+
You can clear the data table before each test with RSpec
|
|
454
|
+
|
|
455
|
+
```ruby
|
|
456
|
+
RSpec.configure do |config|
|
|
457
|
+
config.before(:each, clean_click_house: true) do
|
|
458
|
+
ClickHouse.connection.truncate_tables
|
|
459
|
+
end
|
|
460
|
+
end
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
```ruby
|
|
464
|
+
RSpec.describe Api::MetricsCountroller, clean_click_house: true do
|
|
465
|
+
it { }
|
|
466
|
+
it { }
|
|
467
|
+
end
|
|
468
|
+
```
|
|
469
|
+
|
|
407
470
|
## Development
|
|
408
471
|
|
|
409
472
|
```bash
|
data/bin/release.sh
ADDED
data/lib/click_house.rb
CHANGED
|
@@ -31,6 +31,11 @@ module ClickHouse
|
|
|
31
31
|
add_type "Nullable(#{column})", Type::NullableType.new(Type::DateType.new)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
%w[String].each do |column|
|
|
35
|
+
add_type column, Type::StringType.new
|
|
36
|
+
add_type "Nullable(#{column})", Type::NullableType.new(Type::StringType.new)
|
|
37
|
+
end
|
|
38
|
+
|
|
34
39
|
['DateTime(%s)'].each do |column|
|
|
35
40
|
add_type column, Type::DateTimeType.new
|
|
36
41
|
add_type "Nullable(#{column})", Type::NullableType.new(Type::DateTimeType.new)
|
data/lib/click_house/errors.rb
CHANGED
data/lib/click_house/extend.rb
CHANGED
|
@@ -10,5 +10,6 @@ module ClickHouse
|
|
|
10
10
|
autoload :ConnectionTable, 'click_house/extend/connection_table'
|
|
11
11
|
autoload :ConnectionSelective, 'click_house/extend/connection_selective'
|
|
12
12
|
autoload :ConnectionInserting, 'click_house/extend/connection_inserting'
|
|
13
|
+
autoload :ConnectionAltering, 'click_house/extend/connection_altering'
|
|
13
14
|
end
|
|
14
15
|
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Metrics/ParameterLists
|
|
4
|
+
module ClickHouse
|
|
5
|
+
module Extend
|
|
6
|
+
module ConnectionAltering
|
|
7
|
+
def add_column(table, name, type, default: nil, if_not_exists: false, after: nil, cluster: nil)
|
|
8
|
+
sql = 'ADD COLUMN %<exists>s %<name>s %<type>s %<default>s %<after>s'
|
|
9
|
+
|
|
10
|
+
pattern = {
|
|
11
|
+
name: name,
|
|
12
|
+
exists: Util::Statement.ensure(if_not_exists, 'IF NOT EXISTS'),
|
|
13
|
+
type: Util::Statement.ensure(type, type),
|
|
14
|
+
default: Util::Statement.ensure(default, "DEFAULT #{default}"),
|
|
15
|
+
after: Util::Statement.ensure(after, "AFTER #{after}")
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
alter_table(table, format(sql, pattern), cluster: cluster)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def drop_column(table, name, if_exists: false, cluster: nil)
|
|
22
|
+
sql = 'DROP COLUMN %<exists>s %<name>s'
|
|
23
|
+
|
|
24
|
+
pattern = {
|
|
25
|
+
name: name,
|
|
26
|
+
exists: Util::Statement.ensure(if_exists, 'IF EXISTS')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
alter_table(table, format(sql, pattern), cluster: cluster)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def alter_table(name, sql = nil, cluster: nil)
|
|
33
|
+
template = 'ALTER TABLE %<name>s %<cluster>s %<sql>s'
|
|
34
|
+
sql = yield(sql) if sql.nil?
|
|
35
|
+
|
|
36
|
+
pattern = {
|
|
37
|
+
name: name,
|
|
38
|
+
sql: sql,
|
|
39
|
+
cluster: Util::Statement.ensure(cluster, "ON CLUSTER #{cluster}"),
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
execute(format(template, pattern)).success?
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
# rubocop:enable Metrics/ParameterLists
|
|
@@ -68,14 +68,48 @@ module ClickHouse
|
|
|
68
68
|
sample: Util::Statement.ensure(sample, "SAMPLE BY #{sample}"),
|
|
69
69
|
ttl: Util::Statement.ensure(ttl, "TTL #{ttl}"),
|
|
70
70
|
settings: Util::Statement.ensure(settings, "SETTINGS #{settings}"),
|
|
71
|
-
engine: Util::Statement.ensure(engine, "ENGINE = #{engine}")
|
|
71
|
+
engine: Util::Statement.ensure(engine, "ENGINE = #{engine}")
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
puts format(sql, pattern)
|
|
75
|
-
|
|
76
74
|
execute(format(sql, pattern)).success?
|
|
77
75
|
end
|
|
78
76
|
# rubocop:enable Metrics/ParameterLists
|
|
77
|
+
|
|
78
|
+
def truncate_table(name, if_exists: false, cluster: nil)
|
|
79
|
+
sql = 'TRUNCATE TABLE %<exists>s %<name>s %<cluster>s'
|
|
80
|
+
|
|
81
|
+
pattern = {
|
|
82
|
+
name: name,
|
|
83
|
+
exists: Util::Statement.ensure(if_exists, 'IF EXISTS'),
|
|
84
|
+
cluster: Util::Statement.ensure(cluster, "ON CLUSTER #{cluster}")
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
execute(format(sql, pattern)).success?
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def truncate_tables(names = tables, *argv)
|
|
91
|
+
Array(names).each { |name| truncate_table(name, *argv) }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def rename_table(from, to, cluster: nil)
|
|
95
|
+
from = Array(from)
|
|
96
|
+
to = Array(to)
|
|
97
|
+
|
|
98
|
+
unless from.length == to.length
|
|
99
|
+
raise StatementException, '<from> tables length should equal <to> length'
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
sql = <<~SQL
|
|
103
|
+
RENAME TABLE %<names>s %<cluster>s
|
|
104
|
+
SQL
|
|
105
|
+
|
|
106
|
+
pattern = {
|
|
107
|
+
names: from.zip(to).map { |a| a.join(' TO ') }.join(', '),
|
|
108
|
+
cluster: Util::Statement.ensure(cluster, "ON CLUSTER #{cluster}")
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
execute(format(sql, pattern)).success?
|
|
112
|
+
end
|
|
79
113
|
end
|
|
80
114
|
end
|
|
81
115
|
end
|
data/lib/click_house/type.rb
CHANGED
|
@@ -12,5 +12,7 @@ module ClickHouse
|
|
|
12
12
|
autoload :BooleanType, 'click_house/type/boolean_type'
|
|
13
13
|
autoload :DecimalType, 'click_house/type/decimal_type'
|
|
14
14
|
autoload :FixedStringType, 'click_house/type/fixed_string_type'
|
|
15
|
+
autoload :ArrayType, 'click_house/type/array_type'
|
|
16
|
+
autoload :StringType, 'click_house/type/string_type'
|
|
15
17
|
end
|
|
16
18
|
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ClickHouse
|
|
4
|
+
module Type
|
|
5
|
+
class ArrayType < BaseType
|
|
6
|
+
attr_reader :subtype
|
|
7
|
+
|
|
8
|
+
STRING_QUOTE = "'"
|
|
9
|
+
|
|
10
|
+
def initialize(subtype)
|
|
11
|
+
@subtype = subtype
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def cast(value, *)
|
|
15
|
+
value
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def serialize(array, *argv)
|
|
19
|
+
return array unless string?
|
|
20
|
+
|
|
21
|
+
serialized = array.map do |value|
|
|
22
|
+
escaped = subtype.serialize(value, *argv).tr(STRING_QUOTE, '\\\\' + STRING_QUOTE)
|
|
23
|
+
format("%<quote>s#{escaped}%<quote>s", quote: STRING_QUOTE)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
"[#{serialized.join(',')}]"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def string?
|
|
32
|
+
return @is_string if defined?(@is_string)
|
|
33
|
+
|
|
34
|
+
@is_string = subtype.is_a?(StringType) || subtype.is_a?(FixedStringType)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
data/lib/click_house/version.rb
CHANGED
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.
|
|
4
|
+
version: 1.1.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: 2019-11-
|
|
11
|
+
date: 2019-11-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -139,6 +139,7 @@ files:
|
|
|
139
139
|
- README.md
|
|
140
140
|
- Rakefile
|
|
141
141
|
- bin/console
|
|
142
|
+
- bin/release.sh
|
|
142
143
|
- bin/setup
|
|
143
144
|
- click_house.gemspec
|
|
144
145
|
- doc/logo.svg
|
|
@@ -153,6 +154,7 @@ files:
|
|
|
153
154
|
- lib/click_house/extend.rb
|
|
154
155
|
- lib/click_house/extend/configurable.rb
|
|
155
156
|
- lib/click_house/extend/connectible.rb
|
|
157
|
+
- lib/click_house/extend/connection_altering.rb
|
|
156
158
|
- lib/click_house/extend/connection_database.rb
|
|
157
159
|
- lib/click_house/extend/connection_healthy.rb
|
|
158
160
|
- lib/click_house/extend/connection_inserting.rb
|
|
@@ -167,6 +169,7 @@ files:
|
|
|
167
169
|
- lib/click_house/response/factory.rb
|
|
168
170
|
- lib/click_house/response/result_set.rb
|
|
169
171
|
- lib/click_house/type.rb
|
|
172
|
+
- lib/click_house/type/array_type.rb
|
|
170
173
|
- lib/click_house/type/base_type.rb
|
|
171
174
|
- lib/click_house/type/boolean_type.rb
|
|
172
175
|
- lib/click_house/type/date_time_type.rb
|
|
@@ -176,6 +179,7 @@ files:
|
|
|
176
179
|
- lib/click_house/type/float_type.rb
|
|
177
180
|
- lib/click_house/type/integer_type.rb
|
|
178
181
|
- lib/click_house/type/nullable_type.rb
|
|
182
|
+
- lib/click_house/type/string_type.rb
|
|
179
183
|
- lib/click_house/type/undefined_type.rb
|
|
180
184
|
- lib/click_house/util.rb
|
|
181
185
|
- lib/click_house/util/pretty.rb
|