activerecord-sqlserver-adapter 4.2.18 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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