diff options
author | Guillermo Iguaran <guilleiguaran@gmail.com> | 2019-07-08 10:20:45 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-08 10:20:45 -0500 |
commit | c00cd7b446aaeb8e2486142938238b26c48ed711 (patch) | |
tree | d33b5cb6ab8bf61f4f04ac5731c54a2336661461 /activerecord/lib/active_record/connection_adapters | |
parent | fe30211574648fa21bff958a3cf952fd0c20c3b1 (diff) | |
parent | 84ff4f6ea2a118b47160e3fe7ed29bff52c2a7a2 (diff) | |
download | rails-c00cd7b446aaeb8e2486142938238b26c48ed711.tar.gz rails-c00cd7b446aaeb8e2486142938238b26c48ed711.tar.bz2 rails-c00cd7b446aaeb8e2486142938238b26c48ed711.zip |
Merge branch 'master' into add_database_exist_method
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters')
11 files changed, 133 insertions, 16 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb index 1b6ba8ce97..93273f6cf6 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb @@ -114,16 +114,16 @@ module ActiveRecord # if the value is a Time responding to usec. def quoted_date(value) if value.acts_like?(:time) - zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal - - if value.respond_to?(zone_conversion_method) - value = value.send(zone_conversion_method) + if ActiveRecord::Base.default_timezone == :utc + value = value.getutc if value.respond_to?(:getutc) && !value.utc? + else + value = value.getlocal if value.respond_to?(:getlocal) end end result = value.to_s(:db) if value.respond_to?(:usec) && value.usec > 0 - "#{result}.#{sprintf("%06d", value.usec)}" + result << "." << sprintf("%06d", value.usec) else result end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 70292e6d63..e9ae8d159e 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -737,7 +737,7 @@ module ActiveRecord end.compact.join(", ") # ...and send them all in one query - execute "SET #{encoding} #{sql_mode_assignment} #{variable_assignments}" + execute("SET #{encoding} #{sql_mode_assignment} #{variable_assignments}", "SCHEMA") end def column_definitions(table_name) # :nodoc: diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 279d0b9e84..2708d2756b 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -5,6 +5,8 @@ module ActiveRecord module ConnectionAdapters # An abstract definition of a column in a table. class Column + include Deduplicable + attr_reader :name, :default, :sql_type_metadata, :null, :default_function, :collation, :comment delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true @@ -76,6 +78,7 @@ module ActiveRecord def hash Column.hash ^ name.hash ^ + name.encoding.hash ^ default.hash ^ sql_type_metadata.hash ^ null.hash ^ @@ -83,6 +86,17 @@ module ActiveRecord collation.hash ^ comment.hash end + + private + def deduplicated + @name = -name + @sql_type_metadata = sql_type_metadata.deduplicate if sql_type_metadata + @default = -default if default + @default_function = -default_function if default_function + @collation = -collation if collation + @comment = -comment if comment + super + end end class NullColumn < Column diff --git a/activerecord/lib/active_record/connection_adapters/deduplicable.rb b/activerecord/lib/active_record/connection_adapters/deduplicable.rb new file mode 100644 index 0000000000..fb2fd60bbc --- /dev/null +++ b/activerecord/lib/active_record/connection_adapters/deduplicable.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module ActiveRecord + module ConnectionAdapters # :nodoc: + module Deduplicable + extend ActiveSupport::Concern + + module ClassMethods + def registry + @registry ||= {} + end + + def new(*) + super.deduplicate + end + end + + def deduplicate + self.class.registry[self] ||= deduplicated + end + alias :-@ :deduplicate + + private + def deduplicated + freeze + end + end + end +end diff --git a/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper.rb b/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper.rb index 234fb25fdf..bcd300f3db 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper.rb @@ -41,13 +41,15 @@ module ActiveRecord case column.sql_type when /\Atimestamp\b/ :timestamp + when /\A(?:enum|set)\b/ + column.sql_type else super end end def schema_limit(column) - super unless /\A(?:tiny|medium|long)?(?:text|blob)/.match?(column.sql_type) + super unless /\A(?:enum|set|(?:tiny|medium|long)?(?:text|blob))\b/.match?(column.sql_type) end def schema_precision(column) diff --git a/activerecord/lib/active_record/connection_adapters/mysql/type_metadata.rb b/activerecord/lib/active_record/connection_adapters/mysql/type_metadata.rb index 9167593064..a7232fa249 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/type_metadata.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/type_metadata.rb @@ -6,9 +6,11 @@ module ActiveRecord class TypeMetadata < DelegateClass(SqlTypeMetadata) # :nodoc: undef to_yaml if method_defined?(:to_yaml) + include Deduplicable + attr_reader :extra - def initialize(type_metadata, extra: "") + def initialize(type_metadata, extra: nil) super(type_metadata) @extra = extra end @@ -25,6 +27,13 @@ module ActiveRecord __getobj__.hash ^ extra.hash end + + private + def deduplicated + __setobj__(__getobj__.deduplicate) + @extra = -extra if extra + super + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb index ec25bb1e19..f1ecf6df30 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb @@ -23,6 +23,29 @@ module ActiveRecord def sql_type super.sub(/\[\]\z/, "") end + + def init_with(coder) + @serial = coder["serial"] + super + end + + def encode_with(coder) + coder["serial"] = @serial + super + end + + def ==(other) + other.is_a?(Column) && + super && + serial? == other.serial? + end + alias :eql? :== + + def hash + Column.hash ^ + super.hash ^ + serial?.hash + end end end PostgreSQLColumn = PostgreSQL::Column # :nodoc: diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb b/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb index 8bdec623af..b7f6479357 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb @@ -7,6 +7,8 @@ module ActiveRecord class TypeMetadata < DelegateClass(SqlTypeMetadata) undef to_yaml if method_defined?(:to_yaml) + include Deduplicable + attr_reader :oid, :fmod def initialize(type_metadata, oid: nil, fmod: nil) @@ -29,6 +31,12 @@ module ActiveRecord oid.hash ^ fmod.hash end + + private + def deduplicated + __setobj__(__getobj__.deduplicate) + super + end end end PostgreSQLTypeMetadata = PostgreSQL::TypeMetadata diff --git a/activerecord/lib/active_record/connection_adapters/schema_cache.rb b/activerecord/lib/active_record/connection_adapters/schema_cache.rb index dbfe1e4a34..7d54fcf9a0 100644 --- a/activerecord/lib/active_record/connection_adapters/schema_cache.rb +++ b/activerecord/lib/active_record/connection_adapters/schema_cache.rb @@ -27,7 +27,6 @@ module ActiveRecord def encode_with(coder) coder["columns"] = @columns - coder["columns_hash"] = @columns_hash coder["primary_keys"] = @primary_keys coder["data_sources"] = @data_sources coder["indexes"] = @indexes @@ -37,12 +36,13 @@ module ActiveRecord def init_with(coder) @columns = coder["columns"] - @columns_hash = coder["columns_hash"] @primary_keys = coder["primary_keys"] @data_sources = coder["data_sources"] @indexes = coder["indexes"] || {} @version = coder["version"] @database_version = coder["database_version"] + + derive_columns_hash_and_deduplicate_values end def primary_keys(table_name) @@ -79,9 +79,7 @@ module ActiveRecord # Get the columns for a table as a hash, key is the column name # value is the column object. def columns_hash(table_name) - @columns_hash[table_name] ||= Hash[columns(table_name).map { |col| - [col.name, col] - }] + @columns_hash[table_name] ||= columns(table_name).index_by(&:name) end # Checks whether the columns hash is already cached for a table. @@ -124,15 +122,38 @@ module ActiveRecord def marshal_dump # if we get current version during initialization, it happens stack over flow. @version = connection.migration_context.current_version - [@version, @columns, @columns_hash, @primary_keys, @data_sources, @indexes, database_version] + [@version, @columns, {}, @primary_keys, @data_sources, @indexes, database_version] end def marshal_load(array) - @version, @columns, @columns_hash, @primary_keys, @data_sources, @indexes, @database_version = array - @indexes = @indexes || {} + @version, @columns, _columns_hash, @primary_keys, @data_sources, @indexes, @database_version = array + @indexes ||= {} + + derive_columns_hash_and_deduplicate_values end private + def derive_columns_hash_and_deduplicate_values + @columns = deep_deduplicate(@columns) + @columns_hash = @columns.transform_values { |columns| columns.index_by(&:name) } + @primary_keys = deep_deduplicate(@primary_keys) + @data_sources = deep_deduplicate(@data_sources) + @indexes = deep_deduplicate(@indexes) + end + + def deep_deduplicate(value) + case value + when Hash + value.transform_keys { |k| deep_deduplicate(k) }.transform_values { |v| deep_deduplicate(v) } + when Array + value.map { |i| deep_deduplicate(i) } + when String, Deduplicable + -value + else + value + end + end + def prepare_data_sources connection.data_sources.each { |source| @data_sources[source] = true } end diff --git a/activerecord/lib/active_record/connection_adapters/sql_type_metadata.rb b/activerecord/lib/active_record/connection_adapters/sql_type_metadata.rb index df28df7a7c..969867e70f 100644 --- a/activerecord/lib/active_record/connection_adapters/sql_type_metadata.rb +++ b/activerecord/lib/active_record/connection_adapters/sql_type_metadata.rb @@ -1,9 +1,13 @@ # frozen_string_literal: true +require "active_record/connection_adapters/deduplicable" + module ActiveRecord # :stopdoc: module ConnectionAdapters class SqlTypeMetadata + include Deduplicable + attr_reader :sql_type, :type, :limit, :precision, :scale def initialize(sql_type: nil, type: nil, limit: nil, precision: nil, scale: nil) @@ -32,6 +36,12 @@ module ActiveRecord precision.hash >> 1 ^ scale.hash >> 2 end + + private + def deduplicated + @sql_type = -sql_type + super + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index 3a1edfc855..f4847eb6c0 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -393,6 +393,7 @@ module ActiveRecord if from_primary_key.is_a?(Array) @definition.primary_keys from_primary_key end + columns(from).each do |column| column_name = options[:rename] ? (options[:rename][column.name] || |