clickhouse-activerecord 0.5.0 → 0.5.7

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: 1e17583f619debbb02952aa4299fedebbdd0de5ff6ae5c4a604071e42381c33a
4
- data.tar.gz: d9d642a756c2ff7791081f1298917d96758dd5de4f07781dc7c9e587100536b4
3
+ metadata.gz: 79b43575e5eef93daa11e1a2aca2984f696cbef59021f55d1470b2dc0a5d1e3d
4
+ data.tar.gz: b79cccb85d8a07fa4dc533d7b7e9042eeaa2afead26214c075b3131e1843394b
5
5
  SHA512:
6
- metadata.gz: cca1c4ce673a6622855a860e51b85952b0b09e3cbaaafe6b817a5c95ff1bb90d33da4974908acecaed6a658f7574fbaf9f71c1497d1c527006eb36bc3aaefab3
7
- data.tar.gz: 344cc941b595fe40179c8974dfc371dd3732cbf8994999d75976506582d23abbda39340e7b2232cc7b7c25f1c6271d3f26325c409cfd7aa21f1acfc017fb8d32
6
+ metadata.gz: 840b01cc1d5b88eee5e031fada23cfd35f7a8d948a35a767b2f5baf1596af665f28c56778e699960511004367b16ee3130be1f5bd2ee713a9a0d5053a9b58a37
7
+ data.tar.gz: 4e613a19c51b362a05634da06d9528809ed09f01ebec4eac9984656156e9b877bdc4ce321e24bea63ae4e49d85609fa9dda781db60159e60b6d6ee06e8a99a3e
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
@@ -196,6 +196,7 @@ false`. The default integer is `UInt32`
196
196
  | UInt32 | 0 to 4,294,967,295 | 3,4 |
197
197
  | UInt64 | 0 to 18446744073709551615 | 5,6,7,8 |
198
198
  | UInt256 | 0 to ... | 8+ |
199
+ | Array | ... | ... |
199
200
 
200
201
  Example:
201
202
 
@@ -0,0 +1,27 @@
1
+ module CoreExtensions
2
+ module ActiveRecord
3
+ module Migration
4
+ module CommandRecorder
5
+ def create_table_with_distributed(*args, &block)
6
+ record(:create_table_with_distributed, args, &block)
7
+ end
8
+
9
+ def create_view(*args, &block)
10
+ record(:create_view, args, &block)
11
+ end
12
+
13
+ private
14
+
15
+ def invert_create_table_with_distributed(args)
16
+ table_name, options = args
17
+ [:drop_table_with_distributed, table_name, options]
18
+ end
19
+
20
+ def invert_create_view(args)
21
+ view_name, options = args
22
+ [:drop_table, view_name, options]
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module Clickhouse
6
+ module OID # :nodoc:
7
+ class Array < Type::Value # :nodoc:
8
+
9
+ def initialize(sql_type)
10
+ @subtype = case sql_type
11
+ when /U?Int\d+/
12
+ :integer
13
+ when /DateTime/
14
+ :datetime
15
+ when /Date/
16
+ :date
17
+ else
18
+ :string
19
+ end
20
+ end
21
+
22
+ def type
23
+ @subtype
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -22,6 +22,9 @@ module ActiveRecord
22
22
  if options[:null] || options[:null].nil?
23
23
  sql.gsub!(/\s+(.*)/, ' Nullable(\1)')
24
24
  end
25
+ if options[:array]
26
+ sql.gsub!(/\s+(.*)/, ' Array(\1)')
27
+ end
25
28
  sql.gsub!(/(\sString)\(\d+\)/, '\1')
26
29
  sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
27
30
  sql
@@ -33,7 +36,7 @@ module ActiveRecord
33
36
  # rails 6.1
34
37
  opts ||= options.options
35
38
  end
36
-
39
+
37
40
  if opts.present?
38
41
  create_sql << " ENGINE = #{opts}"
39
42
  else
@@ -43,17 +46,48 @@ module ActiveRecord
43
46
  create_sql
44
47
  end
45
48
 
49
+ def add_as_clause!(create_sql, options)
50
+ return unless options.as
51
+
52
+ assign_database_to_subquery!(options.as) if options.view
53
+ create_sql << " AS #{to_sql(options.as)}"
54
+ end
55
+
56
+ def assign_database_to_subquery!(subquery)
57
+ # If you do not specify a database explicitly, ClickHouse will use the "default" database.
58
+ return unless subquery
59
+
60
+ match = subquery.match(/(?<=from)[^.\w]+(?<database>\w+(?=\.))?(?<table_name>[.\w]+)/i)
61
+ return unless match
62
+ return if match[:database]
63
+
64
+ subquery[match.begin(:table_name)...match.end(:table_name)] =
65
+ "#{current_database}.#{match[:table_name].sub('.', '')}"
66
+ end
67
+
68
+ def add_to_clause!(create_sql, options)
69
+ # If you do not specify a database explicitly, ClickHouse will use the "default" database.
70
+ return unless options.to
71
+
72
+ match = options.to.match(/(?<database>.+(?=\.))?(?<table_name>.+)/i)
73
+ return unless match
74
+ return if match[:database]
75
+
76
+ create_sql << "TO #{current_database}.#{options.to.sub('.', '')} "
77
+ end
78
+
46
79
  def visit_TableDefinition(o)
47
80
  create_sql = +"CREATE#{table_modifier_in_create(o)} #{o.view ? "VIEW" : "TABLE"} "
48
81
  create_sql << "IF NOT EXISTS " if o.if_not_exists
49
82
  create_sql << "#{quote_table_name(o.name)} "
83
+ add_to_clause!(create_sql, o) if o.materialized
50
84
 
51
85
  statements = o.columns.map { |c| accept c }
52
86
  statements << accept(o.primary_keys) if o.primary_keys
53
87
  create_sql << "(#{statements.join(', ')})" if statements.present?
54
- # Attach options for only table or materialized view
55
- add_table_options!(create_sql, o) if !o.view || o.view && o.materialized
56
- create_sql << " AS #{to_sql(o.as)}" if o.as
88
+ # Attach options for only table or materialized view without TO section
89
+ add_table_options!(create_sql, o) if !o.view || o.view && o.materialized && !o.to
90
+ add_as_clause!(create_sql, o)
57
91
  create_sql
58
92
  end
59
93
 
@@ -81,6 +115,9 @@ module ActiveRecord
81
115
  change_column_sql
82
116
  end
83
117
 
118
+ def current_database
119
+ ActiveRecord::Base.connection_db_config.database
120
+ end
84
121
  end
85
122
  end
86
123
  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,7 @@ 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)) }
62
64
  end
63
65
  end
64
66
  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
@@ -23,6 +25,11 @@ module ActiveRecord
23
25
  raise ActiveRecord::ActiveRecordError, "Response: #{e.message}"
24
26
  end
25
27
 
28
+ def exec_insert_all(sql, name)
29
+ do_execute(sql, name, format: nil)
30
+ true
31
+ end
32
+
26
33
  def exec_update(_sql, _name = nil, _binds = [])
27
34
  raise ActiveRecord::ActiveRecordError, 'Clickhouse update is not supported'
28
35
  end
@@ -53,7 +60,7 @@ module ActiveRecord
53
60
 
54
61
  def do_system_execute(sql, name = nil)
55
62
  log_with_debug(sql, "#{adapter_name} #{name}") do
56
- 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}")
57
64
 
58
65
  process_response(res)
59
66
  end
@@ -63,7 +70,7 @@ module ActiveRecord
63
70
  log(sql, "#{adapter_name} #{name}") do
64
71
  formatted_sql = apply_format(sql, format)
65
72
  request_params = @config || {}
66
- 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}")
67
74
 
68
75
  process_response(res)
69
76
  end
@@ -116,7 +123,7 @@ module ActiveRecord
116
123
  Clickhouse::SchemaCreation.new(self)
117
124
  end
118
125
 
119
- def create_table_definition(table_name, options)
126
+ def create_table_definition(table_name, **options)
120
127
  Clickhouse::TableDefinition.new(self, table_name, **options)
121
128
  end
122
129
 
@@ -3,6 +3,7 @@
3
3
  require 'clickhouse-activerecord/arel/visitors/to_sql'
4
4
  require 'clickhouse-activerecord/arel/table'
5
5
  require 'clickhouse-activerecord/migration'
6
+ require 'active_record/connection_adapters/clickhouse/oid/array'
6
7
  require 'active_record/connection_adapters/clickhouse/oid/date'
7
8
  require 'active_record/connection_adapters/clickhouse/oid/date_time'
8
9
  require 'active_record/connection_adapters/clickhouse/oid/big_integer'
@@ -17,6 +18,7 @@ module ActiveRecord
17
18
  # Establishes a connection to the database that's used by all Active Record objects
18
19
  def clickhouse_connection(config)
19
20
  config = config.symbolize_keys
21
+
20
22
  if config[:connection]
21
23
  connection = {
22
24
  connection: config[:connection]
@@ -27,6 +29,9 @@ module ActiveRecord
27
29
  host: config[:host] || 'localhost',
28
30
  port: port,
29
31
  ssl: config[:ssl].present? ? config[:ssl] : port == 443,
32
+ sslca: config[:sslca],
33
+ read_timeout: config[:read_timeout],
34
+ write_timeout: config[:write_timeout],
30
35
  }
31
36
  end
32
37
 
@@ -190,12 +195,16 @@ module ActiveRecord
190
195
  register_class_with_limit m, %r(Int128), Type::Integer
191
196
  register_class_with_limit m, %r(Int256), Type::Integer
192
197
 
193
- register_class_with_limit m, %r(Uint8), Type::UnsignedInteger
198
+ register_class_with_limit m, %r(UInt8), Type::UnsignedInteger
194
199
  register_class_with_limit m, %r(UInt16), Type::UnsignedInteger
195
200
  register_class_with_limit m, %r(UInt32), Type::UnsignedInteger
196
201
  register_class_with_limit m, %r(UInt64), Type::UnsignedInteger
197
202
  #register_class_with_limit m, %r(UInt128), Type::UnsignedInteger #not implemnted in clickhouse
198
203
  register_class_with_limit m, %r(UInt256), Type::UnsignedInteger
204
+ # register_class_with_limit m, %r(Array), Clickhouse::OID::Array
205
+ m.register_type(%r(Array)) do |sql_type|
206
+ Clickhouse::OID::Array.new(sql_type)
207
+ end
199
208
  end
200
209
 
201
210
  # Quoting time without microseconds
@@ -253,7 +262,7 @@ module ActiveRecord
253
262
  def create_view(table_name, **options)
254
263
  options.merge!(view: true)
255
264
  options = apply_replica(table_name, options)
256
- td = create_table_definition(apply_cluster(table_name), options)
265
+ td = create_table_definition(apply_cluster(table_name), **options)
257
266
  yield td if block_given?
258
267
 
259
268
  if options[:force]
@@ -263,10 +272,10 @@ module ActiveRecord
263
272
  execute schema_creation.accept td
264
273
  end
265
274
 
266
- def create_table(table_name, **options)
275
+ def create_table(table_name, **options, &block)
267
276
  options = apply_replica(table_name, options)
268
- td = create_table_definition(apply_cluster(table_name), options)
269
- yield td if block_given?
277
+ td = create_table_definition(apply_cluster(table_name), **options)
278
+ block.call td if block_given?
270
279
 
271
280
  if options[:force]
272
281
  drop_table(table_name, options.merge(if_exists: true))
@@ -275,6 +284,19 @@ module ActiveRecord
275
284
  execute schema_creation.accept td
276
285
  end
277
286
 
287
+ def create_table_with_distributed(table_name, **options, &block)
288
+ sharding_key = options.delete(:sharding_key) || 'rand()'
289
+ create_table("#{table_name}_distributed", **options, &block)
290
+ raise 'Set a cluster' unless cluster
291
+
292
+ distributed_options = "Distributed(#{cluster},#{@config[:database]},#{table_name}_distributed,#{sharding_key})"
293
+ create_table(table_name, **options.merge(options: distributed_options), &block)
294
+ end
295
+
296
+ def drop_table_with_distributed(table_name, **options)
297
+ ["#{table_name}_distributed", table_name].each { |name| drop_table(name, **options) }
298
+ end
299
+
278
300
  # Drops a ClickHouse database.
279
301
  def drop_database(name) #:nodoc:
280
302
  sql = apply_cluster "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
@@ -315,14 +337,41 @@ module ActiveRecord
315
337
  @full_config[:replica_name]
316
338
  end
317
339
 
340
+ def use_default_replicated_merge_tree_params?
341
+ database_engine_atomic? && @full_config[:use_default_replicated_merge_tree_params]
342
+ end
343
+
344
+ def use_replica?
345
+ (replica || use_default_replicated_merge_tree_params?) && cluster
346
+ end
347
+
318
348
  def replica_path(table)
319
349
  "/clickhouse/tables/#{cluster}/#{@config[:database]}.#{table}"
320
350
  end
321
351
 
352
+ def database_engine_atomic?
353
+ current_database_engine = "select engine from system.databases where name = '#{@config[:database]}'"
354
+ res = ActiveRecord::Base.connection.select_one(current_database_engine)
355
+ res['engine'] == 'Atomic' if res
356
+ end
357
+
322
358
  def apply_cluster(sql)
323
359
  cluster ? "#{sql} ON CLUSTER #{cluster}" : sql
324
360
  end
325
361
 
362
+ def supports_insert_on_duplicate_skip?
363
+ true
364
+ end
365
+
366
+ def supports_insert_on_duplicate_update?
367
+ true
368
+ end
369
+
370
+ def build_insert_sql(insert) # :nodoc:
371
+ sql = +"INSERT #{insert.into} #{insert.values_list}"
372
+ sql
373
+ end
374
+
326
375
  protected
327
376
 
328
377
  def last_inserted_id(result)
@@ -339,17 +388,35 @@ module ActiveRecord
339
388
 
340
389
  def connect
341
390
  @connection = @connection_parameters[:connection] || Net::HTTP.start(@connection_parameters[:host], @connection_parameters[:port], use_ssl: @connection_parameters[:ssl], verify_mode: OpenSSL::SSL::VERIFY_NONE)
391
+
392
+ @connection.ca_file = @connection_parameters[:ca_file] if @connection_parameters[:ca_file]
393
+ @connection.read_timeout = @connection_parameters[:read_timeout] if @connection_parameters[:read_timeout]
394
+ @connection.write_timeout = @connection_parameters[:write_timeout] if @connection_parameters[:write_timeout]
395
+
396
+ @connection
342
397
  end
343
398
 
344
399
  def apply_replica(table, options)
345
- if replica && cluster && options[:options]
346
- match = options[:options].match(/^(.*?MergeTree)\(([^\)]*)\)(.*?)$/)
347
- if match
348
- options[:options] = "Replicated#{match[1]}(#{([replica_path(table), replica].map{|v| "'#{v}'"} + [match[2].presence]).compact.join(', ')})#{match[3]}"
400
+ if use_replica? && options[:options]
401
+ if options[:options].match(/^Replicated/)
402
+ raise 'Do not try create Replicated table. It will be configured based on the *MergeTree engine.'
349
403
  end
404
+
405
+ options[:options] = configure_replica(table, options[:options])
350
406
  end
351
407
  options
352
408
  end
409
+
410
+ def configure_replica(table, options)
411
+ match = options.match(/^(.*?MergeTree)(?:\(([^\)]*)\))?((?:.|\n)*)/)
412
+ return options unless match
413
+
414
+ if replica
415
+ engine_params = ([replica_path(table), replica].map { |v| "'#{v}'" } + [match[2].presence]).compact.join(', ')
416
+ end
417
+
418
+ "Replicated#{match[1]}(#{engine_params})#{match[3]}"
419
+ end
353
420
  end
354
421
  end
355
422
  end
@@ -6,14 +6,23 @@ module ClickhouseActiverecord
6
6
  class << self
7
7
 
8
8
  def create_table
9
- unless table_exists?
10
- version_options = connection.internal_string_options_for_primary_key
11
-
12
- connection.create_table(table_name, id: false, options: 'ReplacingMergeTree(ver) PARTITION BY version ORDER BY (version)', if_not_exists: true) do |t|
13
- t.string :version, **version_options
14
- t.column :active, 'Int8', null: false, default: '1'
15
- t.datetime :ver, null: false, default: -> { 'now()' }
16
- end
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
+ if connection.instance_variable_get(:@full_config)[:distributed_service_tables]
16
+ table_options.merge!(sharding_key: 'cityHash64(version)')
17
+ table_creation_method = 'create_table_with_distributed'
18
+ else
19
+ table_creation_method = 'create_table'
20
+ end
21
+
22
+ connection.public_send(table_creation_method, table_name, **table_options) do |t|
23
+ t.string :version, **version_options
24
+ t.column :active, 'Int8', null: false, default: '1'
25
+ t.datetime :ver, null: false, default: -> { 'now()' }
17
26
  end
18
27
  end
19
28
 
@@ -26,14 +35,25 @@ module ClickhouseActiverecord
26
35
  class InternalMetadata < ::ActiveRecord::InternalMetadata
27
36
  class << self
28
37
  def create_table
29
- unless table_exists?
30
- key_options = connection.internal_string_options_for_primary_key
31
-
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|
33
- t.string :key, key_options
34
- t.string :value
35
- t.timestamps
36
- end
38
+ return if table_exists?
39
+
40
+ key_options = connection.internal_string_options_for_primary_key
41
+ table_options = {
42
+ id: false,
43
+ options: connection.adapter_name.downcase == 'clickhouse' ? 'MergeTree() PARTITION BY toDate(created_at) ORDER BY (created_at)' : '',
44
+ if_not_exists: true
45
+ }
46
+ if connection.instance_variable_get(:@full_config).try(:[], :distributed_service_tables)
47
+ table_options.merge!(sharding_key: 'cityHash64(created_at)')
48
+ table_creation_method = 'create_table_with_distributed'
49
+ else
50
+ table_creation_method = 'create_table'
51
+ end
52
+
53
+ connection.public_send(table_creation_method, table_name, **table_options) do |t|
54
+ t.string :key, **key_options
55
+ t.string :value
56
+ t.timestamps
37
57
  end
38
58
  end
39
59
  end
@@ -47,6 +67,16 @@ module ClickhouseActiverecord
47
67
  @schema_migration = schema_migration
48
68
  end
49
69
 
70
+ def up(target_version = nil)
71
+ selected_migrations = if block_given?
72
+ migrations.select { |m| yield m }
73
+ else
74
+ migrations
75
+ end
76
+
77
+ ClickhouseActiverecord::Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
78
+ end
79
+
50
80
  def down(target_version = nil)
51
81
  selected_migrations = if block_given?
52
82
  migrations.select { |m| yield m }
@@ -144,9 +144,14 @@ HEADER
144
144
  (column.sql_type =~ /(Nullable)?\(?UInt\d+\)?/).nil? ? false : nil
145
145
  end
146
146
 
147
+ def schema_array(column)
148
+ (column.sql_type =~ /Array?\(/).nil? ? nil : true
149
+ end
150
+
147
151
  def prepare_column_options(column)
148
152
  spec = {}
149
153
  spec[:unsigned] = schema_unsigned(column)
154
+ spec[:array] = schema_array(column)
150
155
  spec.merge(super).compact
151
156
  end
152
157
  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 { |sql| connection.execute(sql) }
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
@@ -1,3 +1,3 @@
1
1
  module ClickhouseActiverecord
2
- VERSION = '0.5.0'
2
+ VERSION = '0.5.7'
3
3
  end
@@ -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.0
4
+ version: 0.5.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergey Odintsov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-10 00:00:00.000000000 Z
11
+ date: 2021-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -112,6 +112,8 @@ files:
112
112
  - bin/console
113
113
  - bin/setup
114
114
  - clickhouse-activerecord.gemspec
115
+ - core_extensions/active_record/migration/command_recorder.rb
116
+ - lib/active_record/connection_adapters/clickhouse/oid/array.rb
115
117
  - lib/active_record/connection_adapters/clickhouse/oid/big_integer.rb
116
118
  - lib/active_record/connection_adapters/clickhouse/oid/date.rb
117
119
  - lib/active_record/connection_adapters/clickhouse/oid/date_time.rb