activerecord-sqlserver-adapter 4.2.18 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -223
  3. data/Gemfile +18 -17
  4. data/RAILS5-TODO.md +36 -0
  5. data/README.md +27 -8
  6. data/RUNNING_UNIT_TESTS.md +0 -17
  7. data/Rakefile +2 -7
  8. data/VERSION +1 -1
  9. data/activerecord-sqlserver-adapter.gemspec +1 -1
  10. data/appveyor.yml +0 -2
  11. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +15 -8
  12. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +45 -97
  13. data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +1 -2
  14. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +31 -10
  15. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +0 -18
  16. data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +16 -0
  17. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +101 -58
  18. data/lib/active_record/connection_adapters/sqlserver/showplan.rb +7 -7
  19. data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +20 -0
  20. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +56 -32
  21. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +1 -1
  22. data/lib/active_record/connection_adapters/sqlserver/type.rb +34 -32
  23. data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +4 -0
  24. data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +6 -0
  25. data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +3 -0
  26. data/lib/active_record/connection_adapters/sqlserver/type/char.rb +9 -20
  27. data/lib/active_record/connection_adapters/sqlserver/type/data.rb +30 -0
  28. data/lib/active_record/connection_adapters/sqlserver/type/date.rb +28 -4
  29. data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +28 -14
  30. data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +2 -2
  31. data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +4 -16
  32. data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +9 -0
  33. data/lib/active_record/connection_adapters/sqlserver/type/float.rb +4 -0
  34. data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +3 -0
  35. data/lib/active_record/connection_adapters/sqlserver/type/money.rb +5 -1
  36. data/lib/active_record/connection_adapters/sqlserver/type/real.rb +4 -0
  37. data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +3 -1
  38. data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +5 -1
  39. data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +8 -1
  40. data/lib/active_record/connection_adapters/sqlserver/type/text.rb +4 -0
  41. data/lib/active_record/connection_adapters/sqlserver/type/time.rb +20 -8
  42. data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +25 -10
  43. data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +4 -0
  44. data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +3 -0
  45. data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +6 -0
  46. data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +4 -0
  47. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +7 -1
  48. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +5 -1
  49. data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +15 -2
  50. data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +7 -1
  51. data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +5 -1
  52. data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +7 -1
  53. data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +5 -1
  54. data/lib/active_record/connection_adapters/sqlserver/utils.rb +10 -0
  55. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +71 -57
  56. data/lib/active_record/connection_adapters/sqlserver_column.rb +5 -30
  57. data/lib/active_record/sqlserver_base.rb +1 -5
  58. data/lib/arel/visitors/sqlserver.rb +11 -20
  59. data/test/bin/setup.sh +4 -6
  60. data/test/cases/adapter_test_sqlserver.rb +11 -20
  61. data/test/cases/coerced_tests.rb +233 -138
  62. data/test/cases/column_test_sqlserver.rb +244 -227
  63. data/test/cases/connection_test_sqlserver.rb +5 -76
  64. data/test/cases/fully_qualified_identifier_test_sqlserver.rb +7 -7
  65. data/test/cases/helper_sqlserver.rb +4 -15
  66. data/test/cases/pessimistic_locking_test_sqlserver.rb +1 -1
  67. data/test/cases/rake_test_sqlserver.rb +20 -14
  68. data/test/cases/schema_dumper_test_sqlserver.rb +94 -63
  69. data/test/cases/schema_test_sqlserver.rb +2 -2
  70. data/test/cases/showplan_test_sqlserver.rb +1 -1
  71. data/test/cases/specific_schema_test_sqlserver.rb +7 -14
  72. data/test/cases/transaction_test_sqlserver.rb +1 -1
  73. data/test/cases/uuid_test_sqlserver.rb +0 -1
  74. data/test/config.yml +0 -10
  75. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +1 -1
  76. data/test/schema/sqlserver_specific_schema.rb +0 -16
  77. data/test/support/coerceable_test_sqlserver.rb +6 -2
  78. data/test/support/connection_reflection.rb +0 -4
  79. data/test/support/sql_counter_sqlserver.rb +17 -21
  80. metadata +9 -7
  81. data/lib/active_record/connection_adapters/sqlserver/core_ext/odbc.rb +0 -34
  82. data/lib/active_record/connection_adapters/sqlserver/schema_cache.rb +0 -114
@@ -2,22 +2,9 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  class SQLServerColumn < Column
4
4
 
5
- def initialize(name, default, cast_type, sql_type = nil, null = true, sqlserver_options = {})
6
- super(name, default, cast_type, sql_type, null)
7
- @sqlserver_options = sqlserver_options.symbolize_keys
8
- @default_function = @sqlserver_options[:default_function]
9
- end
10
-
11
- def sql_type_for_statement
12
- if is_integer? || is_real?
13
- sql_type.sub(/\((\d+)?\)/, '')
14
- else
15
- sql_type
16
- end
17
- end
18
-
19
- def table_name
20
- @sqlserver_options[:table_name]
5
+ def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment = nil, sqlserver_options = {})
6
+ @sqlserver_options = sqlserver_options || {}
7
+ super(name, default, sql_type_metadata, null, table_name, default_function, collation, comment: comment)
21
8
  end
22
9
 
23
10
  def is_identity?
@@ -29,23 +16,11 @@ module ActiveRecord
29
16
  end
30
17
 
31
18
  def is_utf8?
32
- @sql_type =~ /nvarchar|ntext|nchar/i
33
- end
34
-
35
- def is_integer?
36
- @sql_type =~ /int/i
37
- end
38
-
39
- def is_real?
40
- @sql_type =~ /real/i
41
- end
42
-
43
- def collation
44
- @sqlserver_options[:collation]
19
+ sql_type =~ /nvarchar|ntext|nchar/i
45
20
  end
46
21
 
47
22
  def case_sensitive?
48
- collation && !collation.match(/_CI/)
23
+ collation && collation.match(/_CS/)
49
24
  end
50
25
 
51
26
  end
@@ -7,14 +7,10 @@ module ActiveRecord
7
7
  case mode
8
8
  when :dblib
9
9
  require 'tiny_tds'
10
- when :odbc
11
- raise ArgumentError, 'Missing :dsn configuration.' unless config.key?(:dsn)
12
- require 'odbc'
13
- require 'active_record/connection_adapters/sqlserver/core_ext/odbc'
14
10
  else
15
11
  raise ArgumentError, "Unknown connection mode in #{config.inspect}."
16
12
  end
17
- ConnectionAdapters::SQLServerAdapter.new(nil, logger, nil, config.merge(mode: mode))
13
+ ConnectionAdapters::SQLServerAdapter.new(nil, nil, config.merge(mode: mode))
18
14
  end
19
15
  end
20
16
  end
@@ -19,11 +19,7 @@ module Arel
19
19
 
20
20
  def visit_Arel_Nodes_Bin o, collector
21
21
  visit o.expr, collector
22
- if o.expr.val.is_a? Numeric
23
- collector
24
- else
25
- collector << " #{ActiveRecord::ConnectionAdapters::SQLServerAdapter.cs_equality_operator} "
26
- end
22
+ collector << " #{ActiveRecord::ConnectionAdapters::SQLServerAdapter.cs_equality_operator} "
27
23
  end
28
24
 
29
25
  def visit_Arel_Nodes_UpdateStatement(o, a)
@@ -77,9 +73,13 @@ module Arel
77
73
  # Apparently, o.engine.connection can actually be a different adapter
78
74
  # than sqlserver. Can be removed if fixed in ActiveRecord. See:
79
75
  # github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/450
80
- table_name = if o.engine.connection.respond_to?(:sqlserver?) && o.engine.connection.database_prefix_remote_server?
81
- remote_server_table_name(o)
82
- else
76
+ table_name = begin
77
+ if o.class.engine.connection.respond_to?(:sqlserver?) && o.class.engine.connection.database_prefix_remote_server?
78
+ remote_server_table_name(o)
79
+ else
80
+ quote_table_name(o.name)
81
+ end
82
+ rescue Exception => e
83
83
  quote_table_name(o.name)
84
84
  end
85
85
  if o.table_alias
@@ -170,7 +170,7 @@ module Arel
170
170
  core = o.cores.first
171
171
  distinct = Nodes::Distinct === core.set_quantifier
172
172
  oneasone = core.projections.all? { |x| x == ActiveRecord::FinderMethods::ONE_AS_ONE }
173
- limitone = node_value(o.limit) == 1
173
+ limitone = [nil, 0, 1].include? node_value(o.limit)
174
174
  if distinct && oneasone && limitone && !o.offset
175
175
  core.projections = [Arel.sql("TOP(1) 1 AS [one]")]
176
176
  o.limit = nil
@@ -190,25 +190,16 @@ module Arel
190
190
 
191
191
  def primary_Key_From_Table t
192
192
  return unless t
193
- return t.primary_key if t.primary_key
194
- if engine_pk = t.engine.primary_key
195
- pk = t.engine.arel_table[engine_pk]
196
- return pk if pk
197
- end
198
- pk = t.engine.connection.schema_cache.primary_keys(t.engine.table_name)
199
- return pk if pk
200
- column_name = t.engine.columns.first.try(:name)
193
+ column_name = schema_cache.primary_keys(t.name) || column_cache(t.name).first.try(:second).try(:name)
201
194
  column_name ? t[column_name] : nil
202
195
  end
203
196
 
204
197
  def remote_server_table_name o
205
198
  ActiveRecord::ConnectionAdapters::SQLServer::Utils.extract_identifiers(
206
- "#{o.engine.connection.database_prefix}#{o.name}"
199
+ "#{o.class.engine.connection.database_prefix}#{o.name}"
207
200
  ).quoted
208
201
  end
209
202
 
210
203
  end
211
204
  end
212
205
  end
213
-
214
- Arel::Visitors::VISITORS['sqlserver'] = Arel::Visitors::SQLServer
data/test/bin/setup.sh CHANGED
@@ -3,17 +3,15 @@
3
3
  set -x
4
4
  set -e
5
5
 
6
- tag=1.2
6
+ docker pull metaskills/mssql-server-linux-rails
7
7
 
8
- docker pull metaskills/mssql-server-linux-rails:$tag
9
-
10
- container=$(docker ps -a -q --filter ancestor=metaskills/mssql-server-linux-rails:$tag)
8
+ container=$(docker ps -a -q --filter ancestor=metaskills/mssql-server-linux-rails)
11
9
  if [[ -z $container ]]; then
12
- docker run -p 1433:1433 -d metaskills/mssql-server-linux-rails:$tag && sleep 10
10
+ docker run -p 1433:1433 -d metaskills/mssql-server-linux-rails && sleep 10
13
11
  exit
14
12
  fi
15
13
 
16
- container=$(docker ps -q --filter ancestor=metaskills/mssql-server-linux-rails:$tag)
14
+ container=$(docker ps -q --filter ancestor=metaskills/mssql-server-linux-rails)
17
15
  if [[ -z $container ]]; then
18
16
  docker start $container && sleep 10
19
17
  fi
@@ -17,7 +17,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
17
17
  string = connection.inspect
18
18
  string.must_match %r{ActiveRecord::ConnectionAdapters::SQLServerAdapter}
19
19
  string.must_match %r{version\: \d.\d}
20
- string.must_match %r{mode: (dblib|odbc)}
20
+ string.must_match %r{mode: dblib}
21
21
  string.must_match %r{azure: (true|false)}
22
22
  string.wont_match %r{host}
23
23
  string.wont_match %r{password}
@@ -96,7 +96,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
96
96
  connection.send :initialize_dateformatter
97
97
  assert_nothing_raised do
98
98
  starting = Time.utc(2000, 1, 31, 5, 42, 0)
99
- ending = Date.new(2006, 12, 31)
99
+ ending = Time.new(2006, 12, 31)
100
100
  Task.create! starting: starting, ending: ending
101
101
  end
102
102
  end
@@ -158,14 +158,14 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
158
158
  end
159
159
  end
160
160
 
161
- it 'find identity column using #identity_column' do
161
+ it 'find identity column using #identity_columns' do
162
162
  task_id_column = Task.columns_hash['id']
163
- assert_equal task_id_column.name, connection.send(:identity_column, Task.table_name).name
164
- assert_equal task_id_column.sql_type, connection.send(:identity_column, Task.table_name).sql_type
163
+ assert_equal task_id_column.name, connection.send(:identity_columns, Task.table_name).first.name
164
+ assert_equal task_id_column.sql_type, connection.send(:identity_columns, Task.table_name).first.sql_type
165
165
  end
166
166
 
167
- it 'return nil when calling #identity_column for a table_name with no identity' do
168
- assert_nil connection.send(:identity_column, Subscriber.table_name)
167
+ it 'return an empty array when calling #identity_columns for a table_name with no identity' do
168
+ connection.send(:identity_columns, Subscriber.table_name).must_equal []
169
169
  end
170
170
 
171
171
  end
@@ -364,8 +364,8 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
364
364
  assert_equal 0, SSTestCustomersView.new.balance
365
365
  end
366
366
 
367
- it 'respond true to table_exists?' do
368
- assert SSTestCustomersView.table_exists?
367
+ it 'respond true to data_source_exists?' do
368
+ assert SSTestCustomersView.connection.data_source_exists?(SSTestCustomersView.table_name)
369
369
  end
370
370
 
371
371
  # With aliased column names
@@ -392,17 +392,8 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
392
392
  SSTestStringDefaultsView.columns_hash['pretend_null'].inspect
393
393
  end
394
394
 
395
- it 'respond true to table_exists?' do
396
- assert SSTestStringDefaultsView.table_exists?
397
- end
398
-
399
- # Doing identity inserts
400
-
401
- it 'be able to do an identity insert' do
402
- customer = SSTestCustomersView.new
403
- customer.id = 420
404
- customer.save!
405
- assert SSTestCustomersView.find(420)
395
+ it 'respond true to data_source_exists?' do
396
+ assert SSTestStringDefaultsView.connection.data_source_exists?(SSTestStringDefaultsView.table_name)
406
397
  end
407
398
 
408
399
  # That have more than 4000 chars for their defintion
@@ -1,30 +1,49 @@
1
1
  require 'cases/helper_sqlserver'
2
2
 
3
3
 
4
- # Windows/Appveyor
5
- if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
6
- # All of these are due to Time.local(2000).zone. See http://git.io/v3t0o
7
- class BelongsToAssociationsTest < ActiveRecord::TestCase
8
- coerce_tests! :test_belongs_to_with_touch_option_on_touch_without_updated_at_attributes
9
- end
10
- class BasicsTest < ActiveRecord::TestCase
11
- coerce_tests! :test_preserving_time_objects_with_local_time_conversion_to_default_timezone_utc
12
- coerce_tests! :test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_local
13
- coerce_tests! :test_preserving_time_objects_with_utc_time_conversion_to_default_timezone_local
4
+
5
+ require 'models/event'
6
+ class UniquenessValidationTest < ActiveRecord::TestCase
7
+ # So sp_executesql swallows this exception. Run without prpared to see it.
8
+ coerce_tests! :test_validate_uniqueness_with_limit
9
+ def test_validate_uniqueness_with_limit_coerced
10
+ connection.unprepared_statement do
11
+ assert_raise(ActiveRecord::ValueTooLong) do
12
+ Event.create(title: "abcdefgh")
13
+ end
14
+ end
14
15
  end
15
- class DirtyTest < ActiveRecord::TestCase
16
- coerce_tests! :test_save_always_should_update_timestamps_when_serialized_attributes_are_present
17
- coerce_tests! :test_previous_changes # Coupled to above test.
16
+
17
+ # So sp_executesql swallows this exception. Run without prpared to see it.
18
+ coerce_tests! :test_validate_uniqueness_with_limit_and_utf8
19
+ def test_validate_uniqueness_with_limit_and_utf8_coerced
20
+ connection.unprepared_statement do
21
+ assert_raise(ActiveRecord::ValueTooLong) do
22
+ Event.create(title: "一二三四五六七八")
23
+ end
24
+ end
18
25
  end
19
26
  end
20
27
 
21
28
 
29
+
30
+
31
+ require 'models/event'
22
32
  module ActiveRecord
23
33
  class AdapterTest < ActiveRecord::TestCase
24
-
25
34
  # As far as I can tell, SQL Server does not support null bytes in strings.
26
35
  coerce_tests! :test_update_prepared_statement
27
36
 
37
+ # So sp_executesql swallows this exception. Run without prpared to see it.
38
+ coerce_tests! :test_value_limit_violations_are_translated_to_specific_exception
39
+ def test_value_limit_violations_are_translated_to_specific_exception_coerced
40
+ connection.unprepared_statement do
41
+ error = assert_raises(ActiveRecord::ValueTooLong) do
42
+ Event.create(title: 'abcdefgh')
43
+ end
44
+ assert_not_nil error.cause
45
+ end
46
+ end
28
47
  end
29
48
  end
30
49
 
@@ -33,7 +52,6 @@ end
33
52
 
34
53
  require 'models/topic'
35
54
  class AttributeMethodsTest < ActiveRecord::TestCase
36
-
37
55
  coerce_tests! :test_typecast_attribute_from_select_to_false
38
56
  def test_typecast_attribute_from_select_to_false_coerced
39
57
  Topic.create(:title => 'Budget')
@@ -47,26 +65,19 @@ class AttributeMethodsTest < ActiveRecord::TestCase
47
65
  topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 1, 1, 0) as is_test").first
48
66
  assert topic.is_test?
49
67
  end
50
-
51
68
  end
52
69
 
53
70
 
54
71
 
55
72
 
56
73
  class BasicsTest < ActiveRecord::TestCase
57
-
58
74
  coerce_tests! :test_column_names_are_escaped
59
75
  def test_column_names_are_escaped_coerced
60
- conn = ActiveRecord::Base.connection
61
- classname = conn.class.name[/[^:]*$/]
62
- badchar = "'"
63
- quoted = conn.quote_column_name "foo#{badchar}bar"
64
- assert_equal "[foo'bar]", quoted
76
+ conn = ActiveRecord::Base.connection
77
+ assert_equal '[t]]]', conn.quote_column_name('t]')
65
78
  end
66
79
 
67
- # PENDING: [Rails5.x] Remove coerced tests and use simple symbol types..
68
- # This test has a few problems. First, it would require that we use the
69
- # `Type::SQLServer::BigInteger.new(limit: 8)` for the `world_population` attribute.
80
+ # We do not have do the DecimalWithoutScale type.
70
81
  coerce_tests! :test_numeric_fields
71
82
  coerce_tests! :test_numeric_fields_with_scale
72
83
 
@@ -76,14 +87,12 @@ class BasicsTest < ActiveRecord::TestCase
76
87
  # Caused in Rails v4.2.5 by adding `firm_id` column in this http://git.io/vBfMs
77
88
  # commit. Trust Rails has this covered.
78
89
  coerce_tests! :test_find_keeps_multiple_group_values
79
-
80
90
  end
81
91
 
82
92
 
83
93
 
84
94
 
85
95
  class BelongsToAssociationsTest < ActiveRecord::TestCase
86
-
87
96
  # Since @client.firm is a single first/top, and we use FETCH the order clause is used.
88
97
  coerce_tests! :test_belongs_to_does_not_use_order_by
89
98
 
@@ -93,7 +102,6 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
93
102
  assert_no_match(/\[firm_with_primary_keys_companies\]\.\[id\]/, sql)
94
103
  assert_match(/\[firm_with_primary_keys_companies\]\.\[name\]/, sql)
95
104
  end
96
-
97
105
  end
98
106
 
99
107
 
@@ -101,11 +109,8 @@ end
101
109
 
102
110
  module ActiveRecord
103
111
  class BindParameterTest < ActiveRecord::TestCase
104
-
105
112
  # Never finds `sql` since we use `EXEC sp_executesql` wrappers.
106
- coerce_tests! :test_binds_are_logged,
107
- :test_binds_are_logged_after_type_cast
108
-
113
+ coerce_tests! :test_binds_are_logged
109
114
  end
110
115
  end
111
116
 
@@ -113,7 +118,6 @@ end
113
118
 
114
119
 
115
120
  class CalculationsTest < ActiveRecord::TestCase
116
-
117
121
  # Are decimal, not integer.
118
122
  coerce_tests! :test_should_return_decimal_average_of_integer_field
119
123
  def test_should_return_decimal_average_of_integer_field_coerced
@@ -123,38 +127,34 @@ class CalculationsTest < ActiveRecord::TestCase
123
127
 
124
128
  coerce_tests! :test_limit_is_kept
125
129
  def test_limit_is_kept_coerced
126
- queries = assert_sql { Account.limit(1).count }
130
+ queries = capture_sql_ss { Account.limit(1).count }
127
131
  assert_equal 1, queries.length
128
- queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY}
132
+ queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1}
129
133
  end
130
134
 
131
135
  coerce_tests! :test_limit_with_offset_is_kept
132
136
  def test_limit_with_offset_is_kept_coerced
133
- queries = assert_sql { Account.limit(1).offset(1).count }
137
+ queries = capture_sql_ss { Account.limit(1).offset(1).count }
134
138
  assert_equal 1, queries.length
135
- queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY}
139
+ queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY.*@0 = 1, @1 = 1}
136
140
  end
137
141
 
142
+ # Leave it up to users to format selects/functions so HAVING works correctly.
143
+ coerce_tests! :test_having_with_strong_parameters
138
144
  end
139
145
 
140
146
 
141
147
 
142
-
143
148
  module ActiveRecord
144
149
  class Migration
145
150
  class ChangeSchemaTest < ActiveRecord::TestCase
146
-
147
151
  # We test these.
148
152
  coerce_tests! :test_create_table_with_bigint,
149
153
  :test_create_table_with_defaults
150
-
151
-
152
154
  end
153
155
  class ChangeSchemaWithDependentObjectsTest < ActiveRecord::TestCase
154
-
155
156
  # In SQL Server you have to delete the tables yourself in the right order.
156
157
  coerce_tests! :test_create_table_with_force_cascade_drops_dependent_objects
157
-
158
158
  end
159
159
  end
160
160
  end
@@ -165,7 +165,6 @@ end
165
165
  module ActiveRecord
166
166
  class Migration
167
167
  class ColumnAttributesTest < ActiveRecord::TestCase
168
-
169
168
  # We have a default 4000 varying character limit.
170
169
  coerce_tests! :test_add_column_without_limit
171
170
  def test_add_column_without_limit_coerced
@@ -173,7 +172,6 @@ module ActiveRecord
173
172
  TestModel.reset_column_information
174
173
  TestModel.columns_hash["description"].limit.must_equal 4000
175
174
  end
176
-
177
175
  end
178
176
  end
179
177
  end
@@ -184,14 +182,14 @@ end
184
182
  module ActiveRecord
185
183
  class Migration
186
184
  class ColumnsTest
187
-
188
- # Our defaults are reall 70000 integers vs '70000' strings.
185
+ # Our defaults are real 70000 integers vs '70000' strings.
189
186
  coerce_tests! :test_rename_column_preserves_default_value_not_null
190
187
  def test_rename_column_preserves_default_value_not_null_coerced
191
188
  add_column 'test_models', 'salary', :integer, :default => 70000
192
189
  default_before = connection.columns("test_models").find { |c| c.name == "salary" }.default
193
190
  assert_equal 70000, default_before
194
191
  rename_column "test_models", "salary", "annual_salary"
192
+ TestModel.reset_column_information
195
193
  assert TestModel.column_names.include?("annual_salary")
196
194
  default_after = connection.columns("test_models").find { |c| c.name == "annual_salary" }.default
197
195
  assert_equal 70000, default_after
@@ -208,6 +206,14 @@ module ActiveRecord
208
206
  assert_equal [], connection.indexes('test_models').map(&:name)
209
207
  end
210
208
 
209
+ # Choose `StatementInvalid` vs `ActiveRecordError`.
210
+ coerce_tests! :test_rename_nonexistent_column
211
+ def test_rename_nonexistent_column_coerced
212
+ exception = ActiveRecord::StatementInvalid
213
+ assert_raise(exception) do
214
+ rename_column "test_models", "nonexistent", "should_fail"
215
+ end
216
+ end
211
217
  end
212
218
  end
213
219
  end
@@ -215,13 +221,53 @@ end
215
221
 
216
222
 
217
223
 
218
- class CoreTest < ActiveRecord::TestCase
224
+ class MigrationTest < ActiveRecord::TestCase
225
+ # We do not have do the DecimalWithoutScale type.
226
+ coerce_tests! :test_add_table_with_decimals
227
+ def test_add_table_with_decimals_coerced
228
+ Person.connection.drop_table :big_numbers rescue nil
229
+ assert !BigNumber.table_exists?
230
+ GiveMeBigNumbers.up
231
+ BigNumber.reset_column_information
232
+ assert BigNumber.create(
233
+ :bank_balance => 1586.43,
234
+ :big_bank_balance => BigDecimal("1000234000567.95"),
235
+ :world_population => 6000000000,
236
+ :my_house_population => 3,
237
+ :value_of_e => BigDecimal("2.7182818284590452353602875")
238
+ )
239
+ b = BigNumber.first
240
+ assert_not_nil b
241
+ assert_not_nil b.bank_balance
242
+ assert_not_nil b.big_bank_balance
243
+ assert_not_nil b.world_population
244
+ assert_not_nil b.my_house_population
245
+ assert_not_nil b.value_of_e
246
+ assert_kind_of BigDecimal, b.world_population
247
+ assert_equal '6000000000.0', b.world_population.to_s
248
+ assert_kind_of Integer, b.my_house_population
249
+ assert_equal 3, b.my_house_population
250
+ assert_kind_of BigDecimal, b.bank_balance
251
+ assert_equal BigDecimal("1586.43"), b.bank_balance
252
+ assert_kind_of BigDecimal, b.big_bank_balance
253
+ assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
254
+ GiveMeBigNumbers.down
255
+ assert_raise(ActiveRecord::StatementInvalid) { BigNumber.first }
256
+ end
257
+
258
+ # For some reason our tests set Rails.@_env which breaks test env switching.
259
+ coerce_tests! :test_migration_sets_internal_metadata_even_when_fully_migrated
260
+ coerce_tests! :test_internal_metadata_stores_environment
261
+ end
262
+
263
+
219
264
 
265
+
266
+ class CoreTest < ActiveRecord::TestCase
220
267
  # I think fixtures are useing the wrong time zone and the `:first`
221
268
  # `topics`.`bonus_time` attribute of 2005-01-30t15:28:00.00+01:00 is
222
269
  # getting local EST time for me and set to "09:28:00.0000000".
223
270
  coerce_tests! :test_pretty_print_persisted
224
-
225
271
  end
226
272
 
227
273
 
@@ -229,7 +275,6 @@ end
229
275
 
230
276
  module ActiveRecord
231
277
  module ConnectionAdapters
232
-
233
278
  # Just like PostgreSQLAdapter does.
234
279
  TypeLookupTest.coerce_all_tests! if defined?(TypeLookupTest)
235
280
 
@@ -237,7 +282,6 @@ module ActiveRecord
237
282
  # a value of 'default_env' will still show tests failing. Just ignoring all
238
283
  # of them since we have no monkey in this circus.
239
284
  MergeAndResolveDefaultUrlConfigTest.coerce_all_tests! if defined?(MergeAndResolveDefaultUrlConfigTest)
240
-
241
285
  end
242
286
  end
243
287
 
@@ -259,10 +303,16 @@ end
259
303
 
260
304
 
261
305
  class DefaultScopingTest < ActiveRecord::TestCase
262
-
263
306
  # We are not doing order duplicate removal anymore.
264
307
  coerce_tests! :test_order_in_default_scope_should_not_prevail
265
308
 
309
+ # Use our escaped format in assertion.
310
+ coerce_tests! :test_with_abstract_class_scope_should_be_executed_in_correct_context
311
+ def test_with_abstract_class_scope_should_be_executed_in_correct_context_coerced
312
+ vegetarian_pattern, gender_pattern = [/[lions].[is_vegetarian]/, /[lions].[gender]/]
313
+ assert_match vegetarian_pattern, Lion.all.to_sql
314
+ assert_match gender_pattern, Lion.female.to_sql
315
+ end
266
316
  end
267
317
 
268
318
 
@@ -271,7 +321,7 @@ end
271
321
  require 'models/post'
272
322
  require 'models/subscriber'
273
323
  class EachTest < ActiveRecord::TestCase
274
-
324
+ # Quoting in tests does not cope with bracket quoting.
275
325
  coerce_tests! :test_find_in_batches_should_quote_batch_order
276
326
  def test_find_in_batches_should_quote_batch_order_coerced
277
327
  c = Post.connection
@@ -283,20 +333,23 @@ class EachTest < ActiveRecord::TestCase
283
333
  end
284
334
  end
285
335
 
336
+ # Quoting in tests does not cope with bracket quoting.
337
+ coerce_tests! :test_in_batches_should_quote_batch_order
338
+ def test_in_batches_should_quote_batch_order_coerced
339
+ c = Post.connection
340
+ assert_sql(/ORDER BY \[posts\]\.\[id\]/) do
341
+ Post.in_batches(of: 1) do |relation|
342
+ assert_kind_of ActiveRecord::Relation, relation
343
+ assert_kind_of Post, relation.first
344
+ end
345
+ end
346
+ end
286
347
  end
287
348
 
288
349
 
289
350
 
290
351
 
291
- require 'models/owner'
292
- class Owner < ActiveRecord::Base
293
- scope :including_last_pet, -> {
294
- select('owners.*, (select TOP (1) p.pet_id from pets p where p.owner_id = owners.owner_id order by p.name desc ) as last_pet_id').
295
- includes(:last_pet)
296
- }
297
- end
298
352
  class EagerAssociationTest < ActiveRecord::TestCase
299
-
300
353
  # Use LEN() vs length() function.
301
354
  coerce_tests! :test_count_with_include
302
355
  def test_count_with_include_coerced
@@ -305,10 +358,6 @@ class EagerAssociationTest < ActiveRecord::TestCase
305
358
 
306
359
  # Use TOP (1) in scope vs limit 1.
307
360
  coerce_tests! %r{including association based on sql condition and no database column}
308
- it "including association based on sql condition and no database column coerced" do
309
- assert_equal pets(:parrot), Owner.including_last_pet.first.last_pet
310
- end
311
-
312
361
  end
313
362
 
314
363
 
@@ -316,13 +365,12 @@ end
316
365
 
317
366
  require 'models/topic'
318
367
  class FinderTest < ActiveRecord::TestCase
319
-
320
368
  coerce_tests! %r{doesn't have implicit ordering},
321
369
  :test_find_doesnt_have_implicit_ordering # We have implicit ordering, via FETCH.
322
370
 
323
371
  coerce_tests! :test_exists_does_not_select_columns_without_alias
324
372
  def test_exists_does_not_select_columns_without_alias_coerced
325
- assert_sql(/SELECT\s+1 AS one FROM \[topics\].*OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY/i) do
373
+ assert_sql(/SELECT\s+1 AS one FROM \[topics\].*OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) do
326
374
  Topic.exists?
327
375
  end
328
376
  end
@@ -335,14 +383,35 @@ class FinderTest < ActiveRecord::TestCase
335
383
 
336
384
  coerce_tests! :test_take_and_first_and_last_with_integer_should_use_sql_limit
337
385
  def test_take_and_first_and_last_with_integer_should_use_sql_limit_coerced
338
- assert_sql(/OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY/) { Topic.take(3).entries }
339
- assert_sql(/OFFSET 0 ROWS FETCH NEXT 2 ROWS ONLY/) { Topic.first(2).entries }
340
- assert_sql(/OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY/) { Topic.last(5).entries }
386
+ assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 3/) { Topic.take(3).entries }
387
+ assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 2/) { Topic.first(2).entries }
388
+ assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 5/) { Topic.last(5).entries }
341
389
  end
342
390
 
343
391
  # This fails only when run in the full test suite task. Just taking it out of the mix.
344
392
  coerce_tests! :test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct
345
393
 
394
+ # Can not use array condition due to not finding right type and hence fractional second quoting.
395
+ coerce_tests! :test_condition_utc_time_interpolation_with_default_timezone_local
396
+ def test_condition_utc_time_interpolation_with_default_timezone_local_coerced
397
+ with_env_tz 'America/New_York' do
398
+ with_timezone_config default: :local do
399
+ topic = Topic.first
400
+ assert_equal topic, Topic.where(written_on: topic.written_on.getutc).first
401
+ end
402
+ end
403
+ end
404
+
405
+ # Can not use array condition due to not finding right type and hence fractional second quoting.
406
+ coerce_tests! :test_condition_local_time_interpolation_with_default_timezone_utc
407
+ def test_condition_local_time_interpolation_with_default_timezone_utc_coerced
408
+ with_env_tz 'America/New_York' do
409
+ with_timezone_config default: :utc do
410
+ topic = Topic.first
411
+ assert_equal topic, Topic.where(written_on: topic.written_on.getlocal).first
412
+ end
413
+ end
414
+ end
346
415
  end
347
416
 
348
417
 
@@ -351,7 +420,6 @@ end
351
420
  module ActiveRecord
352
421
  class Migration
353
422
  class ForeignKeyTest < ActiveRecord::TestCase
354
-
355
423
  # We do not support :restrict.
356
424
  coerce_tests! :test_add_on_delete_restrict_foreign_key
357
425
  def test_add_on_delete_restrict_foreign_key_coerced
@@ -362,7 +430,6 @@ module ActiveRecord
362
430
  @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_update: :restrict
363
431
  end
364
432
  end
365
-
366
433
  end
367
434
  end
368
435
  end
@@ -371,10 +438,8 @@ end
371
438
 
372
439
 
373
440
  class HasOneAssociationsTest < ActiveRecord::TestCase
374
-
375
441
  # We use OFFSET/FETCH vs TOP. So we always have an order.
376
442
  coerce_tests! :test_has_one_does_not_use_order_by
377
-
378
443
  end
379
444
 
380
445
 
@@ -382,7 +447,6 @@ end
382
447
 
383
448
  require 'models/company'
384
449
  class InheritanceTest < ActiveRecord::TestCase
385
-
386
450
  coerce_tests! :test_a_bad_type_column
387
451
  def test_a_bad_type_column_coerced
388
452
  Company.connection.with_identity_insert_enabled('companies') do
@@ -394,32 +458,24 @@ class InheritanceTest < ActiveRecord::TestCase
394
458
  coerce_tests! :test_eager_load_belongs_to_primary_key_quoting
395
459
  def test_eager_load_belongs_to_primary_key_quoting_coerced
396
460
  con = Account.connection
397
- assert_sql(/\[companies\]\.\[id\] IN \(1\)/) do
461
+ assert_sql(/\[companies\]\.\[id\] = 1/) do
398
462
  Account.all.merge!(:includes => :firm).find(1)
399
463
  end
400
464
  end
401
-
402
465
  end
403
466
 
404
467
 
405
468
 
406
469
 
407
- class BigNumber < ActiveRecord::Base
408
- attribute :value_of_e, Type::SQLServer::Integer.new
409
- attribute :my_house_population, Type::SQLServer::Integer.new
410
- end
411
- class MigrationTest < ActiveRecord::TestCase
412
-
413
- # PENDING: [Rails5.x] Remove coerced tests and use simple symbol types.
414
- coerce_tests! :test_add_table_with_decimals
415
-
470
+ class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
471
+ # Uses || operator in SQL. Just trust core gets value out of this test.
472
+ coerce_tests! :test_does_not_override_select
416
473
  end
417
474
 
418
475
 
419
476
 
420
477
 
421
478
  class NamedScopingTest < ActiveRecord::TestCase
422
-
423
479
  # This works now because we add an `order(:id)` sort to break the order tie for deterministic results.
424
480
  coerce_tests! :test_scopes_honor_current_scopes_from_when_defined
425
481
  def test_scopes_honor_current_scopes_from_when_defined_coerced
@@ -431,7 +487,6 @@ class NamedScopingTest < ActiveRecord::TestCase
431
487
  assert_equal authors(:david).posts.ranked_by_comments.limit_by(5).to_a.sort_by(&:id), authors(:david).posts.top(5).to_a.sort_by(&:id)
432
488
  assert_equal Post.ranked_by_comments.limit_by(5), Post.top(5)
433
489
  end
434
-
435
490
  end
436
491
 
437
492
 
@@ -440,7 +495,6 @@ end
440
495
  require 'models/developer'
441
496
  require 'models/computer'
442
497
  class NestedRelationScopingTest < ActiveRecord::TestCase
443
-
444
498
  coerce_tests! :test_merge_options
445
499
  def test_merge_options_coerced
446
500
  Developer.where('salary = 80000').scoping do
@@ -452,7 +506,6 @@ class NestedRelationScopingTest < ActiveRecord::TestCase
452
506
  end
453
507
  end
454
508
  end
455
-
456
509
  end
457
510
 
458
511
 
@@ -460,7 +513,6 @@ end
460
513
 
461
514
  require 'models/topic'
462
515
  class PersistenceTest < ActiveRecord::TestCase
463
-
464
516
  # We can not UPDATE identity columns.
465
517
  coerce_tests! :test_update_columns_changing_id
466
518
 
@@ -501,7 +553,6 @@ class PersistenceTest < ActiveRecord::TestCase
501
553
  # assert_nothing_raised { topic.reload }
502
554
  # assert_equal topic.title, Topic.find(1234).title
503
555
  end
504
-
505
556
  end
506
557
 
507
558
 
@@ -510,15 +561,15 @@ end
510
561
  require 'models/topic'
511
562
  module ActiveRecord
512
563
  class PredicateBuilderTest < ActiveRecord::TestCase
513
-
514
564
  coerce_tests! :test_registering_new_handlers
515
565
  def test_registering_new_handlers_coerced
516
- PredicateBuilder.register_handler(Regexp, proc do |column, value|
566
+ Topic.predicate_builder.register_handler(Regexp, proc do |column, value|
517
567
  Arel::Nodes::InfixOperation.new('~', column, Arel.sql(value.source))
518
568
  end)
519
- assert_match %r{\[topics\]\.\[title\] ~ rails}i, Topic.where(title: /rails/).to_sql
569
+ assert_match %r{\[topics\].\[title\] ~ rails}i, Topic.where(title: /rails/).to_sql
570
+ ensure
571
+ Topic.reset_column_information
520
572
  end
521
-
522
573
  end
523
574
  end
524
575
 
@@ -527,14 +578,12 @@ end
527
578
 
528
579
  require 'models/task'
529
580
  class QueryCacheTest < ActiveRecord::TestCase
530
-
531
581
  coerce_tests! :test_cache_does_not_wrap_string_results_in_arrays
532
582
  def test_cache_does_not_wrap_string_results_in_arrays_coerced
533
583
  Task.cache do
534
584
  assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
535
585
  end
536
586
  end
537
-
538
587
  end
539
588
 
540
589
 
@@ -542,6 +591,21 @@ end
542
591
 
543
592
  require 'models/post'
544
593
  class RelationTest < ActiveRecord::TestCase
594
+ # Use LEN vs LENGTH function.
595
+ coerce_tests! :test_reverse_order_with_function
596
+ def test_reverse_order_with_function_coerced
597
+ topics = Topic.order("LEN(title)").reverse_order
598
+ assert_equal topics(:second).title, topics.first.title
599
+ end
600
+
601
+ # Use LEN vs LENGTH function.
602
+ coerce_tests! :test_reverse_order_with_function_other_predicates
603
+ def test_reverse_order_with_function_other_predicates_coerced
604
+ topics = Topic.order("author_name, LEN(title), id").reverse_order
605
+ assert_equal topics(:second).title, topics.first.title
606
+ topics = Topic.order("LEN(author_name), id, LEN(title)").reverse_order
607
+ assert_equal topics(:fifth).title, topics.first.title
608
+ end
545
609
 
546
610
  # We have implicit ordering, via FETCH.
547
611
  coerce_tests! %r{doesn't have implicit ordering}
@@ -549,18 +613,12 @@ class RelationTest < ActiveRecord::TestCase
549
613
  # We are not doing order duplicate removal anymore.
550
614
  coerce_tests! :test_order_using_scoping
551
615
 
552
- # Account for our `EXEC sp_executesql...` statements.
553
- coerce_tests! :test_to_sql_on_eager_join
554
- def test_to_sql_on_eager_join_coerced
555
- expected = assert_sql { Post.eager_load(:last_comment).order('comments.id DESC').to_a }.first
556
- actual = Post.eager_load(:last_comment).order('comments.id DESC').to_sql
557
- actual = "EXEC sp_executesql N'#{ActiveRecord::ConnectionAdapters::SQLServer::Utils.quote_string(actual)}'"
558
- assert_equal expected, actual
559
- end
560
-
561
616
  # We are not doing order duplicate removal anymore.
562
617
  coerce_tests! :test_default_scope_order_with_scope_order
563
618
 
619
+ # Leave it up to users to format selects/functions so HAVING works correctly.
620
+ coerce_tests! :test_multiple_where_and_having_clauses
621
+ coerce_tests! :test_having_with_binds_for_both_where_and_having
564
622
  end
565
623
 
566
624
 
@@ -568,7 +626,6 @@ end
568
626
 
569
627
  require 'models/post'
570
628
  class SanitizeTest < ActiveRecord::TestCase
571
-
572
629
  coerce_tests! :test_sanitize_sql_like_example_use_case
573
630
  def test_sanitize_sql_like_example_use_case_coerced
574
631
  searchable_post = Class.new(Post) do
@@ -576,18 +633,16 @@ class SanitizeTest < ActiveRecord::TestCase
576
633
  where("title LIKE ?", sanitize_sql_like(term, '!'))
577
634
  end
578
635
  end
579
- assert_sql(/\(title LIKE N''20!% !_reduction!_!!''\)/) do
636
+ assert_sql(/\(title LIKE N'20!% !_reduction!_!!'\)/) do
580
637
  searchable_post.search("20% _reduction_!").to_a
581
638
  end
582
639
  end
583
-
584
640
  end
585
641
 
586
642
 
587
643
 
588
644
 
589
645
  class SchemaDumperTest < ActiveRecord::TestCase
590
-
591
646
  # We have precision to 38.
592
647
  coerce_tests! :test_schema_dump_keeps_large_precision_integer_columns_as_decimal
593
648
  def test_schema_dump_keeps_large_precision_integer_columns_as_decimal_coerced
@@ -604,27 +659,29 @@ class SchemaDumperTest < ActiveRecord::TestCase
604
659
  # Fall through false positive with no filter.
605
660
  coerce_tests! :test_schema_dumps_partial_indices
606
661
  def test_schema_dumps_partial_indices_coerced
607
- index_definition = standard_dump.split(/\n/).grep(/add_index.*company_partial_index/).first.strip
608
- assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "([rating]>(10))"', index_definition
662
+ index_definition = standard_dump.split(/\n/).grep(/t.index.*company_partial_index/).first.strip
663
+ assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", where: "([rating]>(10))"', index_definition
609
664
  end
610
665
 
666
+ # We do not quote the 2.78 string default.
667
+ coerce_tests! :test_schema_dump_includes_decimal_options
668
+ def test_schema_dump_includes_decimal_options_coerced
669
+ output = dump_all_table_schema([/^[^n]/])
670
+ assert_match %r{precision: 3,[[:space:]]+scale: 2,[[:space:]]+default: 2\.78}, output
671
+ end
611
672
  end
612
673
 
613
674
  class SchemaDumperDefaultsTest < ActiveRecord::TestCase
614
-
615
675
  # These date formats do not match ours. We got these covered in our dumper tests.
616
676
  coerce_tests! :test_schema_dump_defaults_with_universally_supported_types
617
-
618
677
  end
619
678
 
620
679
 
621
680
 
622
681
 
623
682
  class TestAdapterWithInvalidConnection < ActiveRecord::TestCase
624
-
625
683
  # We trust Rails on this since we do not want to install mysql.
626
684
  coerce_tests! %r{inspect on Model class does not raise}
627
-
628
685
  end
629
686
 
630
687
 
@@ -632,7 +689,6 @@ end
632
689
 
633
690
  require 'models/topic'
634
691
  class TransactionTest < ActiveRecord::TestCase
635
-
636
692
  coerce_tests! :test_releasing_named_savepoints
637
693
  def test_releasing_named_savepoints_coerced
638
694
  Topic.transaction do
@@ -642,7 +698,6 @@ class TransactionTest < ActiveRecord::TestCase
642
698
  Topic.connection.release_savepoint("another")
643
699
  end
644
700
  end
645
-
646
701
  end
647
702
 
648
703
 
@@ -650,7 +705,6 @@ end
650
705
 
651
706
  require 'models/tag'
652
707
  class TransactionIsolationTest < ActiveRecord::TestCase
653
-
654
708
  # SQL Server will lock the table for counts even when both
655
709
  # connections are `READ COMMITTED`. So we bypass with `READPAST`.
656
710
  coerce_tests! %r{read committed}
@@ -667,32 +721,32 @@ class TransactionIsolationTest < ActiveRecord::TestCase
667
721
 
668
722
  # I really need some help understanding this one.
669
723
  coerce_tests! %r{repeatable read}
670
-
671
- end
672
-
673
-
674
- require 'models/post'
675
- module ActiveRecord
676
- class WhereChainTest < ActiveRecord::TestCase
677
-
678
- coerce_tests! :test_not_eq_with_array_parameter
679
- def test_not_eq_with_array_parameter_coerced
680
- expected = Arel::Nodes::Not.new("title = N'hello'")
681
- relation = Post.where.not(['title = ?', 'hello'])
682
- assert_equal([expected], relation.where_values)
683
- end
684
-
685
- end
686
724
  end
687
725
 
688
726
 
689
727
 
690
728
 
729
+ require 'models/book'
691
730
  class ViewWithPrimaryKeyTest < ActiveRecord::TestCase
731
+ # We have a few view tables. use includes vs equality.
732
+ coerce_tests! :test_views
733
+ def test_views_coerced
734
+ assert_includes @connection.views, Ebook.table_name
735
+ end
692
736
 
693
737
  # We do better than ActiveRecord and find the views PK.
694
738
  coerce_tests! :test_does_not_assume_id_column_as_primary_key
695
-
739
+ def test_does_not_assume_id_column_as_primary_key_coerced
740
+ model = Class.new(ActiveRecord::Base) { self.table_name = "ebooks" }
741
+ assert_equal 'id', model.primary_key
742
+ end
743
+ end
744
+ class ViewWithoutPrimaryKeyTest < ActiveRecord::TestCase
745
+ # We have a few view tables. use includes vs equality.
746
+ coerce_tests! :test_views
747
+ def test_views_coerced
748
+ assert_includes @connection.views, Paperback.table_name
749
+ end
696
750
  end
697
751
 
698
752
 
@@ -700,7 +754,6 @@ end
700
754
 
701
755
  require 'models/author'
702
756
  class YamlSerializationTest < ActiveRecord::TestCase
703
-
704
757
  coerce_tests! :test_types_of_virtual_columns_are_not_changed_on_round_trip
705
758
  def test_types_of_virtual_columns_are_not_changed_on_round_trip_coerced
706
759
  author = Author.select('authors.*, 5 as posts_count').first
@@ -708,6 +761,48 @@ class YamlSerializationTest < ActiveRecord::TestCase
708
761
  assert_equal 5, author.posts_count
709
762
  assert_equal 5, dumped.posts_count
710
763
  end
764
+ end
765
+
766
+
767
+
768
+
769
+ class DateTimePrecisionTest < ActiveRecord::TestCase
770
+ # Original test had `7` which we support vs `8` which we use.
771
+ coerce_tests! :test_invalid_datetime_precision_raises_error
772
+ def test_invalid_datetime_precision_raises_error_coerced
773
+ assert_raises ActiveRecord::ActiveRecordError do
774
+ @connection.create_table(:foos, force: true) do |t|
775
+ t.timestamps precision: 8
776
+ end
777
+ end
778
+ end
779
+ end
780
+
781
+
782
+
711
783
 
784
+ class DefaultNumbersTest < ActiveRecord::TestCase
785
+ # We do better with native types and do not return strings for everything.
786
+ coerce_tests! :test_default_positive_integer
787
+ def test_default_positive_integer_coerced
788
+ record = DefaultNumber.new
789
+ assert_equal 7, record.positive_integer
790
+ assert_equal 7, record.positive_integer_before_type_cast
791
+ end
792
+ coerce_tests! :test_default_negative_integer
793
+ def test_default_negative_integer_coerced
794
+ record = DefaultNumber.new
795
+ assert_equal -5, record.negative_integer
796
+ assert_equal -5, record.negative_integer_before_type_cast
797
+ end
712
798
  end
713
799
 
800
+
801
+
802
+
803
+ module ActiveRecord
804
+ class CollectionCacheKeyTest < ActiveRecord::TestCase
805
+ # Will trust rails has this sorted since you cant offset without a limit.
806
+ coerce_tests! %r{with offset which return 0 rows}
807
+ end
808
+ end