Skip to content

Commit 535ca30

Browse files
committed
refactoring
1 parent daabfa2 commit 535ca30

File tree

7 files changed

+107
-99
lines changed

7 files changed

+107
-99
lines changed

.github/workflows/testing.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ jobs:
1717

1818
strategy:
1919
fail-fast: true
20+
max-parallel: 1
2021
matrix:
21-
ruby-version: [ '3.0' ]
22+
ruby-version: [ '2.7', '3.0', '3.2' ]
2223
clickhouse: [ '22.1' ]
2324

2425
steps:
2526
- uses: actions/checkout@v4
2627

27-
- name: Start ClickHouse (version - ${{ matrix.clickhouse }}) in Docker
28+
- name: Start ClickHouse ${{ matrix.clickhouse }}
2829
uses: isbang/[email protected]
2930
env:
3031
CLICKHOUSE_VERSION: ${{ matrix.clickhouse }}
@@ -51,14 +52,15 @@ jobs:
5152

5253
strategy:
5354
fail-fast: true
55+
max-parallel: 1
5456
matrix:
55-
ruby-version: [ '3.0' ]
57+
ruby-version: [ '2.7', '3.0', '3.2' ]
5658
clickhouse: [ '22.1' ]
5759

5860
steps:
5961
- uses: actions/checkout@v4
6062

61-
- name: Start ClickHouse Cluster (version - ${{ matrix.clickhouse }}) in Docker
63+
- name: Start ClickHouse Cluster ${{ matrix.clickhouse }}
6264
uses: isbang/[email protected]
6365
env:
6466
CLICKHOUSE_VERSION: ${{ matrix.clickhouse }}

lib/clickhouse-activerecord.rb

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,12 @@
55
require 'core_extensions/active_record/internal_metadata'
66
require 'core_extensions/active_record/relation'
77
require 'core_extensions/active_record/schema_migration'
8-
8+
require 'core_extensions/active_record/migration/command_recorder'
99
require 'core_extensions/arel/nodes/select_core'
1010
require 'core_extensions/arel/nodes/select_statement'
1111
require 'core_extensions/arel/select_manager'
1212
require 'core_extensions/arel/table'
1313

14-
require_relative '../core_extensions/active_record/migration/command_recorder'
15-
ActiveRecord::Migration::CommandRecorder.include CoreExtensions::ActiveRecord::Migration::CommandRecorder
16-
1714
if defined?(Rails::Railtie)
1815
require 'clickhouse-activerecord/railtie'
1916
require 'clickhouse-activerecord/schema'
@@ -24,9 +21,10 @@
2421

2522
module ClickhouseActiverecord
2623
def self.load
27-
ActiveRecord::InternalMetadata.prepend(CoreExtensions::ActiveRecord::InternalMetadata::ClassMethods)
24+
ActiveRecord::InternalMetadata.prepend(CoreExtensions::ActiveRecord::InternalMetadata)
25+
ActiveRecord::Migration::CommandRecorder.include(CoreExtensions::ActiveRecord::Migration::CommandRecorder)
2826
ActiveRecord::Relation.prepend(CoreExtensions::ActiveRecord::Relation)
29-
ActiveRecord::SchemaMigration.prepend(CoreExtensions::ActiveRecord::SchemaMigration::ClassMethods)
27+
ActiveRecord::SchemaMigration.prepend(CoreExtensions::ActiveRecord::SchemaMigration)
3028

3129
Arel::Nodes::SelectCore.prepend(CoreExtensions::Arel::Nodes::SelectCore)
3230
Arel::Nodes::SelectStatement.prepend(CoreExtensions::Arel::Nodes::SelectStatement)

lib/clickhouse-activerecord/tasks.rb

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ class Tasks
55
delegate :connection, :establish_connection, to: ActiveRecord::Base
66

77
def initialize(configuration)
8-
@configuration = configuration.with_indifferent_access
8+
@configuration = configuration
99
end
1010

1111
def create
1212
establish_master_connection
13-
connection.create_database @configuration['database']
13+
connection.create_database @configuration.database
1414
rescue ActiveRecord::StatementInvalid => e
1515
if e.cause.to_s.include?('already exists')
1616
raise ActiveRecord::DatabaseAlreadyExists
@@ -21,7 +21,7 @@ def create
2121

2222
def drop
2323
establish_master_connection
24-
connection.drop_database @configuration['database']
24+
connection.drop_database @configuration.database
2525
end
2626

2727
def purge
@@ -31,12 +31,21 @@ def purge
3131
end
3232

3333
def structure_dump(*args)
34-
tables = connection.execute("SHOW TABLES FROM #{@configuration['database']}")['data'].flatten
34+
establish_master_connection
35+
36+
# get all tables
37+
tables = connection.execute("SHOW TABLES FROM #{@configuration.database} WHERE name NOT LIKE '.inner_id.%'")['data'].flatten.map do |table|
38+
next if %w[schema_migrations ar_internal_metadata].include?(table)
39+
connection.show_create_table(table).gsub("#{@configuration.database}.", '')
40+
end.compact
41+
42+
# sort view to last
43+
tables.sort_by! {|table| table.match(/^CREATE\s+(MATERIALIZED\s+)?VIEW/) ? 1 : 0}
3544

45+
# put to file
3646
File.open(args.first, 'w:utf-8') do |file|
3747
tables.each do |table|
38-
next if table.match(/\.inner/)
39-
file.puts connection.execute("SHOW CREATE TABLE #{table}")['data'].try(:first).try(:first).gsub("#{@configuration['database']}.", '') + ";\n\n"
48+
file.puts table + ";\n\n"
4049
end
4150
end
4251
end

lib/core_extensions/active_record/internal_metadata.rb

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,53 @@
11
module CoreExtensions
22
module ActiveRecord
33
module InternalMetadata
4-
module ClassMethods
5-
6-
def create_table
7-
return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
8-
return if table_exists? || !enabled?
9-
10-
key_options = connection.internal_string_options_for_primary_key
11-
table_options = {
12-
id: false,
13-
options: 'ReplacingMergeTree(created_at) PARTITION BY key ORDER BY key',
14-
if_not_exists: true
15-
}
16-
full_config = connection.instance_variable_get(:@config) || {}
17-
18-
if full_config[:distributed_service_tables]
19-
table_options.merge!(with_distributed: table_name, sharding_key: 'cityHash64(created_at)')
20-
21-
distributed_suffix = "_#{full_config[:distributed_service_tables_suffix] || 'distributed'}"
22-
else
23-
distributed_suffix = ''
24-
end
25-
26-
connection.create_table(table_name + distributed_suffix.to_s, **table_options) do |t|
27-
t.string :key, **key_options
28-
t.string :value
29-
t.timestamps
30-
end
31-
end
324

33-
private
5+
def create_table
6+
return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
7+
return if table_exists? || !enabled?
8+
9+
key_options = connection.internal_string_options_for_primary_key
10+
table_options = {
11+
id: false,
12+
options: 'ReplacingMergeTree(created_at) PARTITION BY key ORDER BY key',
13+
if_not_exists: true
14+
}
15+
full_config = connection.instance_variable_get(:@config) || {}
3416

35-
def update_entry(key, new_value)
36-
return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
17+
if full_config[:distributed_service_tables]
18+
table_options.merge!(with_distributed: table_name, sharding_key: 'cityHash64(created_at)')
3719

38-
create_entry(key, new_value)
20+
distributed_suffix = "_#{full_config[:distributed_service_tables_suffix] || 'distributed'}"
21+
else
22+
distributed_suffix = ''
3923
end
4024

41-
def select_entry(key)
42-
return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
25+
connection.create_table(table_name + distributed_suffix.to_s, **table_options) do |t|
26+
t.string :key, **key_options
27+
t.string :value
28+
t.timestamps
29+
end
30+
end
4331

44-
sm = ::Arel::SelectManager.new(arel_table)
45-
sm.final! if connection.table_options(table_name)[:options] =~ /^ReplacingMergeTree/
46-
sm.project(::Arel.star)
47-
sm.where(arel_table[primary_key].eq(::Arel::Nodes::BindParam.new(key)))
48-
sm.order(arel_table[primary_key].asc)
49-
sm.limit = 1
32+
private
5033

51-
connection.select_one(sm, "#{self.class} Load")
52-
end
34+
def update_entry(key, new_value)
35+
return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
36+
37+
create_entry(key, new_value)
38+
end
39+
40+
def select_entry(key)
41+
return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
42+
43+
sm = ::Arel::SelectManager.new(arel_table)
44+
sm.final! if connection.table_options(table_name)[:options] =~ /^ReplacingMergeTree/
45+
sm.project(::Arel.star)
46+
sm.where(arel_table[primary_key].eq(::Arel::Nodes::BindParam.new(key)))
47+
sm.order(arel_table[primary_key].asc)
48+
sm.limit = 1
49+
50+
connection.select_one(sm, "#{self.class} Load")
5351
end
5452
end
5553
end
File renamed without changes.

lib/core_extensions/active_record/schema_migration.rb

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,45 @@
11
module CoreExtensions
22
module ActiveRecord
33
module SchemaMigration
4-
module ClassMethods
54

6-
def create_table
7-
return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
5+
def create_table
6+
return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
87

9-
return if table_exists?
8+
return if table_exists?
109

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) || {}
10+
version_options = connection.internal_string_options_for_primary_key
11+
table_options = {
12+
id: false, options: 'ReplacingMergeTree(ver) ORDER BY (version)', if_not_exists: true
13+
}
14+
full_config = connection.instance_variable_get(:@config) || {}
1615

17-
if full_config[:distributed_service_tables]
18-
table_options.merge!(with_distributed: table_name, sharding_key: 'cityHash64(version)')
16+
if full_config[:distributed_service_tables]
17+
table_options.merge!(with_distributed: table_name, sharding_key: 'cityHash64(version)')
1918

20-
distributed_suffix = "_#{full_config[:distributed_service_tables_suffix] || 'distributed'}"
21-
else
22-
distributed_suffix = ''
23-
end
19+
distributed_suffix = "_#{full_config[:distributed_service_tables_suffix] || 'distributed'}"
20+
else
21+
distributed_suffix = ''
22+
end
2423

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
24+
connection.create_table(table_name + distributed_suffix.to_s, **table_options) do |t|
25+
t.string :version, **version_options
26+
t.column :active, 'Int8', null: false, default: '1'
27+
t.datetime :ver, null: false, default: -> { 'now()' }
3028
end
29+
end
3130

32-
def delete_version(version)
33-
return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
31+
def delete_version(version)
32+
return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
3433

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
34+
im = ::Arel::InsertManager.new(arel_table)
35+
im.insert(arel_table[primary_key] => version.to_s, arel_table['active'] => 0)
36+
connection.insert(im, "#{self.class} Create Rollback Version", primary_key, version)
37+
end
3938

40-
def all_versions
41-
return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
39+
def all_versions
40+
return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)
4241

43-
final.where(active: 1).order(:version).pluck(:version)
44-
end
42+
final.where(active: 1).order(:version).pluck(:version)
4543
end
4644
end
4745
end

lib/tasks/clickhouse.rake

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,18 @@ namespace :clickhouse do
1515
# TODO: deprecated
1616
desc 'Load database schema'
1717
task load: %i[prepare_internal_metadata_table] do
18+
puts 'Warning: `rake clickhouse:schema:load` is deprecated! Use `rake db:schema:load:clickhouse` instead'
1819
simple = ENV['simple'] || ARGV.any? { |a| a.include?('--simple') } ? '_simple' : nil
1920
ActiveRecord::Base.establish_connection(:clickhouse)
20-
ActiveRecord::SchemaMigration.drop_table
21+
connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
22+
connection.schema_migration.drop_table
2123
load(Rails.root.join("db/clickhouse_schema#{simple}.rb"))
2224
end
2325

2426
# TODO: deprecated
2527
desc 'Dump database schema'
2628
task dump: :environment do |_, args|
29+
puts 'Warning: `rake clickhouse:schema:dump` is deprecated! Use `rake db:schema:dump:clickhouse` instead'
2730
simple = ENV['simple'] || args[:simple] || ARGV.any? { |a| a.include?('--simple') } ? '_simple' : nil
2831
filename = Rails.root.join("db/clickhouse_schema#{simple}.rb")
2932
File.open(filename, 'w:utf-8') do |file|
@@ -36,43 +39,38 @@ namespace :clickhouse do
3639
namespace :structure do
3740
desc 'Load database structure'
3841
task load: ['db:check_protected_environments'] do
39-
config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: 'clickhouse')
4042
ClickhouseActiverecord::Tasks.new(config).structure_load(Rails.root.join('db/clickhouse_structure.sql'))
4143
end
4244

4345
desc 'Dump database structure'
4446
task dump: ['db:check_protected_environments'] do
45-
config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: 'clickhouse')
4647
ClickhouseActiverecord::Tasks.new(config).structure_dump(Rails.root.join('db/clickhouse_structure.sql'))
4748
end
4849
end
4950

5051
desc 'Creates the database from DATABASE_URL or config/database.yml'
5152
task create: [] do
52-
config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: 'clickhouse')
53-
ActiveRecord::Tasks::DatabaseTasks.create(config)
53+
puts 'Warning: `rake clickhouse:create` is deprecated! Use `rake db:create:clickhouse` instead'
5454
end
5555

5656
desc 'Drops the database from DATABASE_URL or config/database.yml'
5757
task drop: ['db:check_protected_environments'] do
58-
config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: 'clickhouse')
59-
ActiveRecord::Tasks::DatabaseTasks.drop(config)
58+
puts 'Warning: `rake clickhouse:drop` is deprecated! Use `rake db:drop:clickhouse` instead'
6059
end
6160

6261
desc 'Empty the database from DATABASE_URL or config/database.yml'
6362
task purge: ['db:check_protected_environments'] do
64-
config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: 'clickhouse')
65-
ActiveRecord::Tasks::DatabaseTasks.purge(config)
63+
puts 'Warning: `rake clickhouse:purge` is deprecated! Use `rake db:reset:clickhouse` instead'
6664
end
6765

6866
# desc 'Resets your database using your migrations for the current environment'
6967
task :reset do
70-
Rake::Task['clickhouse:purge'].execute
71-
Rake::Task['clickhouse:migrate'].execute
68+
puts 'Warning: `rake clickhouse:reset` is deprecated! Use `rake db:reset:clickhouse` instead'
7269
end
7370

7471
desc 'Migrate the clickhouse database'
7572
task migrate: %i[prepare_schema_migration_table prepare_internal_metadata_table] do
73+
puts 'Warning: `rake clickhouse:migrate` is deprecated! Use `rake db:migrate:clickhouse` instead'
7674
Rake::Task['db:migrate:clickhouse'].execute
7775
if File.exist? "#{Rails.root}/db/clickhouse_schema_simple.rb"
7876
Rake::Task['clickhouse:schema:dump'].execute(simple: true)
@@ -81,9 +79,14 @@ namespace :clickhouse do
8179

8280
desc 'Rollback the clickhouse database'
8381
task rollback: %i[prepare_schema_migration_table prepare_internal_metadata_table] do
82+
puts 'Warning: `rake clickhouse:rollback` is deprecated! Use `rake db:rollback:clickhouse` instead'
8483
Rake::Task['db:rollback:clickhouse'].execute
8584
if File.exist? "#{Rails.root}/db/clickhouse_schema_simple.rb"
8685
Rake::Task['clickhouse:schema:dump'].execute(simple: true)
8786
end
8887
end
88+
89+
def config
90+
ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: 'clickhouse')
91+
end
8992
end

0 commit comments

Comments
 (0)