clickhouse-activerecord 0.4.8 → 0.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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +54 -1
- data/lib/active_record/connection_adapters/clickhouse/schema_creation.rb +18 -5
- data/lib/active_record/connection_adapters/clickhouse/schema_definitions.rb +23 -5
- data/lib/active_record/connection_adapters/clickhouse/schema_statements.rb +7 -5
- data/lib/active_record/connection_adapters/clickhouse_adapter.rb +52 -18
- data/lib/clickhouse-activerecord/migration.rb +4 -2
- data/lib/clickhouse-activerecord/schema_dumper.rb +18 -2
- data/lib/clickhouse-activerecord/tasks.rb +1 -1
- data/lib/clickhouse-activerecord/version.rb +1 -1
- data/lib/generators/clickhouse_migration_generator.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e17583f619debbb02952aa4299fedebbdd0de5ff6ae5c4a604071e42381c33a
|
4
|
+
data.tar.gz: d9d642a756c2ff7791081f1298917d96758dd5de4f07781dc7c9e587100536b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cca1c4ce673a6622855a860e51b85952b0b09e3cbaaafe6b817a5c95ff1bb90d33da4974908acecaed6a658f7574fbaf9f71c1497d1c527006eb36bc3aaefab3
|
7
|
+
data.tar.gz: 344cc941b595fe40179c8974dfc371dd3732cbf8994999d75976506582d23abbda39340e7b2232cc7b7c25f1c6271d3f26325c409cfd7aa21f1acfc017fb8d32
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
### Version 0.4.10 (Mar 10, 2021)
|
2
|
+
|
3
|
+
* Support ClickHouse 20.9+
|
4
|
+
* Fix schema create / dump
|
5
|
+
* Support all integer types through :limit and :unsigned [@bdevel](https://github.com/bdevel)
|
6
|
+
|
1
7
|
### Version 0.4.4 (Sep 23, 2020)
|
2
8
|
|
3
9
|
* Full support migration and rollback database
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Clickhouse::Activerecord
|
2
2
|
|
3
3
|
A Ruby database ActiveRecord driver for ClickHouse. Support Rails >= 5.2.
|
4
|
-
Support ClickHouse version from
|
4
|
+
Support ClickHouse version from 20.9 LTS.
|
5
5
|
|
6
6
|
## Installation
|
7
7
|
|
@@ -35,6 +35,21 @@ default: &default
|
|
35
35
|
replica_name: '{replica}' # replica macros name, optional for creating replicated tables
|
36
36
|
```
|
37
37
|
|
38
|
+
Alternatively if you wish to pass a custom `Net::HTTP` transport (or any other
|
39
|
+
object which supports a `.post()` function with the same parameters as
|
40
|
+
`Net::HTTP`'s), you can do this directly instead of specifying
|
41
|
+
`host`/`port`/`ssl`:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
class ActionView < ActiveRecord::Base
|
45
|
+
establish_connection(
|
46
|
+
adapter: 'clickhouse',
|
47
|
+
database: 'database',
|
48
|
+
connection: Net::HTTP.start('http://example.org', 8123)
|
49
|
+
)
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
38
53
|
## Usage in Rails 5
|
39
54
|
|
40
55
|
Add your `database.yml` connection information with postfix `_clickhouse` for you environment:
|
@@ -162,6 +177,44 @@ ActionView.maximum(:date)
|
|
162
177
|
#=> 'Wed, 29 Nov 2017'
|
163
178
|
```
|
164
179
|
|
180
|
+
|
181
|
+
### Migration Data Types
|
182
|
+
|
183
|
+
Integer types are unsigned by default. Specify signed values with `:unsigned =>
|
184
|
+
false`. The default integer is `UInt32`
|
185
|
+
|
186
|
+
| Type (bit size) | Range | :limit (byte size) |
|
187
|
+
| :--- | :----: | ---: |
|
188
|
+
| Int8 | -128 to 127 | 1 |
|
189
|
+
| Int16 | -32768 to 32767 | 2 |
|
190
|
+
| Int32 | -2147483648 to 2,147,483,647 | 3,4 |
|
191
|
+
| Int64 | -9223372036854775808 to 9223372036854775807] | 5,6,7,8 |
|
192
|
+
| Int128 | ... | 9 - 15 |
|
193
|
+
| Int256 | ... | 16+ |
|
194
|
+
| UInt8 | 0 to 255 | 1 |
|
195
|
+
| UInt16 | 0 to 65,535 | 2 |
|
196
|
+
| UInt32 | 0 to 4,294,967,295 | 3,4 |
|
197
|
+
| UInt64 | 0 to 18446744073709551615 | 5,6,7,8 |
|
198
|
+
| UInt256 | 0 to ... | 8+ |
|
199
|
+
|
200
|
+
Example:
|
201
|
+
|
202
|
+
``` ruby
|
203
|
+
class CreateDataItems < ActiveRecord::Migration
|
204
|
+
def change
|
205
|
+
create_table "data_items", id: false, options: "VersionedCollapsingMergeTree(sign, version) PARTITION BY toYYYYMM(day) ORDER BY category", force: :cascade do |t|
|
206
|
+
t.date "day", null: false
|
207
|
+
t.string "category", null: false
|
208
|
+
t.integer "value_in", null: false
|
209
|
+
t.integer "sign", limit: 1, unsigned: false, default: -> { "CAST(1, 'Int8')" }, null: false
|
210
|
+
t.integer "version", limit: 8, default: -> { "CAST(toUnixTimestamp(now()), 'UInt64')" }, null: false
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
```
|
216
|
+
|
217
|
+
|
165
218
|
### Using replica and cluster params in connection parameters
|
166
219
|
|
167
220
|
```yml
|
@@ -1,9 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
begin
|
3
|
+
require "active_record/connection_adapters/deduplicable"
|
4
|
+
rescue LoadError => e
|
5
|
+
# Rails < 6.1 does not have this file in this location, ignore
|
6
|
+
end
|
7
|
+
|
8
|
+
require "active_record/connection_adapters/abstract/schema_creation"
|
2
9
|
|
3
10
|
module ActiveRecord
|
4
11
|
module ConnectionAdapters
|
5
12
|
module Clickhouse
|
6
|
-
class SchemaCreation <
|
13
|
+
class SchemaCreation < ConnectionAdapters::SchemaCreation# :nodoc:
|
7
14
|
|
8
15
|
def visit_AddColumnDefinition(o)
|
9
16
|
sql = +"ADD COLUMN #{accept(o.column)}"
|
@@ -21,8 +28,14 @@ module ActiveRecord
|
|
21
28
|
end
|
22
29
|
|
23
30
|
def add_table_options!(create_sql, options)
|
24
|
-
|
25
|
-
|
31
|
+
opts = options[:options]
|
32
|
+
if options.respond_to?(:options)
|
33
|
+
# rails 6.1
|
34
|
+
opts ||= options.options
|
35
|
+
end
|
36
|
+
|
37
|
+
if opts.present?
|
38
|
+
create_sql << " ENGINE = #{opts}"
|
26
39
|
else
|
27
40
|
create_sql << " ENGINE = Log()"
|
28
41
|
end
|
@@ -37,9 +50,9 @@ module ActiveRecord
|
|
37
50
|
|
38
51
|
statements = o.columns.map { |c| accept c }
|
39
52
|
statements << accept(o.primary_keys) if o.primary_keys
|
40
|
-
|
41
53
|
create_sql << "(#{statements.join(', ')})" if statements.present?
|
42
|
-
|
54
|
+
# Attach options for only table or materialized view
|
55
|
+
add_table_options!(create_sql, o) if !o.view || o.view && o.materialized
|
43
56
|
create_sql << " AS #{to_sql(o.as)}" if o.as
|
44
57
|
create_sql
|
45
58
|
end
|
@@ -35,13 +35,31 @@ module ActiveRecord
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def integer(*args, **options)
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
# default to unsigned
|
39
|
+
unsigned = options[:unsigned]
|
40
|
+
unsigned = true if unsigned.nil?
|
41
|
+
|
42
|
+
kind = :uint32 # default
|
43
|
+
|
44
|
+
if options[:limit]
|
45
|
+
if unsigned
|
46
|
+
kind = :uint8 if options[:limit] == 1
|
47
|
+
kind = :uint16 if options[:limit] == 2
|
48
|
+
kind = :uint32 if [3,4].include?(options[:limit])
|
49
|
+
kind = :uint64 if [5,6,7].include?(options[:limit])
|
50
|
+
kind = :big_integer if options[:limit] == 8
|
51
|
+
kind = :uint256 if options[:limit] > 8
|
52
|
+
else
|
53
|
+
kind = :int8 if options[:limit] == 1
|
54
|
+
kind = :int16 if options[:limit] == 2
|
55
|
+
kind = :int32 if [3,4].include?(options[:limit])
|
56
|
+
kind = :int64 if options[:limit] > 5 && options[:limit] <= 8
|
57
|
+
kind = :int128 if options[:limit] > 8 && options[:limit] <= 16
|
58
|
+
kind = :int256 if options[:limit] > 16
|
59
|
+
end
|
42
60
|
end
|
61
|
+
args.each { |name| column(name, kind, options.except(:limit, :unsigned)) }
|
43
62
|
end
|
44
|
-
|
45
63
|
end
|
46
64
|
end
|
47
65
|
end
|
@@ -17,8 +17,10 @@ module ActiveRecord
|
|
17
17
|
def exec_query(sql, name = nil, binds = [], prepare: false)
|
18
18
|
result = do_execute(sql, name)
|
19
19
|
ActiveRecord::Result.new(result['meta'].map { |m| m['name'] }, result['data'])
|
20
|
-
rescue
|
21
|
-
raise
|
20
|
+
rescue ActiveRecord::ActiveRecordError => e
|
21
|
+
raise e
|
22
|
+
rescue StandardError => e
|
23
|
+
raise ActiveRecord::ActiveRecordError, "Response: #{e.message}"
|
22
24
|
end
|
23
25
|
|
24
26
|
def exec_update(_sql, _name = nil, _binds = [])
|
@@ -37,7 +39,7 @@ module ActiveRecord
|
|
37
39
|
|
38
40
|
def table_options(table)
|
39
41
|
sql = show_create_table(table)
|
40
|
-
{ options: sql.gsub(/^(?:.*?)ENGINE = (.*?)
|
42
|
+
{ options: sql.gsub(/^(?:.*?)(?:ENGINE = (.*?))?( AS SELECT .*?)?$/, '\\1').presence, as: sql.match(/^CREATE (?:.*?) AS (SELECT .*?)$/).try(:[], 1) }.compact
|
41
43
|
end
|
42
44
|
|
43
45
|
# Not indexes on clickhouse
|
@@ -114,8 +116,8 @@ module ActiveRecord
|
|
114
116
|
Clickhouse::SchemaCreation.new(self)
|
115
117
|
end
|
116
118
|
|
117
|
-
def create_table_definition(
|
118
|
-
Clickhouse::TableDefinition.new(self,
|
119
|
+
def create_table_definition(table_name, options)
|
120
|
+
Clickhouse::TableDefinition.new(self, table_name, **options)
|
119
121
|
end
|
120
122
|
|
121
123
|
def new_column_from_field(table_name, field)
|
@@ -17,9 +17,18 @@ module ActiveRecord
|
|
17
17
|
# Establishes a connection to the database that's used by all Active Record objects
|
18
18
|
def clickhouse_connection(config)
|
19
19
|
config = config.symbolize_keys
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
if config[:connection]
|
21
|
+
connection = {
|
22
|
+
connection: config[:connection]
|
23
|
+
}
|
24
|
+
else
|
25
|
+
port = config[:port] || 8123
|
26
|
+
connection = {
|
27
|
+
host: config[:host] || 'localhost',
|
28
|
+
port: port,
|
29
|
+
ssl: config[:ssl].present? ? config[:ssl] : port == 443,
|
30
|
+
}
|
31
|
+
end
|
23
32
|
|
24
33
|
if config.key?(:database)
|
25
34
|
database = config[:database]
|
@@ -27,7 +36,7 @@ module ActiveRecord
|
|
27
36
|
raise ArgumentError, 'No database specified. Missing argument: database.'
|
28
37
|
end
|
29
38
|
|
30
|
-
ConnectionAdapters::ClickhouseAdapter.new(logger,
|
39
|
+
ConnectionAdapters::ClickhouseAdapter.new(logger, connection, { user: config[:username], password: config[:password], database: database }.compact, config)
|
31
40
|
end
|
32
41
|
end
|
33
42
|
end
|
@@ -50,7 +59,11 @@ module ActiveRecord
|
|
50
59
|
module TypeCaster
|
51
60
|
class Map
|
52
61
|
def is_view
|
53
|
-
|
62
|
+
if @klass.respond_to?(:is_view)
|
63
|
+
@klass.is_view # rails 6.1
|
64
|
+
else
|
65
|
+
types.is_view # less than 6.1
|
66
|
+
end
|
54
67
|
end
|
55
68
|
end
|
56
69
|
end
|
@@ -79,7 +92,6 @@ module ActiveRecord
|
|
79
92
|
|
80
93
|
class ClickhouseAdapter < AbstractAdapter
|
81
94
|
ADAPTER_NAME = 'Clickhouse'.freeze
|
82
|
-
|
83
95
|
NATIVE_DATABASE_TYPES = {
|
84
96
|
string: { name: 'String' },
|
85
97
|
integer: { name: 'UInt32' },
|
@@ -88,7 +100,21 @@ module ActiveRecord
|
|
88
100
|
decimal: { name: 'Decimal' },
|
89
101
|
datetime: { name: 'DateTime' },
|
90
102
|
date: { name: 'Date' },
|
91
|
-
boolean: { name: 'UInt8' }
|
103
|
+
boolean: { name: 'UInt8' },
|
104
|
+
|
105
|
+
int8: { name: 'Int8' },
|
106
|
+
int16: { name: 'Int16' },
|
107
|
+
int32: { name: 'Int32' },
|
108
|
+
int64: { name: 'Int64' },
|
109
|
+
int128: { name: 'Int128' },
|
110
|
+
int256: { name: 'Int256' },
|
111
|
+
|
112
|
+
uint8: { name: 'UInt8' },
|
113
|
+
uint16: { name: 'UInt16' },
|
114
|
+
uint32: { name: 'UInt32' },
|
115
|
+
uint64: { name: 'UInt64' },
|
116
|
+
# uint128: { name: 'UInt128' }, not yet implemented in clickhouse
|
117
|
+
uint256: { name: 'UInt256' },
|
92
118
|
}.freeze
|
93
119
|
|
94
120
|
include Clickhouse::SchemaStatements
|
@@ -139,10 +165,12 @@ module ActiveRecord
|
|
139
165
|
when /(Nullable)?\(?String\)?/
|
140
166
|
super('String')
|
141
167
|
when /(Nullable)?\(?U?Int8\)?/
|
142
|
-
|
143
|
-
when /(Nullable)?\(?U?
|
144
|
-
|
145
|
-
when /(Nullable)?\(?U?
|
168
|
+
1
|
169
|
+
when /(Nullable)?\(?U?Int16\)?/
|
170
|
+
2
|
171
|
+
when /(Nullable)?\(?U?Int32\)?/
|
172
|
+
nil
|
173
|
+
when /(Nullable)?\(?U?Int64\)?/
|
146
174
|
8
|
147
175
|
else
|
148
176
|
super
|
@@ -154,14 +182,20 @@ module ActiveRecord
|
|
154
182
|
register_class_with_limit m, %r(String), Type::String
|
155
183
|
register_class_with_limit m, 'Date', Clickhouse::OID::Date
|
156
184
|
register_class_with_limit m, 'DateTime', Clickhouse::OID::DateTime
|
157
|
-
|
158
|
-
m.alias_type 'UInt16', 'UInt8'
|
159
|
-
m.alias_type 'UInt32', 'UInt8'
|
160
|
-
register_class_with_limit m, %r(UInt64), Type::UnsignedInteger
|
185
|
+
|
161
186
|
register_class_with_limit m, %r(Int8), Type::Integer
|
162
|
-
m
|
163
|
-
m
|
187
|
+
register_class_with_limit m, %r(Int16), Type::Integer
|
188
|
+
register_class_with_limit m, %r(Int32), Type::Integer
|
164
189
|
register_class_with_limit m, %r(Int64), Type::Integer
|
190
|
+
register_class_with_limit m, %r(Int128), Type::Integer
|
191
|
+
register_class_with_limit m, %r(Int256), Type::Integer
|
192
|
+
|
193
|
+
register_class_with_limit m, %r(Uint8), Type::UnsignedInteger
|
194
|
+
register_class_with_limit m, %r(UInt16), Type::UnsignedInteger
|
195
|
+
register_class_with_limit m, %r(UInt32), Type::UnsignedInteger
|
196
|
+
register_class_with_limit m, %r(UInt64), Type::UnsignedInteger
|
197
|
+
#register_class_with_limit m, %r(UInt128), Type::UnsignedInteger #not implemnted in clickhouse
|
198
|
+
register_class_with_limit m, %r(UInt256), Type::UnsignedInteger
|
165
199
|
end
|
166
200
|
|
167
201
|
# Quoting time without microseconds
|
@@ -304,7 +338,7 @@ module ActiveRecord
|
|
304
338
|
private
|
305
339
|
|
306
340
|
def connect
|
307
|
-
@connection = Net::HTTP.start(@connection_parameters[
|
341
|
+
@connection = @connection_parameters[:connection] || Net::HTTP.start(@connection_parameters[:host], @connection_parameters[:port], use_ssl: @connection_parameters[:ssl], verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
308
342
|
end
|
309
343
|
|
310
344
|
def apply_replica(table, options)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_record/migration'
|
2
|
+
|
1
3
|
module ClickhouseActiverecord
|
2
4
|
|
3
5
|
class SchemaMigration < ::ActiveRecord::SchemaMigration
|
@@ -8,7 +10,7 @@ module ClickhouseActiverecord
|
|
8
10
|
version_options = connection.internal_string_options_for_primary_key
|
9
11
|
|
10
12
|
connection.create_table(table_name, id: false, options: 'ReplacingMergeTree(ver) PARTITION BY version ORDER BY (version)', if_not_exists: true) do |t|
|
11
|
-
t.string :version, version_options
|
13
|
+
t.string :version, **version_options
|
12
14
|
t.column :active, 'Int8', null: false, default: '1'
|
13
15
|
t.datetime :ver, null: false, default: -> { 'now()' }
|
14
16
|
end
|
@@ -27,7 +29,7 @@ module ClickhouseActiverecord
|
|
27
29
|
unless table_exists?
|
28
30
|
key_options = connection.internal_string_options_for_primary_key
|
29
31
|
|
30
|
-
connection.create_table(table_name, id: false, options: 'MergeTree() PARTITION BY toDate(created_at) ORDER BY (created_at)', if_not_exists: true) do |t|
|
32
|
+
connection.create_table(table_name, id: false, options: connection.adapter_name.downcase == 'clickhouse' ? 'MergeTree() PARTITION BY toDate(created_at) ORDER BY (created_at)' : '', if_not_exists: true) do |t|
|
31
33
|
t.string :key, key_options
|
32
34
|
t.string :value
|
33
35
|
t.timestamps
|
@@ -34,7 +34,7 @@ HEADER
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def tables(stream)
|
37
|
-
sorted_tables = @connection.tables.sort {|a,b| @connection.show_create_table(a).match(/^CREATE\s+(MATERIALIZED
|
37
|
+
sorted_tables = @connection.tables.sort {|a,b| @connection.show_create_table(a).match(/^CREATE\s+(MATERIALIZED\s+)?VIEW/) ? 1 : a <=> b }
|
38
38
|
|
39
39
|
sorted_tables.each do |table_name|
|
40
40
|
table(table_name, stream) unless ignored?(table_name)
|
@@ -50,7 +50,7 @@ HEADER
|
|
50
50
|
# super(table.gsub(/^\.inner\./, ''), stream)
|
51
51
|
|
52
52
|
# detect view table
|
53
|
-
match = sql.match(/^CREATE\s+(MATERIALIZED
|
53
|
+
match = sql.match(/^CREATE\s+(MATERIALIZED\s+)?VIEW/)
|
54
54
|
end
|
55
55
|
|
56
56
|
# Copy from original dumper
|
@@ -133,5 +133,21 @@ HEADER
|
|
133
133
|
super
|
134
134
|
end
|
135
135
|
end
|
136
|
+
|
137
|
+
def schema_limit(column)
|
138
|
+
return nil if column.type == :float
|
139
|
+
super
|
140
|
+
end
|
141
|
+
|
142
|
+
def schema_unsigned(column)
|
143
|
+
return nil unless column.type == :integer && !simple
|
144
|
+
(column.sql_type =~ /(Nullable)?\(?UInt\d+\)?/).nil? ? false : nil
|
145
|
+
end
|
146
|
+
|
147
|
+
def prepare_column_options(column)
|
148
|
+
spec = {}
|
149
|
+
spec[:unsigned] = schema_unsigned(column)
|
150
|
+
spec.merge(super).compact
|
151
|
+
end
|
136
152
|
end
|
137
153
|
end
|
@@ -6,7 +6,7 @@ module ClickhouseActiverecord
|
|
6
6
|
delegate :connection, :establish_connection, :clear_active_connections!, to: ActiveRecord::Base
|
7
7
|
|
8
8
|
def initialize(configuration)
|
9
|
-
@configuration = configuration
|
9
|
+
@configuration = configuration.with_indifferent_access
|
10
10
|
end
|
11
11
|
|
12
12
|
def create
|
@@ -13,7 +13,7 @@ class ClickhouseMigrationGenerator < ActiveRecord::Generators::MigrationGenerato
|
|
13
13
|
|
14
14
|
def db_migrate_path
|
15
15
|
if defined?(Rails.application) && Rails.application && respond_to?(:configured_migrate_path, true)
|
16
|
-
configured_migrate_path
|
16
|
+
configured_migrate_path || default_migrate_path
|
17
17
|
else
|
18
18
|
default_migrate_path
|
19
19
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clickhouse-activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergey Odintsov
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -134,7 +134,7 @@ homepage: https://github.com/pnixx/clickhouse-activerecord
|
|
134
134
|
licenses:
|
135
135
|
- MIT
|
136
136
|
metadata: {}
|
137
|
-
post_install_message:
|
137
|
+
post_install_message:
|
138
138
|
rdoc_options: []
|
139
139
|
require_paths:
|
140
140
|
- lib
|
@@ -149,8 +149,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
149
|
- !ruby/object:Gem::Version
|
150
150
|
version: '0'
|
151
151
|
requirements: []
|
152
|
-
rubygems_version: 3.0.
|
153
|
-
signing_key:
|
152
|
+
rubygems_version: 3.0.3
|
153
|
+
signing_key:
|
154
154
|
specification_version: 4
|
155
155
|
summary: ClickHouse ActiveRecord
|
156
156
|
test_files: []
|