clickhouse-activerecord 1.0.2 → 1.0.4

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: e5a31d2ddff53bb618e1624e325c0be76f2f602655565a74a96106674f3a375e
4
- data.tar.gz: 762b41c929d36e7ff0f0ceff557da5b85d0b231e8df3e6c6bd41b6085eb940b0
3
+ metadata.gz: 194430a00c6f085ec0bf6b1cf18911c06b69ff2e87ef18fc50183b1d7d1f20c7
4
+ data.tar.gz: 54e418ac9c841e6852e7e87e1ea169335f0c0940537eda3f95d645f3e63ed81e
5
5
  SHA512:
6
- metadata.gz: a6f8143c312efbc6f276b0fdc2b9e5ea8ab811f06a865d54ff82dcaa0614c30b26c44f65f60098f0895dcf935aa97c86e8b168e7e1bc5b7e54899662b71ad86a
7
- data.tar.gz: d9f4ba22a3f13bd157a225870e4d5eb025ca6a35ac21dc73731c19a8bb0d7464e479479109007d117d29f1aa788bb2f3cd5ae0350f1fa13596c36da3ed99a766
6
+ metadata.gz: 9d5a90636c9eaa390ce1b75f65581061312dd598fbaf64e0402a40d3e2a1ab6b8079a0ae438ac86e1b03d4df3a1d1ab6308db961cf988320a39b13cf65014cc5
7
+ data.tar.gz: d961eaf6d2d5798cbf220dc7249330c91b43fe86a68d64ff0371bb0a0f7cba754dd5e95fb1fb666fadcbd74fe71fd89f6ea5b2d85a6d478e7c624e541f00b768
data/README.md CHANGED
@@ -124,11 +124,11 @@ If you using multiple databases, for example: PostgreSQL, Clickhouse.
124
124
 
125
125
  Schema dump to `db/clickhouse_schema.rb` file:
126
126
 
127
- $ rake clickhouse:schema:dump
127
+ $ rake db:schema:dump:clickhouse
128
128
 
129
129
  Schema load from `db/clickhouse_schema.rb` file:
130
130
 
131
- $ rake clickhouse:schema:load
131
+ $ rake db:schema:load:clickhouse
132
132
 
133
133
  For export schema to PostgreSQL, you need use:
134
134
 
@@ -238,6 +238,7 @@ Donations to this project are going directly to [PNixx](https://github.com/PNixx
238
238
  * BTC address: `1H3rhpf7WEF5JmMZ3PVFMQc7Hm29THgUfN`
239
239
  * ETH address: `0x6F094365A70fe7836A633d2eE80A1FA9758234d5`
240
240
  * XMR address: `42gP71qLB5M43RuDnrQ3vSJFFxis9Kw9VMURhpx9NLQRRwNvaZRjm2TFojAMC8Fk1BQhZNKyWhoyJSn5Ak9kppgZPjE17Zh`
241
+ * TON address: `UQBt0-s1igIpJoEup0B1yAUkZ56rzbpruuAjNhQ26MVCaNlC`
241
242
 
242
243
  ## Development
243
244
 
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module Clickhouse
6
+ module OID # :nodoc:
7
+ class Uuid < Type::Value # :nodoc:
8
+ ACCEPTABLE_UUID = %r{\A(\{)?([a-fA-F0-9]{4}-?){8}(?(1)\}|)\z}
9
+
10
+ alias :serialize :deserialize
11
+
12
+ def type
13
+ :uuid
14
+ end
15
+
16
+ def changed?(old_value, new_value, _)
17
+ old_value.class != new_value.class ||
18
+ new_value && old_value.casecmp(new_value) != 0
19
+ end
20
+
21
+ def changed_in_place?(raw_old_value, new_value)
22
+ raw_old_value.class != new_value.class ||
23
+ new_value && raw_old_value.casecmp(new_value) != 0
24
+ end
25
+
26
+ private
27
+
28
+ def cast_value(value)
29
+ casted = value.to_s
30
+ casted if casted.match?(ACCEPTABLE_UUID)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -64,7 +64,7 @@ module ActiveRecord
64
64
 
65
65
  def do_system_execute(sql, name = nil)
66
66
  log_with_debug(sql, "#{adapter_name} #{name}") do
67
- res = @connection.post("/?#{@config.to_param}", "#{sql} FORMAT JSONCompact", 'User-Agent' => "Clickhouse ActiveRecord #{ClickhouseActiverecord::VERSION}")
67
+ res = @connection.post("/?#{@connection_config.to_param}", "#{sql} FORMAT JSONCompact", 'User-Agent' => "Clickhouse ActiveRecord #{ClickhouseActiverecord::VERSION}")
68
68
 
69
69
  process_response(res)
70
70
  end
@@ -73,7 +73,7 @@ module ActiveRecord
73
73
  def do_execute(sql, name = nil, format: 'JSONCompact', settings: {})
74
74
  log(sql, "#{adapter_name} #{name}") do
75
75
  formatted_sql = apply_format(sql, format)
76
- request_params = @config || {}
76
+ request_params = @connection_config || {}
77
77
  res = @connection.post("/?#{request_params.merge(settings).to_param}", formatted_sql, 'User-Agent' => "Clickhouse ActiveRecord #{ClickhouseActiverecord::VERSION}")
78
78
 
79
79
  process_response(res)
@@ -100,6 +100,16 @@ module ActiveRecord
100
100
  end
101
101
  end
102
102
 
103
+ # Fix insert_all method
104
+ # https://github.com/PNixx/clickhouse-activerecord/issues/71#issuecomment-1923244983
105
+ def with_yaml_fallback(value) # :nodoc:
106
+ if value.is_a?(Array)
107
+ value
108
+ else
109
+ super
110
+ end
111
+ end
112
+
103
113
  private
104
114
 
105
115
  def apply_format(sql, format)
@@ -1,13 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'arel/visitors/clickhouse'
4
+ require 'arel/nodes/final'
4
5
  require 'arel/nodes/settings'
5
6
  require 'arel/nodes/using'
6
- require 'clickhouse-activerecord/migration'
7
7
  require 'active_record/connection_adapters/clickhouse/oid/array'
8
8
  require 'active_record/connection_adapters/clickhouse/oid/date'
9
9
  require 'active_record/connection_adapters/clickhouse/oid/date_time'
10
10
  require 'active_record/connection_adapters/clickhouse/oid/big_integer'
11
+ require 'active_record/connection_adapters/clickhouse/oid/uuid'
11
12
  require 'active_record/connection_adapters/clickhouse/schema_definitions'
12
13
  require 'active_record/connection_adapters/clickhouse/schema_creation'
13
14
  require 'active_record/connection_adapters/clickhouse/schema_statements'
@@ -44,7 +45,7 @@ module ActiveRecord
44
45
  raise ArgumentError, 'No database specified. Missing argument: database.'
45
46
  end
46
47
 
47
- ConnectionAdapters::ClickhouseAdapter.new(logger, connection, { user: config[:username], password: config[:password], database: database }.compact, config)
48
+ ConnectionAdapters::ClickhouseAdapter.new(logger, connection, config)
48
49
  end
49
50
  end
50
51
  end
@@ -63,7 +64,7 @@ module ActiveRecord
63
64
 
64
65
  module ModelSchema
65
66
  module ClassMethods
66
- delegate :final, :settings, to: :all
67
+ delegate :final, :final!, :settings, :settings!, to: :all
67
68
 
68
69
  def is_view
69
70
  @is_view || false
@@ -119,33 +120,20 @@ module ActiveRecord
119
120
  include Clickhouse::SchemaStatements
120
121
 
121
122
  # Initializes and connects a Clickhouse adapter.
122
- def initialize(logger, connection_parameters, config, full_config)
123
+ def initialize(logger, connection_parameters, config)
123
124
  super(nil, logger)
124
125
  @connection_parameters = connection_parameters
126
+ @connection_config = { user: config[:username], password: config[:password], database: config[:database] }.compact
127
+ @debug = config[:debug] || false
125
128
  @config = config
126
- @debug = full_config[:debug] || false
127
- @full_config = full_config
128
129
 
129
130
  @prepared_statements = false
130
131
 
131
132
  connect
132
133
  end
133
134
 
134
- # Support SchemaMigration from v5.2.2 to v6+
135
- def schema_migration # :nodoc:
136
- ClickhouseActiverecord::SchemaMigration.new(self)
137
- end
138
-
139
- def internal_metadata # :nodoc:
140
- ClickhouseActiverecord::InternalMetadata.new(self)
141
- end
142
-
143
135
  def migrations_paths
144
- @full_config[:migrations_paths] || 'db/migrate_clickhouse'
145
- end
146
-
147
- def migration_context # :nodoc:
148
- ClickhouseActiverecord::MigrationContext.new(migrations_paths, schema_migration, internal_metadata)
136
+ @config[:migrations_paths] || 'db/migrate_clickhouse'
149
137
  end
150
138
 
151
139
  def arel_visitor # :nodoc:
@@ -211,6 +199,9 @@ module ActiveRecord
211
199
  register_class_with_limit m, %r(UInt64), Type::UnsignedInteger
212
200
  #register_class_with_limit m, %r(UInt128), Type::UnsignedInteger #not implemnted in clickhouse
213
201
  register_class_with_limit m, %r(UInt256), Type::UnsignedInteger
202
+
203
+ m.register_type %r(bool)i, ActiveModel::Type::Boolean.new
204
+ m.register_type %r{uuid}i, Clickhouse::OID::Uuid.new
214
205
  # register_class_with_limit m, %r(Array), Clickhouse::OID::Array
215
206
  m.register_type(%r(Array)) do |sql_type|
216
207
  Clickhouse::OID::Array.new(sql_type)
@@ -275,7 +266,7 @@ module ActiveRecord
275
266
  def create_database(name)
276
267
  sql = apply_cluster "CREATE DATABASE #{quote_table_name(name)}"
277
268
  log_with_debug(sql, adapter_name) do
278
- res = @connection.post("/?#{@config.except(:database).to_param}", sql)
269
+ res = @connection.post("/?#{@connection_config.except(:database).to_param}", sql)
279
270
  process_response(res)
280
271
  end
281
272
  end
@@ -311,7 +302,7 @@ module ActiveRecord
311
302
  raise 'Set a cluster' unless cluster
312
303
 
313
304
  distributed_options =
314
- "Distributed(#{cluster}, #{@config[:database]}, #{table_name}, #{sharding_key})"
305
+ "Distributed(#{cluster}, #{@connection_config[:database]}, #{table_name}, #{sharding_key})"
315
306
  create_table(distributed_table_name, **options.merge(options: distributed_options), &block)
316
307
  end
317
308
  end
@@ -320,7 +311,7 @@ module ActiveRecord
320
311
  def drop_database(name) #:nodoc:
321
312
  sql = apply_cluster "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
322
313
  log_with_debug(sql, adapter_name) do
323
- res = @connection.post("/?#{@config.except(:database).to_param}", sql)
314
+ res = @connection.post("/?#{@connection_config.except(:database).to_param}", sql)
324
315
  process_response(res)
325
316
  end
326
317
  end
@@ -374,15 +365,15 @@ module ActiveRecord
374
365
  end
375
366
 
376
367
  def cluster
377
- @full_config[:cluster_name]
368
+ @config[:cluster_name]
378
369
  end
379
370
 
380
371
  def replica
381
- @full_config[:replica_name]
372
+ @config[:replica_name]
382
373
  end
383
374
 
384
375
  def use_default_replicated_merge_tree_params?
385
- database_engine_atomic? && @full_config[:use_default_replicated_merge_tree_params]
376
+ database_engine_atomic? && @config[:use_default_replicated_merge_tree_params]
386
377
  end
387
378
 
388
379
  def use_replica?
@@ -390,11 +381,11 @@ module ActiveRecord
390
381
  end
391
382
 
392
383
  def replica_path(table)
393
- "/clickhouse/tables/#{cluster}/#{@config[:database]}.#{table}"
384
+ "/clickhouse/tables/#{cluster}/#{@connection_config[:database]}.#{table}"
394
385
  end
395
386
 
396
387
  def database_engine_atomic?
397
- current_database_engine = "select engine from system.databases where name = '#{@config[:database]}'"
388
+ current_database_engine = "select engine from system.databases where name = '#{@connection_config[:database]}'"
398
389
  res = select_one(current_database_engine)
399
390
  res['engine'] == 'Atomic' if res
400
391
  end
@@ -0,0 +1,7 @@
1
+ module Arel # :nodoc: all
2
+ module Nodes
3
+ class Final < Arel::Nodes::Unary
4
+ delegate :empty?, to: :expr
5
+ end
6
+ end
7
+ end
@@ -13,12 +13,6 @@ module Arel
13
13
  end
14
14
  end
15
15
 
16
- def visit_Arel_Table o, collector
17
- collector = super
18
- collector << ' FINAL' if o.final
19
- collector
20
- end
21
-
22
16
  def visit_Arel_Nodes_SelectOptions(o, collector)
23
17
  maybe_visit o.settings, super
24
18
  end
@@ -34,6 +28,12 @@ module Arel
34
28
  maybe_visit o.limit, collector
35
29
  end
36
30
 
31
+ def visit_Arel_Nodes_Final(o, collector)
32
+ visit o.expr, collector
33
+ collector << ' FINAL'
34
+ collector
35
+ end
36
+
37
37
  def visit_Arel_Nodes_Settings(o, collector)
38
38
  return collector if o.expr.empty?
39
39
 
@@ -53,6 +53,16 @@ module Arel
53
53
  collector
54
54
  end
55
55
 
56
+ def visit_Arel_Nodes_Matches(o, collector)
57
+ op = o.case_sensitive ? " LIKE " : " ILIKE "
58
+ infix_value o, collector, op
59
+ end
60
+
61
+ def visit_Arel_Nodes_DoesNotMatch(o, collector)
62
+ op = o.case_sensitive ? " NOT LIKE " : " NOT ILIKE "
63
+ infix_value o, collector, op
64
+ end
65
+
56
66
  def sanitize_as_setting_value(value)
57
67
  if value == :default
58
68
  'DEFAULT'
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ClickhouseActiverecord
4
4
  class Tasks
5
- delegate :connection, :establish_connection, :clear_active_connections!, to: ActiveRecord::Base
5
+ delegate :connection, :establish_connection, to: ActiveRecord::Base
6
6
 
7
7
  def initialize(configuration)
8
8
  @configuration = configuration.with_indifferent_access
@@ -25,7 +25,7 @@ module ClickhouseActiverecord
25
25
  end
26
26
 
27
27
  def purge
28
- clear_active_connections!
28
+ ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
29
29
  drop
30
30
  create
31
31
  end
@@ -1,3 +1,3 @@
1
1
  module ClickhouseActiverecord
2
- VERSION = '1.0.2'
2
+ VERSION = '1.0.4'
3
3
  end
@@ -2,8 +2,11 @@
2
2
 
3
3
  require 'active_record/connection_adapters/clickhouse_adapter'
4
4
 
5
+ require 'core_extensions/active_record/internal_metadata'
5
6
  require 'core_extensions/active_record/relation'
7
+ require 'core_extensions/active_record/schema_migration'
6
8
 
9
+ require 'core_extensions/arel/nodes/select_core'
7
10
  require 'core_extensions/arel/nodes/select_statement'
8
11
  require 'core_extensions/arel/select_manager'
9
12
  require 'core_extensions/arel/table'
@@ -21,8 +24,11 @@ end
21
24
 
22
25
  module ClickhouseActiverecord
23
26
  def self.load
27
+ ActiveRecord::InternalMetadata.singleton_class.prepend(CoreExtensions::ActiveRecord::InternalMetadata::ClassMethods)
24
28
  ActiveRecord::Relation.prepend(CoreExtensions::ActiveRecord::Relation)
29
+ ActiveRecord::SchemaMigration.singleton_class.prepend(CoreExtensions::ActiveRecord::SchemaMigration::ClassMethods)
25
30
 
31
+ Arel::Nodes::SelectCore.prepend(CoreExtensions::Arel::Nodes::SelectCore)
26
32
  Arel::Nodes::SelectStatement.prepend(CoreExtensions::Arel::Nodes::SelectStatement)
27
33
  Arel::SelectManager.prepend(CoreExtensions::Arel::SelectManager)
28
34
  Arel::Table.prepend(CoreExtensions::Arel::Table)
@@ -0,0 +1,46 @@
1
+ module CoreExtensions
2
+ module ActiveRecord
3
+ module InternalMetadata
4
+ module ClassMethods
5
+
6
+ def []=(key, value)
7
+ row = final.find_by(key: key)
8
+ if row.nil? || row.value != value
9
+ create!(key: key, value: value)
10
+ end
11
+ end
12
+
13
+ def [](key)
14
+ final.where(key: key).pluck(:value).first
15
+ end
16
+
17
+ def create_table
18
+ return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
19
+ return if table_exists? || !enabled?
20
+
21
+ key_options = connection.internal_string_options_for_primary_key
22
+ table_options = {
23
+ id: false,
24
+ options: connection.adapter_name.downcase == 'clickhouse' ? 'ReplacingMergeTree(created_at) PARTITION BY key ORDER BY key' : '',
25
+ if_not_exists: true
26
+ }
27
+ full_config = connection.instance_variable_get(:@config) || {}
28
+
29
+ if full_config[:distributed_service_tables]
30
+ table_options.merge!(with_distributed: table_name, sharding_key: 'cityHash64(created_at)')
31
+
32
+ distributed_suffix = "_#{full_config[:distributed_service_tables_suffix] || 'distributed'}"
33
+ else
34
+ distributed_suffix = ''
35
+ end
36
+
37
+ connection.create_table(table_name + distributed_suffix.to_s, **table_options) do |t|
38
+ t.string :key, **key_options
39
+ t.string :value
40
+ t.timestamps
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -38,17 +38,14 @@ module CoreExtensions
38
38
  # # SELECT users.* FROM users FINAL
39
39
  #
40
40
  # An <tt>ActiveRecord::ActiveRecordError</tt> will be raised if database not ClickHouse.
41
- # @param [Boolean] final
42
- def final(final = true)
43
- spawn.final!(final)
41
+ def final
42
+ spawn.final!
44
43
  end
45
44
 
46
- # @param [Boolean] final
47
- def final!(final = true)
45
+ def final!
48
46
  assert_mutability!
49
47
  check_command('FINAL')
50
- @table = @table.dup
51
- @table.final = final
48
+ @values[:final] = true
52
49
  self
53
50
  end
54
51
 
@@ -79,6 +76,7 @@ module CoreExtensions
79
76
  def build_arel(aliases = nil)
80
77
  arel = super
81
78
 
79
+ arel.final! if @values[:final].present?
82
80
  arel.settings(@values[:settings]) if @values[:settings].present?
83
81
  arel.using(@values[:using]) if @values[:using].present?
84
82
 
@@ -0,0 +1,48 @@
1
+ module CoreExtensions
2
+ module ActiveRecord
3
+ module SchemaMigration
4
+ module ClassMethods
5
+
6
+ def create_table
7
+ return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
8
+
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) ORDER BY (version)', if_not_exists: true
14
+ }
15
+ full_config = connection.instance_variable_get(:@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
+ else
22
+ distributed_suffix = ''
23
+ end
24
+
25
+ connection.create_table(table_name + distributed_suffix.to_s, **table_options) do |t|
26
+ t.string :version, **version_options
27
+ t.column :active, 'Int8', null: false, default: '1'
28
+ t.datetime :ver, null: false, default: -> { 'now()' }
29
+ end
30
+ end
31
+
32
+ def delete_version(version)
33
+ return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
34
+
35
+ im = Arel::InsertManager.new(arel_table)
36
+ im.insert(arel_table[primary_key] => version.to_s, arel_table['active'] => 0)
37
+ connection.insert(im, "#{self.class} Create Rollback Version", primary_key, version)
38
+ end
39
+
40
+ def all_versions
41
+ return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
42
+
43
+ final.where(active: 1).order(:version).pluck(:version)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,19 @@
1
+ module CoreExtensions
2
+ module Arel # :nodoc: all
3
+ module Nodes
4
+ module SelectCore
5
+ attr_accessor :final
6
+
7
+ def source
8
+ return super unless final
9
+
10
+ ::Arel::Nodes::Final.new(super)
11
+ end
12
+
13
+ def eql?(other)
14
+ super && final == other.final
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -2,6 +2,11 @@ module CoreExtensions
2
2
  module Arel
3
3
  module SelectManager
4
4
 
5
+ def final!
6
+ @ctx.final = true
7
+ self
8
+ end
9
+
5
10
  # @param [Hash] values
6
11
  def settings(values)
7
12
  @ast.settings = ::Arel::Nodes::Settings.new(values)
@@ -1,8 +1,6 @@
1
1
  module CoreExtensions
2
2
  module Arel
3
3
  module Table
4
- attr_accessor :final
5
-
6
4
  def is_view
7
5
  type_caster.is_view
8
6
  end
@@ -12,15 +12,16 @@ namespace :clickhouse do
12
12
  end
13
13
 
14
14
  namespace :schema do
15
- # TODO: not testing
15
+ # TODO: deprecated
16
16
  desc 'Load database schema'
17
17
  task load: %i[prepare_internal_metadata_table] do
18
18
  simple = ENV['simple'] || ARGV.any? { |a| a.include?('--simple') } ? '_simple' : nil
19
- config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: 'clickhouse')
20
- ClickhouseActiverecord::SchemaMigration.new(ActiveRecord::Base.establish_connection(config).connection).drop_table
19
+ ActiveRecord::Base.establish_connection(:clickhouse)
20
+ ActiveRecord::SchemaMigration.drop_table
21
21
  load(Rails.root.join("db/clickhouse_schema#{simple}.rb"))
22
22
  end
23
23
 
24
+ # TODO: deprecated
24
25
  desc 'Dump database schema'
25
26
  task dump: :environment do |_, args|
26
27
  simple = ENV['simple'] || args[:simple] || ARGV.any? { |a| a.include?('--simple') } ? '_simple' : nil
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: 1.0.2
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergey Odintsov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-12 00:00:00.000000000 Z
11
+ date: 2024-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -103,21 +103,25 @@ files:
103
103
  - lib/active_record/connection_adapters/clickhouse/oid/big_integer.rb
104
104
  - lib/active_record/connection_adapters/clickhouse/oid/date.rb
105
105
  - lib/active_record/connection_adapters/clickhouse/oid/date_time.rb
106
+ - lib/active_record/connection_adapters/clickhouse/oid/uuid.rb
106
107
  - lib/active_record/connection_adapters/clickhouse/schema_creation.rb
107
108
  - lib/active_record/connection_adapters/clickhouse/schema_definitions.rb
108
109
  - lib/active_record/connection_adapters/clickhouse/schema_statements.rb
109
110
  - lib/active_record/connection_adapters/clickhouse_adapter.rb
111
+ - lib/arel/nodes/final.rb
110
112
  - lib/arel/nodes/settings.rb
111
113
  - lib/arel/nodes/using.rb
112
114
  - lib/arel/visitors/clickhouse.rb
113
115
  - lib/clickhouse-activerecord.rb
114
- - lib/clickhouse-activerecord/migration.rb
115
116
  - lib/clickhouse-activerecord/railtie.rb
116
117
  - lib/clickhouse-activerecord/schema.rb
117
118
  - lib/clickhouse-activerecord/schema_dumper.rb
118
119
  - lib/clickhouse-activerecord/tasks.rb
119
120
  - lib/clickhouse-activerecord/version.rb
121
+ - lib/core_extensions/active_record/internal_metadata.rb
120
122
  - lib/core_extensions/active_record/relation.rb
123
+ - lib/core_extensions/active_record/schema_migration.rb
124
+ - lib/core_extensions/arel/nodes/select_core.rb
121
125
  - lib/core_extensions/arel/nodes/select_statement.rb
122
126
  - lib/core_extensions/arel/select_manager.rb
123
127
  - lib/core_extensions/arel/table.rb
@@ -1,103 +0,0 @@
1
- require 'active_record/migration'
2
-
3
- module ClickhouseActiverecord
4
-
5
- class SchemaMigration < ::ActiveRecord::SchemaMigration
6
- def create_table
7
- return if table_exists?
8
-
9
- version_options = connection.internal_string_options_for_primary_key
10
- table_options = {
11
- id: false, options: 'ReplacingMergeTree(ver) ORDER BY (version)', if_not_exists: true
12
- }
13
- full_config = connection.instance_variable_get(:@full_config) || {}
14
-
15
- if full_config[:distributed_service_tables]
16
- table_options.merge!(with_distributed: table_name, sharding_key: 'cityHash64(version)')
17
-
18
- distributed_suffix = "_#{full_config[:distributed_service_tables_suffix] || 'distributed'}"
19
- end
20
-
21
- connection.create_table(table_name + distributed_suffix.to_s, **table_options) do |t|
22
- t.string :version, **version_options
23
- t.column :active, 'Int8', null: false, default: '1'
24
- t.datetime :ver, null: false, default: -> { 'now()' }
25
- end
26
- end
27
-
28
- def versions
29
- table = arel_table.dup
30
- table.final = true
31
- sm = Arel::SelectManager.new(table)
32
- sm.project(arel_table[primary_key])
33
- sm.order(arel_table[primary_key].asc)
34
- sm.where([arel_table['active'].eq(1)])
35
-
36
- connection.select_values(sm, "#{self.class} Load")
37
- end
38
-
39
- def delete_version(version)
40
- im = Arel::InsertManager.new(arel_table)
41
- im.insert(arel_table[primary_key] => version.to_s, arel_table['active'] => 0)
42
- connection.insert(im, "#{self.class} Create Rollback Version", primary_key, version)
43
- end
44
- end
45
-
46
- class InternalMetadata < ::ActiveRecord::InternalMetadata
47
-
48
- def create_table
49
- return if table_exists? || !enabled?
50
-
51
- key_options = connection.internal_string_options_for_primary_key
52
- table_options = {
53
- id: false,
54
- options: connection.adapter_name.downcase == 'clickhouse' ? 'ReplacingMergeTree(created_at) PARTITION BY key ORDER BY key' : '',
55
- if_not_exists: true
56
- }
57
- full_config = connection.instance_variable_get(:@full_config) || {}
58
-
59
- if full_config[:distributed_service_tables]
60
- table_options.merge!(with_distributed: table_name, sharding_key: 'cityHash64(created_at)')
61
-
62
- distributed_suffix = "_#{full_config[:distributed_service_tables_suffix] || 'distributed'}"
63
- end
64
-
65
- connection.create_table(table_name + distributed_suffix.to_s, **table_options) do |t|
66
- t.string :key, **key_options
67
- t.string :value
68
- t.timestamps
69
- end
70
- end
71
-
72
- private
73
-
74
- def update_entry(key, new_value)
75
- create_entry(key, new_value)
76
- end
77
-
78
- def select_entry(key)
79
- table = arel_table.dup
80
- table.final = true
81
- sm = Arel::SelectManager.new(table)
82
- sm.project(Arel::Nodes::SqlLiteral.new("*"))
83
- sm.where(table[primary_key].eq(Arel::Nodes::BindParam.new(key)))
84
- sm.order(table[primary_key].asc)
85
- sm.limit = 1
86
-
87
- connection.select_all(sm, "#{self.class} Load").first
88
- end
89
- end
90
-
91
- class MigrationContext < ::ActiveRecord::MigrationContext #:nodoc:
92
-
93
- def get_all_versions
94
- if schema_migration.table_exists?
95
- schema_migration.versions.map(&:to_i)
96
- else
97
- []
98
- end
99
- end
100
-
101
- end
102
-
103
- end