diff options
Diffstat (limited to 'activerecord')
23 files changed, 185 insertions, 179 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 7b34cb8ccd..be3a461eda 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,21 @@ +* Add `config.active_record.warn_on_records_fetched_greater_than` option + + When set to an integer, a warning will be logged whenever a result set + larger than the specified size is returned by a query. Fixes #16463 + + *Jason Nochlin* + +* Ignore psqlrc when loading database structure. + + *Jason Weathered* + +* Fix referencing wrong table aliases while joining tables of has many through + association (only when calling calculation methods). + + Fixes #19276. + + *pinglamb* + * Correctly persist a serialized attribute that has been returned to its default value by an in-place modification. diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index cc03e37a12..93550a69f1 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -258,7 +258,7 @@ module ActiveRecord #:nodoc: # <tt>attributes=</tt> method. The +errors+ property of this exception contains an array of # AttributeAssignmentError # objects that should be inspected to determine which attributes triggered the errors. - # * RecordInvalid - raised by save! and create! when the record is invalid. + # * RecordInvalid - raised by <tt>save!</tt> and <tt>create!</tt> when the record is invalid. # * RecordNotFound - No record responded to the +find+ method. Either the row with the given ID doesn't exist # or the row didn't meet the additional restrictions. Some +find+ calls do not raise this exception to signal # nothing was found, please check its documentation for further details. 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 d42f9a894b..72e019066e 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -652,7 +652,7 @@ module ActiveRecord alias :add_belongs_to :add_reference # Removes the reference(s). Also removes a +type+ column if one exists. - # <tt>remove_reference</tt>, <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable. + # <tt>remove_reference</tt> and <tt>remove_belongs_to</tt> are acceptable. # # ====== Remove the reference # diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/array_parser.rb b/activerecord/lib/active_record/connection_adapters/postgresql/array_parser.rb deleted file mode 100644 index 1b74c039ce..0000000000 --- a/activerecord/lib/active_record/connection_adapters/postgresql/array_parser.rb +++ /dev/null @@ -1,93 +0,0 @@ -module ActiveRecord - module ConnectionAdapters - module PostgreSQL - module ArrayParser # :nodoc: - - DOUBLE_QUOTE = '"' - BACKSLASH = "\\" - COMMA = ',' - BRACKET_OPEN = '{' - BRACKET_CLOSE = '}' - - def parse_pg_array(string) # :nodoc: - local_index = 0 - array = [] - while(local_index < string.length) - case string[local_index] - when BRACKET_OPEN - local_index,array = parse_array_contents(array, string, local_index + 1) - when BRACKET_CLOSE - return array - end - local_index += 1 - end - - array - end - - private - - def parse_array_contents(array, string, index) - is_escaping = false - is_quoted = false - was_quoted = false - current_item = '' - - local_index = index - while local_index - token = string[local_index] - if is_escaping - current_item << token - is_escaping = false - else - if is_quoted - case token - when DOUBLE_QUOTE - is_quoted = false - was_quoted = true - when BACKSLASH - is_escaping = true - else - current_item << token - end - else - case token - when BACKSLASH - is_escaping = true - when COMMA - add_item_to_array(array, current_item, was_quoted) - current_item = '' - was_quoted = false - when DOUBLE_QUOTE - is_quoted = true - when BRACKET_OPEN - internal_items = [] - local_index,internal_items = parse_array_contents(internal_items, string, local_index + 1) - array.push(internal_items) - when BRACKET_CLOSE - add_item_to_array(array, current_item, was_quoted) - return local_index,array - else - current_item << token - end - end - end - - local_index += 1 - end - return local_index,array - end - - def add_item_to_array(array, current_item, quoted) - return if !quoted && current_item.length == 0 - - if !quoted && current_item == 'NULL' - array.push nil - else - array.push current_item - end - end - end - end - end -end 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 f486c5ecb7..3de794f797 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb @@ -5,29 +5,20 @@ module ActiveRecord class Array < Type::Value # :nodoc: include Type::Helpers::Mutable - # Loads pg_array_parser if available. String parsing can be - # performed quicker by a native extension, which will not create - # a large amount of Ruby objects that will need to be garbage - # collected. pg_array_parser has a C and Java extension - begin - require 'pg_array_parser' - include PgArrayParser - rescue LoadError - require 'active_record/connection_adapters/postgresql/array_parser' - include PostgreSQL::ArrayParser - end - attr_reader :subtype, :delimiter delegate :type, :user_input_in_time_zone, :limit, to: :subtype def initialize(subtype, delimiter = ',') @subtype = subtype @delimiter = delimiter + + @pg_encoder = PG::TextEncoder::Array.new name: "#{type}[]", delimiter: delimiter + @pg_decoder = PG::TextDecoder::Array.new name: "#{type}[]", delimiter: delimiter end def deserialize(value) if value.is_a?(::String) - type_cast_array(parse_pg_array(value), :deserialize) + type_cast_array(@pg_decoder.decode(value), :deserialize) else super end @@ -35,14 +26,14 @@ module ActiveRecord def cast(value) if value.is_a?(::String) - value = parse_pg_array(value) + value = @pg_decoder.decode(value) end type_cast_array(value, :cast) end def serialize(value) if value.is_a?(::Array) - cast_value_for_database(value) + @pg_encoder.encode(type_cast_array(value, :serialize)) else super end @@ -63,41 +54,6 @@ module ActiveRecord @subtype.public_send(method, value) end end - - def cast_value_for_database(value) - if value.is_a?(::Array) - casted_values = value.map { |item| cast_value_for_database(item) } - "{#{casted_values.join(delimiter)}}" - else - quote_and_escape(subtype.serialize(value)) - end - end - - ARRAY_ESCAPE = "\\" * 2 * 2 # escape the backslash twice for PG arrays - - def quote_and_escape(value) - case value - when ::String - if string_requires_quoting?(value) - value = value.gsub(/\\/, ARRAY_ESCAPE) - value.gsub!(/"/,"\\\"") - %("#{value}") - else - value - end - when nil then "NULL" - else value - end - end - - # See http://www.postgresql.org/docs/9.2/static/arrays.html#ARRAYS-IO - # for a list of all cases in which strings will be quoted. - def string_requires_quoting?(string) - string.empty? || - string == "NULL" || - string =~ /[\{\}"\\\s]/ || - string.include?(delimiter) - end end end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb index 9b3de41fab..9d421d6975 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb @@ -19,7 +19,7 @@ module ActiveRecord enums, nodes = nodes.partition { |row| row['typtype'] == 'e' } domains, nodes = nodes.partition { |row| row['typtype'] == 'd' } arrays, nodes = nodes.partition { |row| row['typinput'] == 'array_in' } - composites, nodes = nodes.partition { |row| row['typelem'] != '0' } + composites, nodes = nodes.partition { |row| row['typelem'].to_i != 0 } mapped.each { |row| register_mapped_type(row) } enums.each { |row| register_enum_type(row) } diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb index eeb141dd1e..cb0b9cdbe9 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb @@ -129,8 +129,8 @@ module ActiveRecord result.map do |row| index_name = row[0] - unique = row[1] == 't' - indkey = row[2].split(" ") + unique = row[1] + indkey = row[2].split(" ").map(&:to_i) inddef = row[3] oid = row[4] @@ -164,7 +164,7 @@ module ActiveRecord type_metadata = fetch_type_metadata(column_name, type, oid, fmod) default_value = extract_value_from_default(default) default_function = extract_default_function(default_value, default) - new_column(column_name, default_value, type_metadata, notnull == 'f', default_function) + new_column(column_name, default_value, type_metadata, !notnull, default_function) end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 96a3ac7c31..e616cee5eb 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -1,3 +1,7 @@ +# Make sure we're using pg high enough for type casts and Ruby 2.2+ compatibility +gem 'pg', '~> 0.18' +require 'pg' + require "active_record/connection_adapters/abstract_adapter" require "active_record/connection_adapters/postgresql/column" require "active_record/connection_adapters/postgresql/database_statements" @@ -12,10 +16,6 @@ require "active_record/connection_adapters/statement_pool" require 'arel/visitors/bind_visitor' -# Make sure we're using pg high enough for Ruby 2.2+ compatibility -gem 'pg', '~> 0.18' -require 'pg' - require 'ipaddr' module ActiveRecord @@ -278,8 +278,7 @@ module ActiveRecord @table_alias_length = nil connect - add_pg_decoders - + add_pg_encoders @statements = StatementPool.new @connection, self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }) @@ -287,6 +286,8 @@ module ActiveRecord raise "Your version of PostgreSQL (#{postgresql_version}) is too old, please upgrade!" end + add_pg_decoders + @type_map = Type::HashLookupTypeMap.new initialize_type_map(type_map) @local_tz = execute('SHOW TIME ZONE', 'SCHEMA').first["TimeZone"] @@ -798,11 +799,20 @@ module ActiveRecord ) end_sql execute_and_clear(sql, "SCHEMA", []) do |result| - result.getvalue(0, 0) == 't' + result.getvalue(0, 0) end end end + def add_pg_encoders + map = PG::TypeMapByClass.new + map[Integer] = PG::TextEncoder::Integer.new + map[TrueClass] = PG::TextEncoder::Boolean.new + map[FalseClass] = PG::TextEncoder::Boolean.new + map[Float] = PG::TextEncoder::Float.new + @connection.type_map_for_queries = map + end + def add_pg_decoders coders_by_name = { 'int2' => PG::TextDecoder::Integer, @@ -814,12 +824,12 @@ module ActiveRecord 'bool' => PG::TextDecoder::Boolean, } query = <<-SQL - SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype + SELECT t.oid, t.typname FROM pg_type as t SQL coders = execute_and_clear(query, "SCHEMA", []) do |result| result - .map { |row| construct_coder(row, coders_by_name['typname']) } + .map { |row| construct_coder(row, coders_by_name[row['typname']]) } .compact end @@ -830,7 +840,7 @@ module ActiveRecord def construct_coder(row, coder_class) return unless coder_class - coder_class.new(oid: row['oid'], name: row['typname']) + coder_class.new(oid: row['oid'].to_i, name: row['typname']) end ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :postgresql) diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 9a39a0e919..09d7ac374a 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -94,6 +94,15 @@ module ActiveRecord mattr_accessor :dump_schemas, instance_writer: false self.dump_schemas = :schema_search_path + ## + # :singleton-method: + # Specify a threshold for the size of query result sets. If the number of + # records in the set exceeds the threshold, a warning is logged. This can + # be used to identify queries which load thousands of records and + # potentially cause memory bloat. + mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false + self.warn_on_records_fetched_greater_than = nil + mattr_accessor :maintain_test_schema, instance_accessor: false mattr_accessor :belongs_to_required_by_default, instance_accessor: false diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index f1bdbc845c..7e907beec0 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -102,6 +102,14 @@ module ActiveRecord end end + initializer "active_record.warn_on_records_fetched_greater_than" do + if config.active_record.warn_on_records_fetched_greater_than + ActiveSupport.on_load(:active_record) do + require 'active_record/relation/record_fetch_warning' + end + end + end + initializer "active_record.set_configs" do |app| ActiveSupport.on_load(:active_record) do app.config.active_record.each do |k,v| diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 7bd091b66c..3f747a20b3 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -378,7 +378,7 @@ module ActiveRecord def construct_relation_for_association_calculations from = arel.froms.first if Arel::Table === from - apply_join_dependency(self, construct_join_dependency) + apply_join_dependency(self, construct_join_dependency(joins_values)) else # FIXME: as far as I can tell, `from` will always be an Arel::Table. # There are no tests that test this branch, but presumably it's diff --git a/activerecord/lib/active_record/relation/record_fetch_warning.rb b/activerecord/lib/active_record/relation/record_fetch_warning.rb new file mode 100644 index 0000000000..14e1bf89fa --- /dev/null +++ b/activerecord/lib/active_record/relation/record_fetch_warning.rb @@ -0,0 +1,49 @@ +module ActiveRecord + class Relation + module RecordFetchWarning + # When this module is prepended to ActiveRecord::Relation and + # `config.active_record.warn_on_records_fetched_greater_than` is + # set to an integer, if the number of records a query returns is + # greater than the value of `warn_on_records_fetched_greater_than`, + # a warning is logged. This allows for the detection of queries that + # return a large number of records, which could cause memory bloat. + # + # In most cases, fetching large number of records can be performed + # efficiently using the ActiveRecord::Batches methods. + # See active_record/lib/relation/batches.rb for more information. + def exec_queries + QueryRegistry.reset + + super.tap do + if logger && warn_on_records_fetched_greater_than + if @records.length > warn_on_records_fetched_greater_than + logger.warn "Query fetched #{@records.size} #{@klass} records: #{QueryRegistry.queries.join(";")}" + end + end + end + end + + ActiveSupport::Notifications.subscribe("sql.active_record") do |*args| + payload = args.last + + QueryRegistry.queries << payload[:sql] + end + + class QueryRegistry # :nodoc: + extend ActiveSupport::PerThreadRegistry + + attr_accessor :queries + + def initialize + reset + end + + def reset + @queries = [] + end + end + end + end +end + +ActiveRecord::Relation.prepend ActiveRecord::Relation::RecordFetchWarning diff --git a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb index 435708a421..d7da95c8a9 100644 --- a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb @@ -67,7 +67,7 @@ module ActiveRecord def structure_load(filename) set_psql_env - Kernel.system("psql -q -f #{Shellwords.escape(filename)} #{configuration['database']}") + Kernel.system("psql -X -q -f #{Shellwords.escape(filename)} #{configuration['database']}") end private diff --git a/activerecord/test/cases/adapters/postgresql/infinity_test.rb b/activerecord/test/cases/adapters/postgresql/infinity_test.rb index 24199c69b8..d9d7832094 100644 --- a/activerecord/test/cases/adapters/postgresql/infinity_test.rb +++ b/activerecord/test/cases/adapters/postgresql/infinity_test.rb @@ -24,6 +24,15 @@ class PostgresqlInfinityTest < ActiveRecord::TestCase assert_equal Float::INFINITY, record.float end + test "type casting string on a float column" do + record = PostgresqlInfinity.new(float: 'Infinity') + assert_equal Float::INFINITY, record.float + record = PostgresqlInfinity.new(float: '-Infinity') + assert_equal(-Float::INFINITY, record.float) + record = PostgresqlInfinity.new(float: 'NaN') + assert_send [record.float, :nan?] + end + test "update_all with infinity on a float column" do record = PostgresqlInfinity.create! PostgresqlInfinity.update_all(float: Float::INFINITY) diff --git a/activerecord/test/cases/adapters/postgresql/numbers_test.rb b/activerecord/test/cases/adapters/postgresql/numbers_test.rb index 093b81fe8d..d8e01e3b89 100644 --- a/activerecord/test/cases/adapters/postgresql/numbers_test.rb +++ b/activerecord/test/cases/adapters/postgresql/numbers_test.rb @@ -31,7 +31,7 @@ class PostgresqlNumberTest < ActiveRecord::TestCase assert_equal 123456.789, first.double assert_equal(-::Float::INFINITY, second.single) assert_equal ::Float::INFINITY, second.double - assert_same ::Float::NAN, third.double + assert_send [third.double, :nan?] end def test_update diff --git a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb index a934180a43..9a1b889d4d 100644 --- a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb +++ b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb @@ -68,7 +68,7 @@ module ActiveRecord def test_insert_sql_with_proprietary_returning_clause with_example_table do id = @connection.insert_sql("insert into ex (number) values(5150)", nil, "number") - assert_equal "5150", id + assert_equal 5150, id end end @@ -106,21 +106,21 @@ module ActiveRecord connection = connection_without_insert_returning id = connection.insert_sql("insert into postgresql_partitioned_table_parent (number) VALUES (1)") expect = connection.query('select max(id) from postgresql_partitioned_table_parent').first.first - assert_equal expect, id + assert_equal expect.to_i, id end def test_exec_insert_with_returning_disabled connection = connection_without_insert_returning result = connection.exec_insert("insert into postgresql_partitioned_table_parent (number) VALUES (1)", nil, [], 'id', 'postgresql_partitioned_table_parent_id_seq') expect = connection.query('select max(id) from postgresql_partitioned_table_parent').first.first - assert_equal expect, result.rows.first.first + assert_equal expect.to_i, result.rows.first.first end def test_exec_insert_with_returning_disabled_and_no_sequence_name_given connection = connection_without_insert_returning result = connection.exec_insert("insert into postgresql_partitioned_table_parent (number) VALUES (1)", nil, [], 'id') expect = connection.query('select max(id) from postgresql_partitioned_table_parent').first.first - assert_equal expect, result.rows.first.first + assert_equal expect.to_i, result.rows.first.first end def test_sql_for_insert_with_returning_disabled @@ -238,7 +238,7 @@ module ActiveRecord result = @connection.exec_query('SELECT number FROM ex WHERE number = 10') assert_equal 1, result.rows.length - assert_equal "10", result.rows.last.last + assert_equal 10, result.rows.last.last end end @@ -274,7 +274,7 @@ module ActiveRecord assert_equal 1, result.rows.length assert_equal 2, result.columns.length - assert_equal [['1', 'foo']], result.rows + assert_equal [[1, 'foo']], result.rows end end @@ -288,7 +288,7 @@ module ActiveRecord assert_equal 1, result.rows.length assert_equal 2, result.columns.length - assert_equal [['1', 'foo']], result.rows + assert_equal [[1, 'foo']], result.rows end end @@ -304,7 +304,7 @@ module ActiveRecord assert_equal 1, result.rows.length assert_equal 2, result.columns.length - assert_equal [['1', 'foo']], result.rows + assert_equal [[1, 'foo']], result.rows end end diff --git a/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb b/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb index d76e762815..7200ed2771 100644 --- a/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb +++ b/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb @@ -106,6 +106,6 @@ class PostgreSQLReferentialIntegrityTest < ActiveRecord::TestCase private def assert_transaction_is_not_broken - assert_equal "1", @connection.select_value("SELECT 1") + assert_equal 1, @connection.select_value("SELECT 1") end end diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb index c1be340e7c..f925dcad97 100644 --- a/activerecord/test/cases/adapters/postgresql/schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb @@ -384,16 +384,16 @@ class SchemaTest < ActiveRecord::TestCase def test_reset_pk_sequence sequence_name = "#{SCHEMA_NAME}.#{UNMATCHED_SEQUENCE_NAME}" @connection.execute "SELECT setval('#{sequence_name}', 123)" - assert_equal "124", @connection.select_value("SELECT nextval('#{sequence_name}')") + assert_equal 124, @connection.select_value("SELECT nextval('#{sequence_name}')") @connection.reset_pk_sequence!("#{SCHEMA_NAME}.#{UNMATCHED_PK_TABLE_NAME}") - assert_equal "1", @connection.select_value("SELECT nextval('#{sequence_name}')") + assert_equal 1, @connection.select_value("SELECT nextval('#{sequence_name}')") end def test_set_pk_sequence table_name = "#{SCHEMA_NAME}.#{PK_TABLE_NAME}" _, sequence_name = @connection.pk_and_sequence_for table_name @connection.set_pk_sequence! table_name, 123 - assert_equal "124", @connection.select_value("SELECT nextval('#{sequence_name}')") + assert_equal 124, @connection.select_value("SELECT nextval('#{sequence_name}')") @connection.reset_pk_sequence! table_name end diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb index 9e428098e4..0791dde1f2 100644 --- a/activerecord/test/cases/batches_test.rb +++ b/activerecord/test/cases/batches_test.rb @@ -190,8 +190,9 @@ class EachTest < ActiveRecord::TestCase def test_find_in_batches_should_use_any_column_as_primary_key_when_start_is_not_specified assert_queries(Subscriber.count + 1) do - Subscriber.find_each(:batch_size => 1) do |subscriber| - assert_kind_of Subscriber, subscriber + Subscriber.find_in_batches(batch_size: 1) do |batch| + assert_kind_of Array, batch + assert_kind_of Subscriber, batch.first end end end diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index f0393aa6b1..8fc996ee74 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -11,6 +11,10 @@ require 'models/minivan' require 'models/speedometer' require 'models/ship_part' require 'models/treasure' +require 'models/developer' +require 'models/comment' +require 'models/rating' +require 'models/post' class NumericData < ActiveRecord::Base self.table_name = 'numeric_data' @@ -636,4 +640,11 @@ class CalculationsTest < ActiveRecord::TestCase Client.update_all(client_of: nil) assert_equal({ nil => Client.count }, Client.group(:firm).count) end + + def test_should_reference_correct_aliases_while_joining_tables_of_has_many_through_association + assert_nothing_raised ActiveRecord::StatementInvalid do + developer = Developer.create!(name: 'developer') + developer.ratings.includes(comment: :post).where(posts: { id: 1 }).count + end + end end diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index 744f9edc47..2f0b5df286 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -184,7 +184,7 @@ class QueryCacheTest < ActiveRecord::TestCase # Oracle adapter returns count() as Fixnum or Float if current_adapter?(:OracleAdapter) assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") - elsif current_adapter?(:SQLite3Adapter, :Mysql2Adapter) + elsif current_adapter?(:SQLite3Adapter, :Mysql2Adapter, :PostgreSQLAdapter) # Future versions of the sqlite3 adapter will return numeric assert_instance_of Fixnum, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") diff --git a/activerecord/test/cases/relation/record_fetch_warning_test.rb b/activerecord/test/cases/relation/record_fetch_warning_test.rb new file mode 100644 index 0000000000..62f0a7cc49 --- /dev/null +++ b/activerecord/test/cases/relation/record_fetch_warning_test.rb @@ -0,0 +1,28 @@ +require 'cases/helper' +require 'models/post' + +module ActiveRecord + class RecordFetchWarningTest < ActiveRecord::TestCase + fixtures :posts + + def test_warn_on_records_fetched_greater_than + original_logger = ActiveRecord::Base.logger + orginal_warn_on_records_fetched_greater_than = ActiveRecord::Base.warn_on_records_fetched_greater_than + + log = StringIO.new + ActiveRecord::Base.logger = ActiveSupport::Logger.new(log) + ActiveRecord::Base.logger.level = Logger::WARN + + require 'active_record/relation/record_fetch_warning' + + ActiveRecord::Base.warn_on_records_fetched_greater_than = 1 + + Post.all.to_a + + assert_match(/Query fetched/, log.string) + ensure + ActiveRecord::Base.logger = original_logger + ActiveRecord::Base.warn_on_records_fetched_greater_than = orginal_warn_on_records_fetched_greater_than + end + end +end diff --git a/activerecord/test/cases/tasks/postgresql_rake_test.rb b/activerecord/test/cases/tasks/postgresql_rake_test.rb index d45fb07417..084302cde5 100644 --- a/activerecord/test/cases/tasks/postgresql_rake_test.rb +++ b/activerecord/test/cases/tasks/postgresql_rake_test.rb @@ -261,14 +261,14 @@ module ActiveRecord def test_structure_load filename = "awesome-file.sql" - Kernel.expects(:system).with("psql -q -f #{filename} my-app-db") + Kernel.expects(:system).with("psql -X -q -f #{filename} my-app-db") ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename) end def test_structure_load_accepts_path_with_spaces filename = "awesome file.sql" - Kernel.expects(:system).with("psql -q -f awesome\\ file.sql my-app-db") + Kernel.expects(:system).with("psql -X -q -f awesome\\ file.sql my-app-db") ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename) end |