Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Rails 5.2] Fix failing tests #662

Merged
merged 20 commits into from
Jan 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ script:
- docker-compose run ci
matrix:
include:
- env: TARGET_VERSION=2.3.8
- env: TARGET_VERSION=2.4.5
- env: TARGET_VERSION=2.5.3
- env: TARGET_VERSION=2.6.0
- name: 2.3.8
env: TARGET_VERSION=2.3.8
- name: 2.4.5
env: TARGET_VERSION=2.4.5
- name: 2.5.3
env: TARGET_VERSION=2.5.3
- name: 2.6.0
env: TARGET_VERSION=2.6.0
16 changes: 8 additions & 8 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ dependencies:
- openssl version
- sudo ./test/bin/install-freetds.sh
- tsql -C
- rvm-exec 2.2.10 bundle install
- rvm-exec 2.3.7 bundle install
- rvm-exec 2.4.4 bundle install
- rvm-exec 2.5.1 bundle install
- rvm-exec 2.3.8 bundle install
- rvm-exec 2.4.5 bundle install
- rvm-exec 2.5.3 bundle install
- rvm-exec 2.6.0 bundle install

database:
override:
Expand All @@ -32,7 +32,7 @@ database:

test:
override:
- rvm-exec 2.2.10 bundle exec rake test
- rvm-exec 2.3.7 bundle exec rake test
- rvm-exec 2.4.4 bundle exec rake test
- rvm-exec 2.5.1 bundle exec rake test
- rvm-exec 2.3.8 bundle exec rake test
- rvm-exec 2.4.5 bundle exec rake test
- rvm-exec 2.5.3 bundle exec rake test
- rvm-exec 2.6.0 bundle exec rake test
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ module Calculations
def build_count_subquery(relation, column_name, distinct)
super(relation.unscope(:order), column_name, distinct)
end

def type_cast_calculated_value(value, type, operation = nil)
case operation
when "count" then value.to_i
when "sum" then type.deserialize(value || 0)
when "average" then value&.respond_to?(:to_d) ? value.to_d : value
else type.deserialize(value)
end
end
end
end
end
Expand Down
15 changes: 13 additions & 2 deletions lib/active_record/connection_adapters/sqlserver/database_limits.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ module ActiveRecord
module ConnectionAdapters
module SQLServer
module DatabaseLimits

def table_alias_length
128
end
Expand Down Expand Up @@ -32,7 +31,7 @@ def columns_per_multicolumn_index
end

def in_clause_length
65_536
10_000
end

def sql_query_length
Expand All @@ -43,6 +42,18 @@ def joins_per_query
256
end

private

# The max number of binds is 2100, but because sp_executesql takes
# the first 2 params as the query string and the list of types,
# we have only 2098 spaces left
def bind_params_length
2_098
end

def insert_rows_length
1_000
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,29 @@ def case_sensitive_comparison(table, attribute, column, value)
end
end

# We should propose this change to Rails team
def insert_fixtures_set(fixture_set, tables_to_delete = [])
fixture_inserts = []

fixture_set.each do |table_name, fixtures|
fixtures.each_slice(insert_rows_length) do |batch|
fixture_inserts << build_fixture_sql(batch, table_name)
end
end

table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name table}".dup }
total_sql = Array.wrap(combine_multi_statements(table_deletes + fixture_inserts))

disable_referential_integrity do
transaction(requires_new: true) do
total_sql.each do |sql|
execute sql, "Fixtures Load"
yield if block_given?
end
end
end
end

def can_perform_case_insensitive_comparison_for?(column)
column.type == :string && (!column.collation || column.case_sensitive?)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,11 +415,13 @@ def column_definitions(table_name)
ci[:default_function] = begin
default = ci[:default_value]
if default.nil? && view_exists
default = select_value "
default = select_value %{
SELECT c.COLUMN_DEFAULT
FROM #{database}.INFORMATION_SCHEMA.COLUMNS c
WHERE c.TABLE_NAME = '#{view_tblnm}'
AND c.COLUMN_NAME = '#{views_real_column_name(table_name, ci[:name])}'".squish, 'SCHEMA'
WHERE
c.TABLE_NAME = '#{view_tblnm}'
AND c.COLUMN_NAME = '#{views_real_column_name(table_name, ci[:name])}'
}.squish, 'SCHEMA'
end
case default
when nil
Expand All @@ -438,7 +440,7 @@ def column_definitions(table_name)
else ci[:type]
end
value = default.match(/\A\((.*)\)\Z/m)[1]
value = select_value "SELECT CAST(#{value} AS #{type}) AS value", 'SCHEMA'
value = select_value("SELECT CAST(#{value} AS #{type}) AS value", 'SCHEMA')
[value, nil]
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ def current_isolation_level

end

Transaction.send :include, SQLServerTransaction
Transaction.send :prepend, SQLServerTransaction

module SQLServerRealTransaction

attr_reader :starting_isolation_level

def initialize(connection, options, run_commit_callbacks: false)
def initialize(connection, options, *args)
@connection = connection
@starting_isolation_level = current_isolation_level if options[:isolation]
super
Expand All @@ -58,7 +58,6 @@ def reset_starting_isolation_level

end

RealTransaction.send :include, SQLServerRealTransaction

RealTransaction.send :prepend, SQLServerRealTransaction
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,19 @@ module TimeValueFractional
def apply_seconds_precision(value)
return value if !value.respond_to?(fractional_property) || value.send(fractional_property).zero?
value.change fractional_property => seconds_precision(value)

millis = seconds_precision(value).to_i
value = value.change fractional_property => millis % fractional_operator
value + millis / fractional_operator
end

def seconds_precision(value)
return 0 if fractional_scale == 0
seconds = value.send(fractional_property).to_d / fractional_operator.to_d
seconds = ((seconds / fractional_precision).round * fractional_precision).round(fractional_scale)
seconds = value.send(fractional_property).to_f / fractional_operator.to_f
seconds = ((seconds * (1 / fractional_precision)).round / (1 / fractional_precision)).round(fractional_scale)
(seconds * fractional_operator).round(0).to_i
end

def quote_fractional(value)
return 0 if fractional_scale == 0
frac_seconds = seconds_precision(value)
seconds = (frac_seconds.to_d / fractional_operator.to_d).round(fractional_scale)
seconds = (frac_seconds.to_f / fractional_operator.to_f).round(fractional_scale)
seconds.to_d.to_s.split('.').last.to(fractional_scale-1)
end

Expand All @@ -43,7 +39,7 @@ def fractional_operator
end

def fractional_precision
BigDecimal('0.003333')
0.00333
end

def fractional_scale
Expand Down Expand Up @@ -72,7 +68,7 @@ def fractional_digits
end

def fractional_precision
BigDecimal('0.0000001')
0.0000001
end

def fractional_scale
Expand Down
21 changes: 12 additions & 9 deletions lib/active_record/connection_adapters/sqlserver_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ def supports_comments_in_create?
false
end

def supports_savepoints?
true
end

def supports_in_memory_oltp?
@version_year >= 2014
end
Expand Down Expand Up @@ -211,7 +215,7 @@ def sqlserver?
end

def sqlserver_azure?
@sqlserver_azure ||= !!(select_value('SELECT @@version', 'SCHEMA') =~ /Azure/i)
!!(sqlserver_version =~ /Azure/i)
end

def database_prefix_remote_server?
Expand Down Expand Up @@ -434,16 +438,15 @@ def initialize_dateformatter
end

def version_year
return @version_year if defined?(@version_year)
@version_year = begin
vstring = _raw_select('SELECT @@version', fetch: :rows).first.first.to_s
return 2016 if vstring =~ /vNext/
/SQL Server (\d+)/.match(vstring).to_a.last.to_s.to_i
rescue Exception => e
2016
end
return 2016 if sqlserver_version =~ /vNext/
/SQL Server (\d+)/.match(sqlserver_version).to_a.last.to_s.to_i
rescue StandardError => e
2016
end

def sqlserver_version
@sqlserver_version ||= _raw_select('SELECT @@version', fetch: :rows).first.first.to_s
end
end
end
end
98 changes: 97 additions & 1 deletion test/cases/coerced_tests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,25 @@ class BindParameterTest < ActiveRecord::TestCase
end



module ActiveRecord
class InstrumentationTest < ActiveRecord::TestCase
# This fails randomly due to schema cache being lost?
coerce_tests! :test_payload_name_on_load
def test_payload_name_on_load_coerced
Book.create(name: "test book")
Book.first
subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
event = ActiveSupport::Notifications::Event.new(*args)
if event.payload[:sql].match "SELECT"
assert_equal "Book Load", event.payload[:name]
end
end
Book.first
ensure
ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
end
end
end

class CalculationsTest < ActiveRecord::TestCase
# This fails randomly due to schema cache being lost?
Expand Down Expand Up @@ -587,6 +605,7 @@ def test_merge_options_coerced



require 'models/parrot'
require 'models/topic'
class PersistenceTest < ActiveRecord::TestCase
# We can not UPDATE identity columns.
Expand Down Expand Up @@ -742,6 +761,24 @@ def test_reverse_arel_assoc_order_with_function_coerced
end
end

class ActiveRecord::RelationTest < ActiveRecord::TestCase
coerce_tests! :test_relation_merging_with_merged_symbol_joins_is_aliased
def test_relation_merging_with_merged_symbol_joins_is_aliased__coerced
categorizations_with_authors = Categorization.joins(:author)
queries = capture_sql { Post.joins(:author, :categorizations).merge(Author.select(:id)).merge(categorizations_with_authors).to_a }

nb_inner_join = queries.sum { |sql| sql.scan(/INNER\s+JOIN/i).size }
assert_equal 3, nb_inner_join, "Wrong amount of INNER JOIN in query"

# using `\W` as the column separator
query_matches = queries.any? do |sql|
%r[INNER\s+JOIN\s+#{Regexp.escape(Author.quoted_table_name)}\s+\Wauthors_categorizations\W]i.match?(sql)
end

assert query_matches, "Should be aliasing the child INNER JOINs in query"
end
end




Expand Down Expand Up @@ -894,10 +931,53 @@ def test_invalid_datetime_precision_raises_error_coerced
end
end
end

# datetime is rounded to increments of .000, .003, or .007 seconds
coerce_tests! :test_datetime_precision_is_truncated_on_assignment
def test_datetime_precision_is_truncated_on_assignment_coerced
@connection.create_table(:foos, force: true)
@connection.add_column :foos, :created_at, :datetime, precision: 0
@connection.add_column :foos, :updated_at, :datetime, precision: 6

time = ::Time.now.change(nsec: 123456789)
foo = Foo.new(created_at: time, updated_at: time)

assert_equal 0, foo.created_at.nsec
assert_equal 123457000, foo.updated_at.nsec

foo.save!
foo.reload

assert_equal 0, foo.created_at.nsec
assert_equal 123457000, foo.updated_at.nsec
end
end



class TimePrecisionTest < ActiveRecord::TestCase
# datetime is rounded to increments of .000, .003, or .007 seconds
coerce_tests! :test_time_precision_is_truncated_on_assignment
def test_time_precision_is_truncated_on_assignment_coerced
@connection.create_table(:foos, force: true)
@connection.add_column :foos, :start, :time, precision: 0
@connection.add_column :foos, :finish, :time, precision: 6

time = ::Time.now.change(nsec: 123456789)
foo = Foo.new(start: time, finish: time)

assert_equal 0, foo.start.nsec
assert_equal 123457000, foo.finish.nsec

foo.save!
foo.reload

assert_equal 0, foo.start.nsec
assert_equal 123457000, foo.finish.nsec
end
end



class DefaultNumbersTest < ActiveRecord::TestCase
# We do better with native types and do not return strings for everything.
Expand Down Expand Up @@ -1066,3 +1146,19 @@ def test_update_with_dirty_primary_key_coerced
end
end
end



class RelationMergingTest < ActiveRecord::TestCase
coerce_tests! :test_merging_with_order_with_binds
def test_merging_with_order_with_binds_coerced
relation = Post.all.merge(Post.order([Arel.sql("title LIKE ?"), "%suffix"]))
assert_equal ["title LIKE N'%suffix'"], relation.order_values
end
end


class EagerLoadingTooManyIdsTest < ActiveRecord::TestCase
# Temporarily coerce this test due to https://github.com/rails/rails/issues/34945
coerce_tests! :test_eager_loading_too_may_ids
end
Loading