lib/ridgepole/diff.rb in ridgepole-0.7.1.beta2 vs lib/ridgepole/diff.rb in ridgepole-0.7.1.beta3
- old
+ new
@@ -1,6 +1,8 @@
class Ridgepole::Diff
+ PRIMARY_KEY_OPTIONS = %i(id limit default null precision scale collation unsigned comment).freeze
+
def initialize(options = {})
@options = options
@logger = Ridgepole::Logger.instance
end
@@ -124,19 +126,67 @@
if @options[:dump_without_table_options]
from.delete(:options)
to.delete(:options)
end
+ pk_attrs = build_primary_key_attrs_if_changed(from, to, table_name)
+ if pk_attrs
+ if @options[:allow_pk_change]
+ table_delta[:primary_key_definition] = {change: {id: pk_attrs}}
+ else
+ @logger.warn(<<-EOS)
+[WARNING] Primary key definition of `#{table_name}` differ but `allow_pk_change` option is false
+ from: #{from.slice(*PRIMARY_KEY_OPTIONS)}
+ to: #{to.slice(*PRIMARY_KEY_OPTIONS)}
+ EOS
+ end
+ from = from.except(*PRIMARY_KEY_OPTIONS)
+ to = to.except(*PRIMARY_KEY_OPTIONS)
+ end
+
unless from == to
@logger.warn(<<-EOS)
[WARNING] No difference of schema configuration for table `#{table_name}` but table options differ.
from: #{from}
to: #{to}
EOS
end
end
+ def convert_to_primary_key_attrs(column_options)
+ options = column_options.dup
+
+ if options[:id]
+ type = options.delete(:id)
+ else
+ type = Ridgepole::DSLParser::TableDefinition::DEFAULT_PRIMARY_KEY_TYPE
+ end
+
+ if [:integer, :bigint].include?(type) && !options.key?(:default)
+ options[:auto_increment] = true
+ end
+
+ {type: type, options: options}
+ end
+
+ def build_attrs_if_changed(to_attrs, from_attrs, table_name, primary_key: false)
+ normalize_column_options!(from_attrs, primary_key)
+ normalize_column_options!(to_attrs, primary_key)
+
+ unless compare_column_attrs(from_attrs, to_attrs)
+ new_to_attrs = fix_change_column_options(table_name, from_attrs, to_attrs)
+ end
+ new_to_attrs
+ end
+
+ def build_primary_key_attrs_if_changed(from, to, table_name)
+ from_column_attrs = convert_to_primary_key_attrs(from.slice(*PRIMARY_KEY_OPTIONS))
+ to_column_attrs = convert_to_primary_key_attrs(to.slice(*PRIMARY_KEY_OPTIONS))
+ return if from_column_attrs == to_column_attrs
+ build_attrs_if_changed(to_column_attrs, from_column_attrs, table_name, primary_key: true)
+ end
+
def scan_definition_change(from, to, from_indices, table_name, table_options, table_delta)
from = (from || {}).dup
to = (to || {}).dup
definition_delta = {}
@@ -148,16 +198,13 @@
priv_column_name = table_options[:primary_key] || 'id'
end
to.each do |column_name, to_attrs|
if (from_attrs = from.delete(column_name))
- normalize_column_options!(from_attrs)
- normalize_column_options!(to_attrs)
-
- unless compare_column_attrs(from_attrs, to_attrs)
+ to_attrs = build_attrs_if_changed(to_attrs, from_attrs, table_name)
+ if to_attrs
definition_delta[:change] ||= {}
- to_attrs = fix_change_column_options(table_name, from_attrs, to_attrs)
definition_delta[:change][column_name] = to_attrs
end
else
definition_delta[:add] ||= {}
to_attrs[:options] ||= {}
@@ -302,17 +349,17 @@
else
true
end
end
- def normalize_column_options!(attrs)
+ def normalize_column_options!(attrs, primary_key = false)
opts = attrs[:options]
- opts[:null] = true unless opts.has_key?(:null)
+ opts[:null] = true if not opts.has_key?(:null) and not primary_key
default_limit = Ridgepole::DefaultsLimit.default_limit(attrs[:type], @options)
opts.delete(:limit) if opts[:limit] == default_limit
# XXX: MySQL only?
- if not opts.has_key?(:default)
+ if not opts.has_key?(:default) and not primary_key
opts[:default] = nil
end
if Ridgepole::ConnectionAdapters.mysql?
opts[:unsigned] = false unless opts.has_key?(:unsigned)