clickhouse-activerecord 0.5.2 → 0.5.8
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 +12 -0
- data/README.md +1 -0
- data/clickhouse-activerecord.gemspec +1 -1
- data/core_extensions/active_record/migration/command_recorder.rb +18 -0
- data/lib/active_record/connection_adapters/clickhouse/schema_creation.rb +46 -3
- data/lib/active_record/connection_adapters/clickhouse/schema_definitions.rb +36 -2
- data/lib/active_record/connection_adapters/clickhouse/schema_statements.rb +5 -3
- data/lib/active_record/connection_adapters/clickhouse_adapter.rb +87 -23
- data/lib/clickhouse-activerecord/migration.rb +48 -16
- data/lib/clickhouse-activerecord/tasks.rb +10 -2
- data/lib/clickhouse-activerecord/version.rb +1 -1
- data/lib/clickhouse-activerecord.rb +3 -0
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8f8d01291f12197d0b5d0b8f791631fe144cdc5d855de9dd9c8498e170fafdf
|
4
|
+
data.tar.gz: 2ebd5b6068a179a7c87679db0fe9c34bbe2f9197c6230da9aad1a6935fc9c7d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94abbef81ff0000ecbc05092dd3558dc90e53223fd0025c5a57549f4b5f98431a01ee9fceee5587887c9fa6fcc3411420e936ad942150caa8edc5146c7db54df
|
7
|
+
data.tar.gz: '03871bfe2bec394c9612928229cc3380615acd795b25c058072a3aec62a7852e06711f2811286438ab278c838d4ed65736bd47ae449bc0ca5bbad6763692a927'
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
### Version 0.5.6 (Oct 25, 2021)
|
2
|
+
|
3
|
+
* Added auto creating service distributed tables and additional options for creating view [@ygreeek](https://github.com/ygreeek)
|
4
|
+
* Added default user agent
|
5
|
+
|
6
|
+
### Version 0.5.3 (Sep 22, 2021)
|
7
|
+
|
8
|
+
* Fix replica cluster for a new syntax MergeTree
|
9
|
+
* Fix support rails 5.2 on alter table
|
10
|
+
* Support array type of column
|
11
|
+
* Support Rails 6.1.0 [@bdevel](https://github.com/bdevel)
|
12
|
+
|
1
13
|
### Version 0.4.10 (Mar 10, 2021)
|
2
14
|
|
3
15
|
* Support ClickHouse 20.9+
|
data/README.md
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_runtime_dependency 'bundler', '>= 1.13.4'
|
27
27
|
spec.add_runtime_dependency 'activerecord', '>= 5.2'
|
28
28
|
|
29
|
-
spec.add_development_dependency 'bundler', '
|
29
|
+
spec.add_development_dependency 'bundler', '>= 1.15'
|
30
30
|
spec.add_development_dependency 'rake', '~> 13.0'
|
31
31
|
spec.add_development_dependency 'rspec', '~> 3.4'
|
32
32
|
spec.add_development_dependency 'pry', '~> 0.12'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module CoreExtensions
|
2
|
+
module ActiveRecord
|
3
|
+
module Migration
|
4
|
+
module CommandRecorder
|
5
|
+
def create_view(*args, &block)
|
6
|
+
record(:create_view, args, &block)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def invert_create_view(args)
|
12
|
+
view_name, options = args
|
13
|
+
[:drop_table, view_name, options]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -19,9 +19,18 @@ module ActiveRecord
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def add_column_options!(sql, options)
|
22
|
+
if options[:value]
|
23
|
+
sql.gsub!(/\s+(.*)/, " \\1(#{options[:value]})")
|
24
|
+
end
|
25
|
+
if options[:fixed_string]
|
26
|
+
sql.gsub!(/\s+(.*)/, " FixedString(#{options[:fixed_string]})")
|
27
|
+
end
|
22
28
|
if options[:null] || options[:null].nil?
|
23
29
|
sql.gsub!(/\s+(.*)/, ' Nullable(\1)')
|
24
30
|
end
|
31
|
+
if options[:low_cardinality]
|
32
|
+
sql.gsub!(/\s+(.*)/, ' LowCardinality(\1)')
|
33
|
+
end
|
25
34
|
if options[:array]
|
26
35
|
sql.gsub!(/\s+(.*)/, ' Array(\1)')
|
27
36
|
end
|
@@ -46,17 +55,48 @@ module ActiveRecord
|
|
46
55
|
create_sql
|
47
56
|
end
|
48
57
|
|
58
|
+
def add_as_clause!(create_sql, options)
|
59
|
+
return unless options.as
|
60
|
+
|
61
|
+
assign_database_to_subquery!(options.as) if options.view
|
62
|
+
create_sql << " AS #{to_sql(options.as)}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def assign_database_to_subquery!(subquery)
|
66
|
+
# If you do not specify a database explicitly, ClickHouse will use the "default" database.
|
67
|
+
return unless subquery
|
68
|
+
|
69
|
+
match = subquery.match(/(?<=from)[^.\w]+(?<database>\w+(?=\.))?(?<table_name>[.\w]+)/i)
|
70
|
+
return unless match
|
71
|
+
return if match[:database]
|
72
|
+
|
73
|
+
subquery[match.begin(:table_name)...match.end(:table_name)] =
|
74
|
+
"#{current_database}.#{match[:table_name].sub('.', '')}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_to_clause!(create_sql, options)
|
78
|
+
# If you do not specify a database explicitly, ClickHouse will use the "default" database.
|
79
|
+
return unless options.to
|
80
|
+
|
81
|
+
match = options.to.match(/(?<database>.+(?=\.))?(?<table_name>.+)/i)
|
82
|
+
return unless match
|
83
|
+
return if match[:database]
|
84
|
+
|
85
|
+
create_sql << "TO #{current_database}.#{match[:table_name].sub('.', '')}"
|
86
|
+
end
|
87
|
+
|
49
88
|
def visit_TableDefinition(o)
|
50
89
|
create_sql = +"CREATE#{table_modifier_in_create(o)} #{o.view ? "VIEW" : "TABLE"} "
|
51
90
|
create_sql << "IF NOT EXISTS " if o.if_not_exists
|
52
91
|
create_sql << "#{quote_table_name(o.name)} "
|
92
|
+
add_to_clause!(create_sql, o) if o.materialized
|
53
93
|
|
54
94
|
statements = o.columns.map { |c| accept c }
|
55
95
|
statements << accept(o.primary_keys) if o.primary_keys
|
56
96
|
create_sql << "(#{statements.join(', ')})" if statements.present?
|
57
|
-
# Attach options for only table or materialized view
|
58
|
-
add_table_options!(create_sql, o)
|
59
|
-
create_sql
|
97
|
+
# Attach options for only table or materialized view without TO section
|
98
|
+
add_table_options!(create_sql, o) if !o.view || o.view && o.materialized && !o.to
|
99
|
+
add_as_clause!(create_sql, o)
|
60
100
|
create_sql
|
61
101
|
end
|
62
102
|
|
@@ -84,6 +124,9 @@ module ActiveRecord
|
|
84
124
|
change_column_sql
|
85
125
|
end
|
86
126
|
|
127
|
+
def current_database
|
128
|
+
ActiveRecord::Base.connection_db_config.database
|
129
|
+
end
|
87
130
|
end
|
88
131
|
end
|
89
132
|
end
|
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
module Clickhouse
|
6
6
|
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
7
7
|
|
8
|
-
attr_reader :view, :materialized, :if_not_exists
|
8
|
+
attr_reader :view, :materialized, :if_not_exists, :to
|
9
9
|
|
10
10
|
def initialize(
|
11
11
|
conn,
|
@@ -17,6 +17,7 @@ module ActiveRecord
|
|
17
17
|
comment: nil,
|
18
18
|
view: false,
|
19
19
|
materialized: false,
|
20
|
+
to: nil,
|
20
21
|
**
|
21
22
|
)
|
22
23
|
@conn = conn
|
@@ -32,6 +33,7 @@ module ActiveRecord
|
|
32
33
|
@comment = comment
|
33
34
|
@view = view || materialized
|
34
35
|
@materialized = materialized
|
36
|
+
@to = to
|
35
37
|
end
|
36
38
|
|
37
39
|
def integer(*args, **options)
|
@@ -58,7 +60,39 @@ module ActiveRecord
|
|
58
60
|
kind = :int256 if options[:limit] > 16
|
59
61
|
end
|
60
62
|
end
|
61
|
-
args.each { |name| column(name, kind, options.except(:limit, :unsigned)) }
|
63
|
+
args.each { |name| column(name, kind, **options.except(:limit, :unsigned)) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def datetime(*args, **options)
|
67
|
+
kind = :datetime
|
68
|
+
|
69
|
+
if options[:precision]
|
70
|
+
kind = :datetime64
|
71
|
+
options[:value] = options[:precision]
|
72
|
+
end
|
73
|
+
|
74
|
+
args.each { |name| column(name, kind, **options.except(:precision)) }
|
75
|
+
end
|
76
|
+
|
77
|
+
def uuid(*args, **options)
|
78
|
+
args.each { |name| column(name, :uuid, **options) }
|
79
|
+
end
|
80
|
+
|
81
|
+
def enum(*args, **options)
|
82
|
+
kind = :enum8
|
83
|
+
|
84
|
+
unless options[:value].is_a? Hash
|
85
|
+
raise ArgumentError, "Column #{args.first}: option 'value' must be Hash, got: #{options[:value].class}"
|
86
|
+
end
|
87
|
+
|
88
|
+
options[:value] = options[:value].each_with_object([]) { |(k, v), arr| arr.push("'#{k}' = #{v}") }.join(', ')
|
89
|
+
|
90
|
+
if options[:limit]
|
91
|
+
kind = :enum8 if options[:limit] == 1
|
92
|
+
kind = :enum16 if options[:limit] == 2
|
93
|
+
end
|
94
|
+
|
95
|
+
args.each { |name| column(name, kind, **options.except(:limit)) }
|
62
96
|
end
|
63
97
|
end
|
64
98
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'clickhouse-activerecord/version'
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module ConnectionAdapters
|
5
7
|
module Clickhouse
|
@@ -37,7 +39,7 @@ module ActiveRecord
|
|
37
39
|
end
|
38
40
|
|
39
41
|
def tables(name = nil)
|
40
|
-
result = do_system_execute(
|
42
|
+
result = do_system_execute("SHOW TABLES WHERE name NOT LIKE '.inner_id.%'", name)
|
41
43
|
return [] if result.nil?
|
42
44
|
result['data'].flatten
|
43
45
|
end
|
@@ -58,7 +60,7 @@ module ActiveRecord
|
|
58
60
|
|
59
61
|
def do_system_execute(sql, name = nil)
|
60
62
|
log_with_debug(sql, "#{adapter_name} #{name}") do
|
61
|
-
res = @connection.post("/?#{@config.to_param}", "#{sql} FORMAT JSONCompact")
|
63
|
+
res = @connection.post("/?#{@config.to_param}", "#{sql} FORMAT JSONCompact", 'User-Agent' => "Clickhouse ActiveRecord #{ClickhouseActiverecord::VERSION}")
|
62
64
|
|
63
65
|
process_response(res)
|
64
66
|
end
|
@@ -68,7 +70,7 @@ module ActiveRecord
|
|
68
70
|
log(sql, "#{adapter_name} #{name}") do
|
69
71
|
formatted_sql = apply_format(sql, format)
|
70
72
|
request_params = @config || {}
|
71
|
-
res = @connection.post("/?#{request_params.merge(settings).to_param}", formatted_sql)
|
73
|
+
res = @connection.post("/?#{request_params.merge(settings).to_param}", formatted_sql, 'User-Agent' => "Clickhouse ActiveRecord #{ClickhouseActiverecord::VERSION}")
|
72
74
|
|
73
75
|
process_response(res)
|
74
76
|
end
|
@@ -46,20 +46,18 @@ module ActiveRecord
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
# Replace for only ClickhouseAdapter
|
49
|
+
module ClickhouseRelationReverseOrder
|
52
50
|
def reverse_order!
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
51
|
+
return super unless connection.is_a?(ConnectionAdapters::ClickhouseAdapter)
|
52
|
+
|
53
|
+
orders = order_values.uniq.compact_blank
|
54
|
+
return super unless orders.empty? && !primary_key
|
55
|
+
|
56
|
+
self.order_values = %w(date created_at).select {|c| column_names.include?(c) }.map{|c| arel_attribute(c).desc }
|
60
57
|
self
|
61
58
|
end
|
62
59
|
end
|
60
|
+
Relation.prepend(ClickhouseRelationReverseOrder)
|
63
61
|
|
64
62
|
module TypeCaster
|
65
63
|
class Map
|
@@ -82,13 +80,19 @@ module ActiveRecord
|
|
82
80
|
def is_view=(value)
|
83
81
|
@is_view = value
|
84
82
|
end
|
83
|
+
end
|
84
|
+
end
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
86
|
+
ActiveRecord::Core::ClassMethods.module_eval do
|
87
|
+
def arel_table
|
88
|
+
@arel_table ||=
|
89
|
+
if self.connection.is_a?(ConnectionAdapters::ClickhouseAdapter)
|
90
|
+
ClickhouseActiverecord::Arel::Table.new(table_name, type_caster: type_caster)
|
91
|
+
else
|
92
|
+
Arel::Table.new(table_name, klass: self)
|
93
|
+
end
|
90
94
|
end
|
91
|
-
|
95
|
+
end
|
92
96
|
|
93
97
|
module ConnectionAdapters
|
94
98
|
class ClickhouseColumn < Column
|
@@ -104,8 +108,13 @@ module ActiveRecord
|
|
104
108
|
float: { name: 'Float32' },
|
105
109
|
decimal: { name: 'Decimal' },
|
106
110
|
datetime: { name: 'DateTime' },
|
111
|
+
datetime64: { name: 'DateTime64' },
|
107
112
|
date: { name: 'Date' },
|
108
113
|
boolean: { name: 'UInt8' },
|
114
|
+
uuid: { name: 'UUID' },
|
115
|
+
|
116
|
+
enum8: { name: 'Enum8' },
|
117
|
+
enum16: { name: 'Enum16' },
|
109
118
|
|
110
119
|
int8: { name: 'Int8' },
|
111
120
|
int16: { name: 'Int16' },
|
@@ -182,6 +191,20 @@ module ActiveRecord
|
|
182
191
|
end
|
183
192
|
end
|
184
193
|
|
194
|
+
# `extract_scale` and `extract_precision` are the same as in the Rails abstract base class,
|
195
|
+
# except this permits a space after the comma
|
196
|
+
|
197
|
+
def extract_scale(sql_type)
|
198
|
+
case sql_type
|
199
|
+
when /\((\d+)\)/ then 0
|
200
|
+
when /\((\d+)(,\s?(\d+))\)/ then $3.to_i
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def extract_precision(sql_type)
|
205
|
+
$1.to_i if sql_type =~ /\((\d+)(,\s?\d+)?\)/
|
206
|
+
end
|
207
|
+
|
185
208
|
def initialize_type_map(m) # :nodoc:
|
186
209
|
super
|
187
210
|
register_class_with_limit m, %r(String), Type::String
|
@@ -262,7 +285,7 @@ module ActiveRecord
|
|
262
285
|
def create_view(table_name, **options)
|
263
286
|
options.merge!(view: true)
|
264
287
|
options = apply_replica(table_name, options)
|
265
|
-
td = create_table_definition(apply_cluster(table_name), options)
|
288
|
+
td = create_table_definition(apply_cluster(table_name), **options)
|
266
289
|
yield td if block_given?
|
267
290
|
|
268
291
|
if options[:force]
|
@@ -272,16 +295,26 @@ module ActiveRecord
|
|
272
295
|
execute schema_creation.accept td
|
273
296
|
end
|
274
297
|
|
275
|
-
def create_table(table_name, **options)
|
298
|
+
def create_table(table_name, **options, &block)
|
276
299
|
options = apply_replica(table_name, options)
|
277
|
-
td = create_table_definition(apply_cluster(table_name), options)
|
278
|
-
|
300
|
+
td = create_table_definition(apply_cluster(table_name), **options)
|
301
|
+
block.call td if block_given?
|
279
302
|
|
280
303
|
if options[:force]
|
281
304
|
drop_table(table_name, options.merge(if_exists: true))
|
282
305
|
end
|
283
306
|
|
284
307
|
execute schema_creation.accept td
|
308
|
+
|
309
|
+
if options[:with_distributed]
|
310
|
+
distributed_table_name = options.delete(:with_distributed)
|
311
|
+
sharding_key = options.delete(:sharding_key) || 'rand()'
|
312
|
+
raise 'Set a cluster' unless cluster
|
313
|
+
|
314
|
+
distributed_options =
|
315
|
+
"Distributed(#{cluster}, #{@config[:database]}, #{table_name}, #{sharding_key})"
|
316
|
+
create_table(distributed_table_name, **options.merge(options: distributed_options), &block)
|
317
|
+
end
|
285
318
|
end
|
286
319
|
|
287
320
|
# Drops a ClickHouse database.
|
@@ -299,6 +332,11 @@ module ActiveRecord
|
|
299
332
|
|
300
333
|
def drop_table(table_name, options = {}) # :nodoc:
|
301
334
|
do_execute apply_cluster "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}"
|
335
|
+
|
336
|
+
if options[:with_distributed]
|
337
|
+
distributed_table_name = options.delete(:with_distributed)
|
338
|
+
drop_table(distributed_table_name, **options)
|
339
|
+
end
|
302
340
|
end
|
303
341
|
|
304
342
|
def change_column(table_name, column_name, type, options = {})
|
@@ -324,10 +362,24 @@ module ActiveRecord
|
|
324
362
|
@full_config[:replica_name]
|
325
363
|
end
|
326
364
|
|
365
|
+
def use_default_replicated_merge_tree_params?
|
366
|
+
database_engine_atomic? && @full_config[:use_default_replicated_merge_tree_params]
|
367
|
+
end
|
368
|
+
|
369
|
+
def use_replica?
|
370
|
+
(replica || use_default_replicated_merge_tree_params?) && cluster
|
371
|
+
end
|
372
|
+
|
327
373
|
def replica_path(table)
|
328
374
|
"/clickhouse/tables/#{cluster}/#{@config[:database]}.#{table}"
|
329
375
|
end
|
330
376
|
|
377
|
+
def database_engine_atomic?
|
378
|
+
current_database_engine = "select engine from system.databases where name = '#{@config[:database]}'"
|
379
|
+
res = ActiveRecord::Base.connection.select_one(current_database_engine)
|
380
|
+
res['engine'] == 'Atomic' if res
|
381
|
+
end
|
382
|
+
|
331
383
|
def apply_cluster(sql)
|
332
384
|
cluster ? "#{sql} ON CLUSTER #{cluster}" : sql
|
333
385
|
end
|
@@ -370,14 +422,26 @@ module ActiveRecord
|
|
370
422
|
end
|
371
423
|
|
372
424
|
def apply_replica(table, options)
|
373
|
-
if
|
374
|
-
|
375
|
-
|
376
|
-
options[:options] = "Replicated#{match[1]}(#{([replica_path(table), replica].map{|v| "'#{v}'"} + [match[2].presence]).compact.join(', ')})#{match[3]}"
|
425
|
+
if use_replica? && options[:options]
|
426
|
+
if options[:options].match(/^Replicated/)
|
427
|
+
raise 'Do not try create Replicated table. It will be configured based on the *MergeTree engine.'
|
377
428
|
end
|
429
|
+
|
430
|
+
options[:options] = configure_replica(table, options[:options])
|
378
431
|
end
|
379
432
|
options
|
380
433
|
end
|
434
|
+
|
435
|
+
def configure_replica(table, options)
|
436
|
+
match = options.match(/^(.*?MergeTree)(?:\(([^\)]*)\))?((?:.|\n)*)/)
|
437
|
+
return options unless match
|
438
|
+
|
439
|
+
if replica
|
440
|
+
engine_params = ([replica_path(table), replica].map { |v| "'#{v}'" } + [match[2].presence]).compact.join(', ')
|
441
|
+
end
|
442
|
+
|
443
|
+
"Replicated#{match[1]}(#{engine_params})#{match[3]}"
|
444
|
+
end
|
381
445
|
end
|
382
446
|
end
|
383
447
|
end
|
@@ -6,14 +6,24 @@ module ClickhouseActiverecord
|
|
6
6
|
class << self
|
7
7
|
|
8
8
|
def create_table
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
return if table_exists?
|
10
|
+
|
11
|
+
version_options = connection.internal_string_options_for_primary_key
|
12
|
+
table_options = {
|
13
|
+
id: false, options: 'ReplacingMergeTree(ver) PARTITION BY version ORDER BY (version)', if_not_exists: true
|
14
|
+
}
|
15
|
+
full_config = connection.instance_variable_get(:@full_config) || {}
|
16
|
+
|
17
|
+
if full_config[:distributed_service_tables]
|
18
|
+
table_options.merge!(with_distributed: table_name, sharding_key: 'cityHash64(version)')
|
19
|
+
|
20
|
+
distributed_suffix = "_#{full_config[:distributed_service_tables_suffix] || 'distributed'}"
|
21
|
+
end
|
22
|
+
|
23
|
+
connection.create_table(table_name + distributed_suffix.to_s, **table_options) do |t|
|
24
|
+
t.string :version, **version_options
|
25
|
+
t.column :active, 'Int8', null: false, default: '1'
|
26
|
+
t.datetime :ver, null: false, default: -> { 'now()' }
|
17
27
|
end
|
18
28
|
end
|
19
29
|
|
@@ -26,14 +36,26 @@ module ClickhouseActiverecord
|
|
26
36
|
class InternalMetadata < ::ActiveRecord::InternalMetadata
|
27
37
|
class << self
|
28
38
|
def create_table
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
39
|
+
return if table_exists?
|
40
|
+
|
41
|
+
key_options = connection.internal_string_options_for_primary_key
|
42
|
+
table_options = {
|
43
|
+
id: false,
|
44
|
+
options: connection.adapter_name.downcase == 'clickhouse' ? 'MergeTree() PARTITION BY toDate(created_at) ORDER BY (created_at)' : '',
|
45
|
+
if_not_exists: true
|
46
|
+
}
|
47
|
+
full_config = connection.instance_variable_get(:@full_config) || {}
|
48
|
+
|
49
|
+
if full_config[:distributed_service_tables]
|
50
|
+
table_options.merge!(with_distributed: table_name, sharding_key: 'cityHash64(created_at)')
|
51
|
+
|
52
|
+
distributed_suffix = "_#{full_config[:distributed_service_tables_suffix] || 'distributed'}"
|
53
|
+
end
|
54
|
+
|
55
|
+
connection.create_table(table_name + distributed_suffix.to_s, **table_options) do |t|
|
56
|
+
t.string :key, **key_options
|
57
|
+
t.string :value
|
58
|
+
t.timestamps
|
37
59
|
end
|
38
60
|
end
|
39
61
|
end
|
@@ -47,6 +69,16 @@ module ClickhouseActiverecord
|
|
47
69
|
@schema_migration = schema_migration
|
48
70
|
end
|
49
71
|
|
72
|
+
def up(target_version = nil)
|
73
|
+
selected_migrations = if block_given?
|
74
|
+
migrations.select { |m| yield m }
|
75
|
+
else
|
76
|
+
migrations
|
77
|
+
end
|
78
|
+
|
79
|
+
ClickhouseActiverecord::Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
|
80
|
+
end
|
81
|
+
|
50
82
|
def down(target_version = nil)
|
51
83
|
selected_migrations = if block_given?
|
52
84
|
migrations.select { |m| yield m }
|
@@ -14,7 +14,7 @@ module ClickhouseActiverecord
|
|
14
14
|
connection.create_database @configuration["database"]
|
15
15
|
rescue ActiveRecord::StatementInvalid => e
|
16
16
|
if e.cause.to_s.include?('already exists')
|
17
|
-
raise ActiveRecord::
|
17
|
+
raise ActiveRecord::DatabaseAlreadyExists
|
18
18
|
else
|
19
19
|
raise
|
20
20
|
end
|
@@ -43,7 +43,15 @@ module ClickhouseActiverecord
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def structure_load(*args)
|
46
|
-
File.read(args.first).split(";\n\n").each
|
46
|
+
File.read(args.first).split(";\n\n").each do |sql|
|
47
|
+
if sql.gsub(/[a-z]/i, '').blank?
|
48
|
+
next
|
49
|
+
elsif sql =~ /^INSERT INTO/
|
50
|
+
connection.do_execute(sql, nil, format: nil)
|
51
|
+
else
|
52
|
+
connection.execute(sql)
|
53
|
+
end
|
54
|
+
end
|
47
55
|
end
|
48
56
|
|
49
57
|
def migrate
|
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'active_record/connection_adapters/clickhouse_adapter'
|
4
4
|
|
5
|
+
require_relative '../core_extensions/active_record/migration/command_recorder'
|
6
|
+
ActiveRecord::Migration::CommandRecorder.include CoreExtensions::ActiveRecord::Migration::CommandRecorder
|
7
|
+
|
5
8
|
if defined?(Rails::Railtie)
|
6
9
|
require 'clickhouse-activerecord/railtie'
|
7
10
|
require 'clickhouse-activerecord/schema'
|
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.5.
|
4
|
+
version: 0.5.8
|
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: 2022-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -42,14 +42,14 @@ dependencies:
|
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.15'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.15'
|
55
55
|
- !ruby/object:Gem::Dependency
|
@@ -112,6 +112,7 @@ files:
|
|
112
112
|
- bin/console
|
113
113
|
- bin/setup
|
114
114
|
- clickhouse-activerecord.gemspec
|
115
|
+
- core_extensions/active_record/migration/command_recorder.rb
|
115
116
|
- lib/active_record/connection_adapters/clickhouse/oid/array.rb
|
116
117
|
- lib/active_record/connection_adapters/clickhouse/oid/big_integer.rb
|
117
118
|
- lib/active_record/connection_adapters/clickhouse/oid/date.rb
|
@@ -135,7 +136,7 @@ homepage: https://github.com/pnixx/clickhouse-activerecord
|
|
135
136
|
licenses:
|
136
137
|
- MIT
|
137
138
|
metadata: {}
|
138
|
-
post_install_message:
|
139
|
+
post_install_message:
|
139
140
|
rdoc_options: []
|
140
141
|
require_paths:
|
141
142
|
- lib
|
@@ -150,8 +151,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
151
|
- !ruby/object:Gem::Version
|
151
152
|
version: '0'
|
152
153
|
requirements: []
|
153
|
-
rubygems_version: 3.0.
|
154
|
-
signing_key:
|
154
|
+
rubygems_version: 3.0.3
|
155
|
+
signing_key:
|
155
156
|
specification_version: 4
|
156
157
|
summary: ClickHouse ActiveRecord
|
157
158
|
test_files: []
|