Skip to content

Commit

Permalink
fix schema dumper & schema load
Browse files Browse the repository at this point in the history
  • Loading branch information
PNixx committed Feb 25, 2019
1 parent 9424c83 commit bce303d
Show file tree
Hide file tree
Showing 14 changed files with 92 additions and 36 deletions.
2 changes: 1 addition & 1 deletion clickhouse-activerecord.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
spec.require_paths = ['lib']

spec.add_dependency "bundler", ">= 1.13.4"
spec.add_dependency 'activerecord', '>= 5.0'
spec.add_dependency 'activerecord', '>= 5.2'

spec.add_development_dependency 'bundler', '~> 1.15'
spec.add_development_dependency 'rake', '~> 10.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ module ConnectionAdapters
module Clickhouse
module OID # :nodoc:
class BigInteger < Type::BigInteger # :nodoc:

DEFAULT_LIMIT = 8
def type
:big_integer
end

def limit
DEFAULT_LIMIT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,24 @@ module ActiveRecord
module ConnectionAdapters
module Clickhouse
class SchemaCreation < AbstractAdapter::SchemaCreation# :nodoc:

def visit_AddColumnDefinition(o)
+"ADD COLUMN #{accept(o.column)}"
end

def add_column_options!(sql, options)
if options[:null] == true
sql.gsub(/\s+(.*)/, ' Nullable(\1)')
else
sql
if options[:null] || options[:null].nil?
sql.gsub!(/\s+(.*)/, ' Nullable(\1)')
end
sql.gsub!(/(\sString)\(\d+\)/, '\1')
sql
end

def add_table_options!(create_sql, options)
if engine_sql = options[:options]
create_sql << " ENGINE=#{engine_sql}"
if options[:options].present?
create_sql << " ENGINE = #{options[:options]}"
else
create_sql << " ENGINE=Log()"
create_sql << " ENGINE = Log()"
end

create_sql
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ module ActiveRecord
module ConnectionAdapters
module Clickhouse
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition

def integer(*args, **options)
if options[:limit] == 8
args.each { |name| column(name, :big_integer, options.except(:limit)) }
else
super
end
end

end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,42 @@ def tables(name = nil)
result['data'].flatten
end

def table_options(table)
sql = do_system_execute("SHOW CREATE TABLE #{table}")['data'].try(:first).try(:first)
{ options: sql.gsub(/^(?:.*?)ENGINE = (.*?)$/, '\\1') }
end

# @todo copied from ActiveRecord::ConnectionAdapters::SchemaStatements v5.2.2
# Why version column type of String, but insert to Integer?
def assume_migrated_upto_version(version, migrations_paths)
migrations_paths = Array(migrations_paths)
version = version.to_i
sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)

migrated = ActiveRecord::SchemaMigration.all_versions.map(&:to_i)
versions = migration_context.migration_files.map do |file|
migration_context.parse_migration_filename(file).first.to_i
end

unless migrated.include?(version)
do_execute( "INSERT INTO #{sm_table} (version) VALUES (#{quote(version.to_s)})", 'SchemaMigration', format: nil)
end

inserting = (versions - migrated).select { |v| v < version }
if inserting.any?
if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict."
end
if supports_multi_insert?
do_system_execute insert_versions_sql(inserting)
else
inserting.each do |v|
do_system_execute insert_versions_sql(v)
end
end
end
end

# Not indexes on clickhouse
def indexes(table_name, name = nil)
[]
Expand Down
38 changes: 22 additions & 16 deletions lib/active_record/connection_adapters/clickhouse_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
require 'active_record/connection_adapters/clickhouse/schema_definitions'
require 'active_record/connection_adapters/clickhouse/schema_creation'
require 'active_record/connection_adapters/clickhouse/schema_statements'
require 'net/http'

module ActiveRecord
class Base
class << self
# Establishes a connection to the database that's used by all Active Record objects
def clickhouse_connection(config)
config = config.symbolize_keys
host = config[:host]
host = config[:host] || 'localhost'
port = config[:port] || 8123

if config.key?(:database)
Expand Down Expand Up @@ -124,11 +125,13 @@ def valid_type?(type)

def extract_limit(sql_type) # :nodoc:
case sql_type
when 'Nullable(String)'
255
when /Nullable\(U?Int(8|16)\)/
4
when /Nullable\(U?Int(32|64)\)/
when /(Nullable)?\(?String\)?/
super('String')
when /(Nullable)?\(?U?Int8\)?/
super('int2')
when /(Nullable)?\(?U?Int(16|32)\)?/
super('int4')
when /(Nullable)?\(?U?Int(64)\)?/
8
else
super
Expand All @@ -137,18 +140,17 @@ def extract_limit(sql_type) # :nodoc:

def initialize_type_map(m) # :nodoc:
super
register_class_with_limit m, 'String', Type::String
register_class_with_limit m, 'Nullable(String)', Type::String
register_class_with_limit m, 'Uint8', Type::UnsignedInteger
register_class_with_limit m, %r(String), Type::String
register_class_with_limit m, 'Date', Clickhouse::OID::Date
register_class_with_limit m, 'DateTime', Clickhouse::OID::DateTime
m.alias_type 'UInt16', 'uint4'
m.alias_type 'UInt32', 'uint8'
m.register_type 'UInt64', Clickhouse::OID::BigInteger.new
m.alias_type 'Int8', 'int4'
m.alias_type 'Int16', 'int4'
m.alias_type 'Int32', 'int8'
m.alias_type 'Int64', 'UInt64'
register_class_with_limit m, %r(Uint8), Type::UnsignedInteger
m.alias_type 'UInt16', 'UInt8'
m.alias_type 'UInt32', 'UInt8'
register_class_with_limit m, %r(UInt64), Type::UnsignedInteger
register_class_with_limit m, %r(Int8), Type::Integer
m.alias_type 'Int16', 'Int8'
m.alias_type 'Int32', 'Int8'
register_class_with_limit m, %r(Int64), Type::Integer
end

# Executes insert +sql+ statement in the context of this connection using
Expand All @@ -163,6 +165,10 @@ def primary_key(table_name) #:nodoc:
false
end

def create_schema_dumper(options) # :nodoc:
ClickhouseActiverecord::SchemaDumper.create(self, options)
end

protected

def last_inserted_id(result)
Expand Down
2 changes: 1 addition & 1 deletion lib/clickhouse-activerecord/schema_dumper.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module ClickhouseActiverecord
class SchemaDumper < ActiveRecord::SchemaDumper
class SchemaDumper < ::ActiveRecord::ConnectionAdapters::SchemaDumper

def table(table, stream)
stream.puts " # TABLE: #{table}"
Expand Down
8 changes: 5 additions & 3 deletions spec/cases/migration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@

current_schema = schema(model)

expect(current_schema.keys.count).to eq(2)
expect(current_schema.keys.count).to eq(3)
expect(current_schema).to have_key('id')
expect(current_schema).to have_key('money')
expect(current_schema).to have_key('balance')
expect(current_schema['id'].sql_type).to eq('UInt32')
expect(current_schema['money'].sql_type).to eq('Decimal(16, 4)')
expect(current_schema['money'].sql_type).to eq('Nullable(Decimal(16, 4))')
expect(current_schema['balance'].sql_type).to eq('Decimal(32, 2)')
end
end
end
Expand Down Expand Up @@ -98,7 +100,7 @@
expect(current_schema).to have_key('new_column')
expect(current_schema['id'].sql_type).to eq('UInt32')
expect(current_schema['date'].sql_type).to eq('Date')
expect(current_schema['new_column'].sql_type).to eq('UInt64')
expect(current_schema['new_column'].sql_type).to eq('Nullable(UInt64)')
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
class CreateEventsTable < ActiveRecord::Migration[5.0]
def up
create_table :events, options: 'MergeTree(date, (date, event_name), 8192)' do |t|
t.string :event_name
t.date :date
t.string :event_name, null: false
t.date :date, null: false
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class CreateSomeTable < ActiveRecord::Migration[5.0]
def up
create_table :some, options: 'MergeTree(date, (date), 8192)' do |t|
t.date :date
t.date :date, null: false
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class CreateSomeTable < ActiveRecord::Migration[5.0]
def up
create_table :some, options: 'MergeTree(date, (date), 8192)' do |t|
t.date :date
t.date :date, null: false
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class CreateSomeTable < ActiveRecord::Migration[5.0]
def up
create_table :some, options: 'MergeTree(date, (date), 8192)' do |t|
t.date :date
t.date :date, null: false
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class CreateSomeTable < ActiveRecord::Migration[5.0]
def up
create_table :some do |t|
t.decimal :money, precision: 16, scale: 4
t.decimal :balance, precision: 32, scale: 2, null: false, default: 0
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class CreateSomeTable < ActiveRecord::Migration[5.0]
def up
create_table :some, options: 'MergeTree(date, (date), 8192)' do |t|
t.date :date
t.date :date, null: false
end
end
end
Expand Down

0 comments on commit bce303d

Please sign in to comment.