clickhouse-activerecord 1.0.2 → 1.0.4

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 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