diff options
Diffstat (limited to 'activerecord/lib')
19 files changed, 53 insertions, 52 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 70b2ca7d7e..b1778732dd 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1762,6 +1762,7 @@ module ActiveRecord # has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) } # has_and_belongs_to_many :categories, ->(post) { # where("default_category = ?", post.default_category) + # } # # === Extensions # diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb index 3d4ad1dd5b..544aec5e8b 100644 --- a/activerecord/lib/active_record/associations/belongs_to_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_association.rb @@ -50,11 +50,8 @@ module ActiveRecord def replace(record) if record raise_on_type_mismatch!(record) - update_counters_on_replace(record) set_inverse_instance(record) @updated = true - else - decrement_counters end replace_keys(record) @@ -80,19 +77,6 @@ module ActiveRecord reflection.counter_cache_column && owner.persisted? end - def update_counters_on_replace(record) - if require_counter_update? && different_target?(record) - owner.instance_variable_set :@_after_replace_counter_called, true - record.increment!(reflection.counter_cache_column, touch: reflection.options[:touch]) - decrement_counters - end - end - - # Checks whether record is different to the current target, without loading it - def different_target?(record) - record._read_attribute(primary_key(record)) != owner._read_attribute(reflection.foreign_key) - end - def replace_keys(record) owner[reflection.foreign_key] = record ? record._read_attribute(primary_key(record)) : nil end diff --git a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb index 3fd2fb5f67..9ae452e7a1 100644 --- a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb @@ -19,10 +19,6 @@ module ActiveRecord owner[reflection.foreign_type] = record ? record.class.polymorphic_name : nil end - def different_target?(record) - super || record.class != klass - end - def inverse_reflection_for(record) reflection.polymorphic_inverse_of(record.class) end diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb index 0166ed98ca..da4cc343eb 100644 --- a/activerecord/lib/active_record/associations/builder/belongs_to.rb +++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb @@ -34,9 +34,7 @@ module ActiveRecord::Associations::Builder # :nodoc: foreign_key = reflection.foreign_key cache_column = reflection.counter_cache_column - if @_after_replace_counter_called ||= false - @_after_replace_counter_called = false - elsif association(reflection.name).target_changed? + if association(reflection.name).target_changed? if reflection.polymorphic? model = attribute_in_database(reflection.foreign_type).try(:constantize) model_was = attribute_before_last_save(reflection.foreign_type).try(:constantize) diff --git a/activerecord/lib/active_record/associations/preloader.rb b/activerecord/lib/active_record/associations/preloader.rb index 5c2ac5b374..d4d1b2a282 100644 --- a/activerecord/lib/active_record/associations/preloader.rb +++ b/activerecord/lib/active_record/associations/preloader.rb @@ -88,7 +88,6 @@ module ActiveRecord if records.empty? [] else - records.uniq! Array.wrap(associations).flat_map { |association| preloaders_on association, records, preload_scope } diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb index ad148efcfe..1305216be2 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb @@ -71,6 +71,11 @@ module ActiveRecord 256 end deprecate :joins_per_query + + private + def bind_params_length + 65535 + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index fdc9ffa688..5b24a467ec 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -46,11 +46,16 @@ module ActiveRecord def select_all(arel, name = nil, binds = [], preparable: nil) arel = arel_from_relation(arel) sql, binds = to_sql_and_binds(arel, binds) + if !prepared_statements || (arel.is_a?(String) && preparable.nil?) preparable = false + elsif binds.length > bind_params_length + sql, binds = unprepared_statement { to_sql_and_binds(arel) } + preparable = false else preparable = visitor.preparable end + if prepared_statements && preparable select_prepared(sql, name, binds) else diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 4a6e915b66..172f0a5c84 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -211,13 +211,13 @@ module ActiveRecord # # ====== Add a backend specific option to the generated SQL (MySQL) # - # create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8') + # create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4') # # generates: # # CREATE TABLE suppliers ( # id bigint auto_increment PRIMARY KEY - # ) ENGINE=InnoDB DEFAULT CHARSET=utf8 + # ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 # # ====== Rename the primary key column # diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb index 26abeea7ed..6fbeaa2b9e 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb @@ -33,7 +33,13 @@ module ActiveRecord def cast(value) if value.is_a?(::String) - value = @pg_decoder.decode(value) + value = begin + @pg_decoder.decode(value) + rescue TypeError + # malformed array string is treated as [], will raise in PG 2.0 gem + # this keeps a consistent implementation + [] + end end type_cast_array(value, :cast) end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 3ee344a249..11593f71c9 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -4,6 +4,14 @@ gem "pg", ">= 0.18", "< 2.0" require "pg" +# Use async_exec instead of exec_params on pg versions before 1.1 +class ::PG::Connection + unless self.public_method_defined?(:async_exec_params) + remove_method :exec_params + alias exec_params async_exec + end +end + require "active_record/connection_adapters/abstract_adapter" require "active_record/connection_adapters/statement_pool" require "active_record/connection_adapters/postgresql/column" @@ -606,7 +614,7 @@ module ActiveRecord type_casted_binds = type_casted_binds(binds) log(sql, name, binds, type_casted_binds) do ActiveSupport::Dependencies.interlock.permit_concurrent_loads do - @connection.async_exec(sql, type_casted_binds) + @connection.exec_params(sql, type_casted_binds) 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 d32fd5ea09..baa0a29afd 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -576,7 +576,7 @@ module ActiveRecord column end else - basic_structure.to_hash + basic_structure.to_a end end diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index ea53324829..807b882bfb 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -1169,7 +1169,7 @@ module ActiveRecord def migrations_path=(path) ActiveSupport::Deprecation.warn \ - "ActiveRecord::Migrator.migrations_paths= is now deprecated and will be removed in Rails 6.0." \ + "`ActiveRecord::Migrator.migrations_path=` is now deprecated and will be removed in Rails 6.0. " \ "You can set the `migrations_paths` on the `connection` instead through the `database.yml`." self.migrations_paths = [path] end diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index 694ff85fa1..9b985e049b 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -375,7 +375,7 @@ module ActiveRecord # default values when instantiating the Active Record object for this table. def column_defaults load_schema - @column_defaults ||= _default_attributes.to_hash + @column_defaults ||= _default_attributes.deep_dup.to_hash end def _default_attributes # :nodoc: diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 86e5d14c81..806f8a1cbb 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -349,7 +349,7 @@ module ActiveRecord stmt = Arel::UpdateManager.new - stmt.set Arel.sql(@klass.sanitize_sql_for_assignment(updates)) + stmt.set Arel.sql(@klass.sanitize_sql_for_assignment(updates, table.name)) stmt.table(table) if has_join_values? || offset_value @@ -377,14 +377,14 @@ module ActiveRecord updates = counters.map do |counter_name, value| operator = value < 0 ? "-" : "+" - quoted_column = connection.quote_column_name(counter_name) + quoted_column = connection.quote_table_name_for_assignment(table.name, counter_name) "#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{value.abs}" end if touch names = touch if touch != true touch_updates = klass.touch_attributes_with_time(*names) - updates << klass.sanitize_sql_for_assignment(touch_updates) unless touch_updates.empty? + updates << klass.sanitize_sql_for_assignment(touch_updates, table.name) unless touch_updates.empty? end update_all updates.join(", ") @@ -414,14 +414,12 @@ module ActiveRecord # Person.where(name: 'David').touch_all # # => "UPDATE \"people\" SET \"updated_at\" = '2018-01-04 22:55:23.132670' WHERE \"people\".\"name\" = 'David'" def touch_all(*names, time: nil) - updates = touch_attributes_with_time(*names, time: time) - if klass.locking_enabled? - quoted_locking_column = connection.quote_column_name(klass.locking_column) - updates = sanitize_sql_for_assignment(updates) + ", #{quoted_locking_column} = COALESCE(#{quoted_locking_column}, 0) + 1" + names << { time: time } + update_counters(klass.locking_column => 1, touch: names) + else + update_all klass.touch_attributes_with_time(*names, time: time) end - - update_all(updates) end # Destroys the records by instantiating each diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 0fabfe5518..930e4377ff 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -416,7 +416,7 @@ module ActiveRecord raise UnknownPrimaryKey.new(@klass) if primary_key.nil? expects_array = ids.first.kind_of?(Array) - return ids.first if expects_array && ids.first.empty? + return [] if expects_array && ids.first.empty? ids = ids.flatten.compact.uniq diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index cb70b8bcde..f734cd0ad8 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -57,14 +57,10 @@ module ActiveRecord end def build_bind_attribute(column_name, value) - attr = build_query_attribute(column_name, value) + attr = Relation::QueryAttribute.new(column_name.to_s, value, table.type(column_name)) Arel::Nodes::BindParam.new(attr) end - def build_query_attribute(column_name, value) - Relation::QueryAttribute.new(column_name.to_s, value, table.type(column_name)) - end - protected def expand_from_hash(attributes) return ["1=0"] if attributes.empty? diff --git a/activerecord/lib/active_record/relation/predicate_builder/array_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/array_handler.rb index 0895b9fba6..fadb3c420d 100644 --- a/activerecord/lib/active_record/relation/predicate_builder/array_handler.rb +++ b/activerecord/lib/active_record/relation/predicate_builder/array_handler.rb @@ -22,8 +22,8 @@ module ActiveRecord when 1 then predicate_builder.build(attribute, values.first) else values.map! do |v| - attr = predicate_builder.build_query_attribute(attribute.name, v) - attr.value_for_database if attr.boundable? + bind = predicate_builder.build_bind_attribute(attribute.name, v) + bind if bind.value.boundable? end.compact! values.empty? ? NullPredicate : attribute.in(values) end diff --git a/activerecord/lib/active_record/result.rb b/activerecord/lib/active_record/result.rb index 3b2556b1c8..da6d10b6ec 100644 --- a/activerecord/lib/active_record/result.rb +++ b/activerecord/lib/active_record/result.rb @@ -21,7 +21,7 @@ module ActiveRecord # ] # # # Get an array of hashes representing the result (column => value): - # result.to_hash + # result.to_a # # => [{"id" => 1, "title" => "title_1", "body" => "body_1"}, # {"id" => 2, "title" => "title_2", "body" => "body_2"}, # ... @@ -65,9 +65,12 @@ module ActiveRecord end end - # Returns an array of hashes representing each row record. def to_hash - hash_rows + ActiveSupport::Deprecation.warn(<<-MSG.squish) + `ActiveRecord::Result#to_hash` has been renamed to `to_a`. + `to_hash` is deprecated and will be removed in Rails 6.1. + MSG + to_a end alias :map! :map @@ -83,6 +86,8 @@ module ActiveRecord hash_rows end + alias :to_a :to_ary + def [](idx) hash_rows[idx] end diff --git a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb index 533e6953a4..029f763158 100644 --- a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb @@ -61,7 +61,7 @@ module ActiveRecord ActiveRecord::Base.dump_schemas end - args = ["-s", "-x", "-O", "-f", filename] + args = ["-s", "-X", "-x", "-O", "-f", filename] args.concat(Array(extra_flags)) if extra_flags unless search_path.blank? args += search_path.split(",").map do |part| |