activerecord-jdbcsqlserver-adapter 50.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 (148) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.travis.yml +27 -0
  4. data/CHANGELOG.md +124 -0
  5. data/CODE_OF_CONDUCT.md +31 -0
  6. data/Dockerfile +20 -0
  7. data/Gemfile +77 -0
  8. data/Guardfile +29 -0
  9. data/MIT-LICENSE +20 -0
  10. data/RAILS5-TODO.md +5 -0
  11. data/README.md +93 -0
  12. data/RUNNING_UNIT_TESTS.md +96 -0
  13. data/Rakefile +46 -0
  14. data/VERSION +1 -0
  15. data/activerecord-jdbcsqlserver-adapter.gemspec +21 -0
  16. data/appveyor.yml +39 -0
  17. data/docker-compose.ci.yml +11 -0
  18. data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +27 -0
  19. data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +25 -0
  20. data/lib/active_record/connection_adapters/sqlserver/core_ext/date_time.rb +58 -0
  21. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +47 -0
  22. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +4 -0
  23. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +49 -0
  24. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +362 -0
  25. data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +67 -0
  26. data/lib/active_record/connection_adapters/sqlserver/errors.rb +7 -0
  27. data/lib/active_record/connection_adapters/sqlserver/jdbc_overrides.rb +192 -0
  28. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +99 -0
  29. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +34 -0
  30. data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +16 -0
  31. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +517 -0
  32. data/lib/active_record/connection_adapters/sqlserver/showplan.rb +66 -0
  33. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +66 -0
  34. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +22 -0
  35. data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +20 -0
  36. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +112 -0
  37. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +64 -0
  38. data/lib/active_record/connection_adapters/sqlserver/type.rb +49 -0
  39. data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +19 -0
  40. data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +21 -0
  41. data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +15 -0
  42. data/lib/active_record/connection_adapters/sqlserver/type/char.rb +32 -0
  43. data/lib/active_record/connection_adapters/sqlserver/type/data.rb +30 -0
  44. data/lib/active_record/connection_adapters/sqlserver/type/date.rb +61 -0
  45. data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +71 -0
  46. data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +17 -0
  47. data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +23 -0
  48. data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +21 -0
  49. data/lib/active_record/connection_adapters/sqlserver/type/float.rb +19 -0
  50. data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +15 -0
  51. data/lib/active_record/connection_adapters/sqlserver/type/json.rb +11 -0
  52. data/lib/active_record/connection_adapters/sqlserver/type/money.rb +25 -0
  53. data/lib/active_record/connection_adapters/sqlserver/type/real.rb +19 -0
  54. data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +15 -0
  55. data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +25 -0
  56. data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +29 -0
  57. data/lib/active_record/connection_adapters/sqlserver/type/string.rb +12 -0
  58. data/lib/active_record/connection_adapters/sqlserver/type/text.rb +19 -0
  59. data/lib/active_record/connection_adapters/sqlserver/type/time.rb +68 -0
  60. data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +93 -0
  61. data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +19 -0
  62. data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +25 -0
  63. data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +21 -0
  64. data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +12 -0
  65. data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +19 -0
  66. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +26 -0
  67. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +24 -0
  68. data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +36 -0
  69. data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +26 -0
  70. data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +24 -0
  71. data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +26 -0
  72. data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +24 -0
  73. data/lib/active_record/connection_adapters/sqlserver/utils.rb +146 -0
  74. data/lib/active_record/connection_adapters/sqlserver/version.rb +11 -0
  75. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +445 -0
  76. data/lib/active_record/connection_adapters/sqlserver_column.rb +28 -0
  77. data/lib/active_record/jdbc_sqlserver_connection_methods.rb +31 -0
  78. data/lib/active_record/sqlserver_base.rb +16 -0
  79. data/lib/active_record/tasks/sqlserver_database_tasks.rb +131 -0
  80. data/lib/activerecord-jdbcsqlserver-adapter.rb +24 -0
  81. data/lib/activerecord-sqlserver-adapter.rb +1 -0
  82. data/lib/arel/visitors/sqlserver.rb +205 -0
  83. data/lib/arel_sqlserver.rb +3 -0
  84. data/test/appveyor/dbsetup.ps1 +27 -0
  85. data/test/appveyor/dbsetup.sql +11 -0
  86. data/test/bin/wait-for.sh +79 -0
  87. data/test/cases/adapter_test_sqlserver.rb +430 -0
  88. data/test/cases/coerced_tests.rb +845 -0
  89. data/test/cases/column_test_sqlserver.rb +812 -0
  90. data/test/cases/connection_test_sqlserver.rb +71 -0
  91. data/test/cases/execute_procedure_test_sqlserver.rb +45 -0
  92. data/test/cases/fetch_test_sqlserver.rb +57 -0
  93. data/test/cases/fully_qualified_identifier_test_sqlserver.rb +76 -0
  94. data/test/cases/helper_sqlserver.rb +44 -0
  95. data/test/cases/index_test_sqlserver.rb +47 -0
  96. data/test/cases/json_test_sqlserver.rb +32 -0
  97. data/test/cases/migration_test_sqlserver.rb +61 -0
  98. data/test/cases/order_test_sqlserver.rb +147 -0
  99. data/test/cases/pessimistic_locking_test_sqlserver.rb +94 -0
  100. data/test/cases/rake_test_sqlserver.rb +169 -0
  101. data/test/cases/schema_dumper_test_sqlserver.rb +234 -0
  102. data/test/cases/schema_test_sqlserver.rb +54 -0
  103. data/test/cases/scratchpad_test_sqlserver.rb +8 -0
  104. data/test/cases/showplan_test_sqlserver.rb +65 -0
  105. data/test/cases/specific_schema_test_sqlserver.rb +180 -0
  106. data/test/cases/transaction_test_sqlserver.rb +91 -0
  107. data/test/cases/utils_test_sqlserver.rb +129 -0
  108. data/test/cases/uuid_test_sqlserver.rb +49 -0
  109. data/test/config.yml +38 -0
  110. data/test/debug.rb +14 -0
  111. data/test/fixtures/1px.gif +0 -0
  112. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +11 -0
  113. data/test/models/sqlserver/booking.rb +3 -0
  114. data/test/models/sqlserver/customers_view.rb +3 -0
  115. data/test/models/sqlserver/datatype.rb +3 -0
  116. data/test/models/sqlserver/datatype_migration.rb +8 -0
  117. data/test/models/sqlserver/dollar_table_name.rb +3 -0
  118. data/test/models/sqlserver/dot_table_name.rb +3 -0
  119. data/test/models/sqlserver/edge_schema.rb +13 -0
  120. data/test/models/sqlserver/fk_has_fk.rb +3 -0
  121. data/test/models/sqlserver/fk_has_pk.rb +3 -0
  122. data/test/models/sqlserver/natural_pk_data.rb +4 -0
  123. data/test/models/sqlserver/natural_pk_int_data.rb +3 -0
  124. data/test/models/sqlserver/no_pk_data.rb +3 -0
  125. data/test/models/sqlserver/object_default.rb +3 -0
  126. data/test/models/sqlserver/quoted_table.rb +7 -0
  127. data/test/models/sqlserver/quoted_view_1.rb +3 -0
  128. data/test/models/sqlserver/quoted_view_2.rb +3 -0
  129. data/test/models/sqlserver/sst_memory.rb +3 -0
  130. data/test/models/sqlserver/string_default.rb +3 -0
  131. data/test/models/sqlserver/string_defaults_big_view.rb +3 -0
  132. data/test/models/sqlserver/string_defaults_view.rb +3 -0
  133. data/test/models/sqlserver/tinyint_pk.rb +3 -0
  134. data/test/models/sqlserver/upper.rb +3 -0
  135. data/test/models/sqlserver/uppered.rb +3 -0
  136. data/test/models/sqlserver/uuid.rb +3 -0
  137. data/test/schema/datatypes/2012.sql +55 -0
  138. data/test/schema/enable-in-memory-oltp.sql +81 -0
  139. data/test/schema/sqlserver_specific_schema.rb +238 -0
  140. data/test/support/coerceable_test_sqlserver.rb +49 -0
  141. data/test/support/connection_reflection.rb +34 -0
  142. data/test/support/load_schema_sqlserver.rb +29 -0
  143. data/test/support/minitest_sqlserver.rb +1 -0
  144. data/test/support/paths_sqlserver.rb +50 -0
  145. data/test/support/rake_helpers.rb +41 -0
  146. data/test/support/sql_counter_sqlserver.rb +28 -0
  147. data/test/support/test_in_memory_oltp.rb +15 -0
  148. metadata +310 -0
@@ -0,0 +1,845 @@
1
+ require 'cases/helper_sqlserver'
2
+
3
+
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
15
+ end
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
25
+ end
26
+ end
27
+
28
+
29
+
30
+
31
+ require 'models/event'
32
+ module ActiveRecord
33
+ class AdapterTest < ActiveRecord::TestCase
34
+ # As far as I can tell, SQL Server does not support null bytes in strings.
35
+ coerce_tests! :test_update_prepared_statement
36
+ coerce_tests! :test_log_invalid_encoding if defined? JRUBY_VERSION # JRuby just happily converts the encoding
37
+
38
+ # So sp_executesql swallows this exception. Run without prpared to see it.
39
+ coerce_tests! :test_value_limit_violations_are_translated_to_specific_exception
40
+ def test_value_limit_violations_are_translated_to_specific_exception_coerced
41
+ connection.unprepared_statement do
42
+ error = assert_raises(ActiveRecord::ValueTooLong) do
43
+ Event.create(title: 'abcdefgh')
44
+ end
45
+ assert_not_nil error.cause
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+
52
+
53
+
54
+ require 'models/topic'
55
+ class AttributeMethodsTest < ActiveRecord::TestCase
56
+ coerce_tests! :test_typecast_attribute_from_select_to_false
57
+ def test_typecast_attribute_from_select_to_false_coerced
58
+ Topic.create(:title => 'Budget')
59
+ topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 2, 1, 0) as is_test").first
60
+ assert !topic.is_test?
61
+ end
62
+
63
+ coerce_tests! :test_typecast_attribute_from_select_to_true
64
+ def test_typecast_attribute_from_select_to_true_coerced
65
+ Topic.create(:title => 'Budget')
66
+ topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 1, 1, 0) as is_test").first
67
+ assert topic.is_test?
68
+ end
69
+ end
70
+
71
+
72
+
73
+
74
+ class BasicsTest < ActiveRecord::TestCase
75
+ coerce_tests! :test_column_names_are_escaped
76
+ def test_column_names_are_escaped_coerced
77
+ conn = ActiveRecord::Base.connection
78
+ assert_equal '[t]]]', conn.quote_column_name('t]')
79
+ end
80
+
81
+ # We do not have do the DecimalWithoutScale type.
82
+ coerce_tests! :test_numeric_fields
83
+ coerce_tests! :test_numeric_fields_with_scale
84
+
85
+ # Just like PostgreSQLAdapter does.
86
+ coerce_tests! :test_respect_internal_encoding
87
+
88
+ # Caused in Rails v4.2.5 by adding `firm_id` column in this http://git.io/vBfMs
89
+ # commit. Trust Rails has this covered.
90
+ coerce_tests! :test_find_keeps_multiple_group_values
91
+ end
92
+
93
+
94
+
95
+
96
+ class BelongsToAssociationsTest < ActiveRecord::TestCase
97
+ # Since @client.firm is a single first/top, and we use FETCH the order clause is used.
98
+ coerce_tests! :test_belongs_to_does_not_use_order_by
99
+
100
+ coerce_tests! :test_belongs_to_with_primary_key_joins_on_correct_column
101
+ def test_belongs_to_with_primary_key_joins_on_correct_column_coerced
102
+ sql = Client.joins(:firm_with_primary_key).to_sql
103
+ assert_no_match(/\[firm_with_primary_keys_companies\]\.\[id\]/, sql)
104
+ assert_match(/\[firm_with_primary_keys_companies\]\.\[name\]/, sql)
105
+ end
106
+ end
107
+
108
+
109
+
110
+
111
+ module ActiveRecord
112
+ class BindParameterTest < ActiveRecord::TestCase
113
+ # Never finds `sql` since we use `EXEC sp_executesql` wrappers.
114
+ coerce_tests! :test_binds_are_logged
115
+ end
116
+ end
117
+
118
+
119
+
120
+
121
+ class CalculationsTest < ActiveRecord::TestCase
122
+ # Are decimal, not integer.
123
+ coerce_tests! :test_should_return_decimal_average_of_integer_field
124
+ def test_should_return_decimal_average_of_integer_field_coerced
125
+ value = Account.average(:id)
126
+ assert_equal BigDecimal('3.0').to_s, BigDecimal(value).to_s
127
+ end
128
+
129
+ coerce_tests! :test_limit_is_kept
130
+ def test_limit_is_kept_coerced
131
+ queries = capture_sql_ss { Account.limit(1).count }
132
+ assert_equal 1, queries.length
133
+ queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1}
134
+ end unless defined? JRUBY_VERSION
135
+
136
+ def test_limit_is_kept_coerced
137
+ queries = capture_sql_ss { Account.limit(1).count }
138
+ assert_equal 1, queries.length
139
+ queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT \? ROWS ONLY}
140
+ end if defined? JRUBY_VERSION
141
+
142
+ coerce_tests! :test_limit_with_offset_is_kept
143
+ def test_limit_with_offset_is_kept_coerced
144
+ queries = capture_sql_ss { Account.limit(1).offset(1).count }
145
+ assert_equal 1, queries.length
146
+ queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY.*@0 = 1, @1 = 1}
147
+ end unless defined? JRUBY_VERSION
148
+
149
+ def test_limit_with_offset_is_kept_coerced
150
+ queries = capture_sql_ss { Account.limit(1).offset(1).count }
151
+ assert_equal 1, queries.length
152
+ queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET \? ROWS FETCH NEXT \? ROWS ONLY}
153
+ end if defined? JRUBY_VERSION
154
+
155
+ # Leave it up to users to format selects/functions so HAVING works correctly.
156
+ coerce_tests! :test_having_with_strong_parameters
157
+ end
158
+
159
+
160
+
161
+ module ActiveRecord
162
+ class Migration
163
+ class ChangeSchemaTest < ActiveRecord::TestCase
164
+ # We test these.
165
+ coerce_tests! :test_create_table_with_bigint,
166
+ :test_create_table_with_defaults
167
+ end
168
+ class ChangeSchemaWithDependentObjectsTest < ActiveRecord::TestCase
169
+ # In SQL Server you have to delete the tables yourself in the right order.
170
+ coerce_tests! :test_create_table_with_force_cascade_drops_dependent_objects
171
+ end
172
+ end
173
+ end
174
+
175
+
176
+
177
+
178
+ module ActiveRecord
179
+ class Migration
180
+ class ColumnAttributesTest < ActiveRecord::TestCase
181
+ # We have a default 4000 varying character limit.
182
+ coerce_tests! :test_add_column_without_limit
183
+ def test_add_column_without_limit_coerced
184
+ add_column :test_models, :description, :string, limit: nil
185
+ TestModel.reset_column_information
186
+ TestModel.columns_hash["description"].limit.must_equal 4000
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+
193
+
194
+
195
+ module ActiveRecord
196
+ class Migration
197
+ class ColumnsTest
198
+ # Our defaults are real 70000 integers vs '70000' strings.
199
+ coerce_tests! :test_rename_column_preserves_default_value_not_null
200
+ def test_rename_column_preserves_default_value_not_null_coerced
201
+ add_column 'test_models', 'salary', :integer, :default => 70000
202
+ default_before = connection.columns("test_models").find { |c| c.name == "salary" }.default
203
+ assert_equal 70000, default_before
204
+ rename_column "test_models", "salary", "annual_salary"
205
+ TestModel.reset_column_information
206
+ assert TestModel.column_names.include?("annual_salary")
207
+ default_after = connection.columns("test_models").find { |c| c.name == "annual_salary" }.default
208
+ assert_equal 70000, default_after
209
+ end
210
+
211
+ # Dropping the column removes the single index.
212
+ coerce_tests! :test_remove_column_with_multi_column_index
213
+ def test_remove_column_with_multi_column_index_coerced
214
+ add_column "test_models", :hat_size, :integer
215
+ add_column "test_models", :hat_style, :string, :limit => 100
216
+ add_index "test_models", ["hat_style", "hat_size"], :unique => true
217
+ assert_equal 1, connection.indexes('test_models').size
218
+ remove_column("test_models", "hat_size")
219
+ assert_equal [], connection.indexes('test_models').map(&:name)
220
+ end
221
+
222
+ # Choose `StatementInvalid` vs `ActiveRecordError`.
223
+ coerce_tests! :test_rename_nonexistent_column
224
+ def test_rename_nonexistent_column_coerced
225
+ exception = ActiveRecord::StatementInvalid
226
+ assert_raise(exception) do
227
+ rename_column "test_models", "nonexistent", "should_fail"
228
+ end
229
+ end
230
+ end
231
+ end
232
+ end
233
+
234
+
235
+
236
+
237
+ class MigrationTest < ActiveRecord::TestCase
238
+ # We do not have do the DecimalWithoutScale type.
239
+ coerce_tests! :test_add_table_with_decimals
240
+ def test_add_table_with_decimals_coerced
241
+ Person.connection.drop_table :big_numbers rescue nil
242
+ assert !BigNumber.table_exists?
243
+ GiveMeBigNumbers.up
244
+ BigNumber.reset_column_information
245
+ assert BigNumber.create(
246
+ :bank_balance => 1586.43,
247
+ :big_bank_balance => BigDecimal("1000234000567.95"),
248
+ :world_population => 6000000000,
249
+ :my_house_population => 3,
250
+ :value_of_e => BigDecimal("2.7182818284590452353602875")
251
+ )
252
+ b = BigNumber.first
253
+ assert_not_nil b
254
+ assert_not_nil b.bank_balance
255
+ assert_not_nil b.big_bank_balance
256
+ assert_not_nil b.world_population
257
+ assert_not_nil b.my_house_population
258
+ assert_not_nil b.value_of_e
259
+ assert_kind_of BigDecimal, b.world_population
260
+ assert_equal '6000000000.0', b.world_population.to_s
261
+ assert_kind_of Integer, b.my_house_population
262
+ assert_equal 3, b.my_house_population
263
+ assert_kind_of BigDecimal, b.bank_balance
264
+ assert_equal BigDecimal("1586.43"), b.bank_balance
265
+ assert_kind_of BigDecimal, b.big_bank_balance
266
+ assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
267
+ GiveMeBigNumbers.down
268
+ assert_raise(ActiveRecord::StatementInvalid) { BigNumber.first }
269
+ end
270
+
271
+ # For some reason our tests set Rails.@_env which breaks test env switching.
272
+ coerce_tests! :test_migration_sets_internal_metadata_even_when_fully_migrated
273
+ coerce_tests! :test_internal_metadata_stores_environment
274
+ end
275
+
276
+
277
+
278
+
279
+ class CoreTest < ActiveRecord::TestCase
280
+ # I think fixtures are useing the wrong time zone and the `:first`
281
+ # `topics`.`bonus_time` attribute of 2005-01-30t15:28:00.00+01:00 is
282
+ # getting local EST time for me and set to "09:28:00.0000000".
283
+ coerce_tests! :test_pretty_print_persisted
284
+ end
285
+
286
+
287
+
288
+
289
+ module ActiveRecord
290
+ module ConnectionAdapters
291
+ # Just like PostgreSQLAdapter does.
292
+ TypeLookupTest.coerce_all_tests! if defined?(TypeLookupTest)
293
+
294
+ # All sorts of errors due to how we test. Even setting ENV['RAILS_ENV'] to
295
+ # a value of 'default_env' will still show tests failing. Just ignoring all
296
+ # of them since we have no monkey in this circus.
297
+ MergeAndResolveDefaultUrlConfigTest.coerce_all_tests! if defined?(MergeAndResolveDefaultUrlConfigTest)
298
+ end
299
+ end
300
+
301
+
302
+
303
+
304
+ module ActiveRecord
305
+ class DatabaseTasksCreateAllTest < ActiveRecord::TestCase
306
+ # We extend `local_database?` so that common VM IPs can be used.
307
+ coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
308
+ end
309
+ class DatabaseTasksDropAllTest < ActiveRecord::TestCase
310
+ # We extend `local_database?` so that common VM IPs can be used.
311
+ coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
312
+ end
313
+ end
314
+
315
+
316
+
317
+
318
+ class DefaultScopingTest < ActiveRecord::TestCase
319
+ # We are not doing order duplicate removal anymore.
320
+ coerce_tests! :test_order_in_default_scope_should_not_prevail
321
+
322
+ # Use our escaped format in assertion.
323
+ coerce_tests! :test_with_abstract_class_scope_should_be_executed_in_correct_context
324
+ def test_with_abstract_class_scope_should_be_executed_in_correct_context_coerced
325
+ vegetarian_pattern, gender_pattern = [/[lions].[is_vegetarian]/, /[lions].[gender]/]
326
+ assert_match vegetarian_pattern, Lion.all.to_sql
327
+ assert_match gender_pattern, Lion.female.to_sql
328
+ end
329
+ end
330
+
331
+
332
+
333
+
334
+ require 'models/post'
335
+ require 'models/subscriber'
336
+ class EachTest < ActiveRecord::TestCase
337
+ # Quoting in tests does not cope with bracket quoting.
338
+ coerce_tests! :test_find_in_batches_should_quote_batch_order
339
+ def test_find_in_batches_should_quote_batch_order_coerced
340
+ c = Post.connection
341
+ assert_sql(/ORDER BY \[posts\]\.\[id\]/) do
342
+ Post.find_in_batches(:batch_size => 1) do |batch|
343
+ assert_kind_of Array, batch
344
+ assert_kind_of Post, batch.first
345
+ end
346
+ end
347
+ end
348
+
349
+ # Quoting in tests does not cope with bracket quoting.
350
+ coerce_tests! :test_in_batches_should_quote_batch_order
351
+ def test_in_batches_should_quote_batch_order_coerced
352
+ c = Post.connection
353
+ assert_sql(/ORDER BY \[posts\]\.\[id\]/) do
354
+ Post.in_batches(of: 1) do |relation|
355
+ assert_kind_of ActiveRecord::Relation, relation
356
+ assert_kind_of Post, relation.first
357
+ end
358
+ end
359
+ end
360
+ end
361
+
362
+
363
+
364
+
365
+ class EagerAssociationTest < ActiveRecord::TestCase
366
+ # Use LEN() vs length() function.
367
+ coerce_tests! :test_count_with_include
368
+ def test_count_with_include_coerced
369
+ assert_equal 3, authors(:david).posts_with_comments.where("LEN(comments.body) > 15").references(:comments).count
370
+ end
371
+
372
+ # Use TOP (1) in scope vs limit 1.
373
+ coerce_tests! %r{including association based on sql condition and no database column}
374
+ end
375
+
376
+
377
+
378
+
379
+ require 'models/topic'
380
+ class FinderTest < ActiveRecord::TestCase
381
+ coerce_tests! %r{doesn't have implicit ordering},
382
+ :test_find_doesnt_have_implicit_ordering # We have implicit ordering, via FETCH.
383
+
384
+ coerce_tests! :test_exists_does_not_select_columns_without_alias
385
+ def test_exists_does_not_select_columns_without_alias_coerced
386
+ assert_sql(/SELECT\s+1 AS one FROM \[topics\].*OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) do
387
+ Topic.exists?
388
+ end
389
+ end unless defined? JRUBY_VERSION
390
+
391
+ def test_exists_does_not_select_columns_without_alias_coerced
392
+ # Unfortunately the best we can do is check for ? with prepared statements on
393
+ assert_sql(/SELECT\s+1 AS one FROM \[topics\].*OFFSET 0 ROWS FETCH NEXT \? ROWS ONLY/i) do
394
+ Topic.exists?
395
+ end
396
+ end if defined? JRUBY_VERSION
397
+
398
+ coerce_tests! :test_string_sanitation
399
+ def test_string_sanitation_coerced
400
+ assert_not_equal "'something ' 1=1'", ActiveRecord::Base.sanitize("something ' 1=1")
401
+ assert_equal "N'something; select table'", ActiveRecord::Base.sanitize("something; select table")
402
+ end
403
+
404
+ coerce_tests! :test_take_and_first_and_last_with_integer_should_use_sql_limit
405
+ def test_take_and_first_and_last_with_integer_should_use_sql_limit_coerced
406
+ assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 3/) { Topic.take(3).entries }
407
+ assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 2/) { Topic.first(2).entries }
408
+ assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 5/) { Topic.last(5).entries }
409
+ end unless defined? JRUBY_VERSION
410
+
411
+ def test_take_and_first_and_last_with_integer_should_use_sql_limit_coerced
412
+ # Unfortunately the best we can do is check for ? with prepared statements on
413
+ assert_sql(/OFFSET 0 ROWS FETCH NEXT \? ROWS ONLY/) { Topic.take(3).entries }
414
+ assert_sql(/OFFSET 0 ROWS FETCH NEXT \? ROWS ONLY/) { Topic.first(2).entries }
415
+ assert_sql(/OFFSET 0 ROWS FETCH NEXT \? ROWS ONLY/) { Topic.last(5).entries }
416
+ end if defined? JRUBY_VERSION
417
+
418
+ # This fails only when run in the full test suite task. Just taking it out of the mix.
419
+ coerce_tests! :test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct
420
+
421
+ # Can not use array condition due to not finding right type and hence fractional second quoting.
422
+ coerce_tests! :test_condition_utc_time_interpolation_with_default_timezone_local
423
+ def test_condition_utc_time_interpolation_with_default_timezone_local_coerced
424
+ with_env_tz 'America/New_York' do
425
+ with_timezone_config default: :local do
426
+ topic = Topic.first
427
+ assert_equal topic, Topic.where(written_on: topic.written_on.getutc).first
428
+ end
429
+ end
430
+ end
431
+
432
+ # Can not use array condition due to not finding right type and hence fractional second quoting.
433
+ coerce_tests! :test_condition_local_time_interpolation_with_default_timezone_utc
434
+ def test_condition_local_time_interpolation_with_default_timezone_utc_coerced
435
+ with_env_tz 'America/New_York' do
436
+ with_timezone_config default: :utc do
437
+ topic = Topic.first
438
+ assert_equal topic, Topic.where(written_on: topic.written_on.getlocal).first
439
+ end
440
+ end
441
+ end
442
+ end
443
+
444
+
445
+
446
+
447
+ module ActiveRecord
448
+ class Migration
449
+ class ForeignKeyTest < ActiveRecord::TestCase
450
+ # We do not support :restrict.
451
+ coerce_tests! :test_add_on_delete_restrict_foreign_key
452
+ def test_add_on_delete_restrict_foreign_key_coerced
453
+ assert_raises ArgumentError do
454
+ @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_delete: :restrict
455
+ end
456
+ assert_raises ArgumentError do
457
+ @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_update: :restrict
458
+ end
459
+ end
460
+ end
461
+ end
462
+ end
463
+
464
+
465
+
466
+
467
+ class HasOneAssociationsTest < ActiveRecord::TestCase
468
+ # We use OFFSET/FETCH vs TOP. So we always have an order.
469
+ coerce_tests! :test_has_one_does_not_use_order_by
470
+ end
471
+
472
+
473
+
474
+
475
+ require 'models/company'
476
+ class InheritanceTest < ActiveRecord::TestCase
477
+ coerce_tests! :test_a_bad_type_column
478
+ def test_a_bad_type_column_coerced
479
+ Company.connection.with_identity_insert_enabled('companies') do
480
+ Company.connection.insert "INSERT INTO companies (id, #{QUOTED_TYPE}, name) VALUES(100, 'bad_class!', 'Not happening')"
481
+ end
482
+ assert_raise(ActiveRecord::SubclassNotFound) { Company.find(100) }
483
+ end
484
+
485
+ coerce_tests! :test_eager_load_belongs_to_primary_key_quoting
486
+ def test_eager_load_belongs_to_primary_key_quoting_coerced
487
+ con = Account.connection
488
+ assert_sql(/\[companies\]\.\[id\] = 1/) do
489
+ Account.all.merge!(:includes => :firm).find(1)
490
+ end
491
+ end
492
+ end
493
+
494
+
495
+
496
+
497
+ class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
498
+ # Uses || operator in SQL. Just trust core gets value out of this test.
499
+ coerce_tests! :test_does_not_override_select
500
+ end
501
+
502
+
503
+
504
+
505
+ class NamedScopingTest < ActiveRecord::TestCase
506
+ # This works now because we add an `order(:id)` sort to break the order tie for deterministic results.
507
+ coerce_tests! :test_scopes_honor_current_scopes_from_when_defined
508
+ def test_scopes_honor_current_scopes_from_when_defined_coerced
509
+ assert !Post.ranked_by_comments.order(:id).limit_by(5).empty?
510
+ assert !authors(:david).posts.ranked_by_comments.order(:id).limit_by(5).empty?
511
+ assert_not_equal Post.ranked_by_comments.order(:id).limit_by(5), authors(:david).posts.ranked_by_comments.order(:id).limit_by(5)
512
+ assert_not_equal Post.order(:id).top(5), authors(:david).posts.order(:id).top(5)
513
+ # Oracle sometimes sorts differently if WHERE condition is changed
514
+ 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)
515
+ assert_equal Post.ranked_by_comments.limit_by(5), Post.top(5)
516
+ end
517
+ end
518
+
519
+
520
+
521
+
522
+ require 'models/developer'
523
+ require 'models/computer'
524
+ class NestedRelationScopingTest < ActiveRecord::TestCase
525
+ coerce_tests! :test_merge_options
526
+ def test_merge_options_coerced
527
+ Developer.where('salary = 80000').scoping do
528
+ Developer.limit(10).scoping do
529
+ devs = Developer.all
530
+ sql = devs.to_sql
531
+ assert_match '(salary = 80000)', sql
532
+ assert_match 'FETCH NEXT 10 ROWS ONLY', sql
533
+ end
534
+ end
535
+ end
536
+ end
537
+
538
+
539
+
540
+
541
+ require 'models/topic'
542
+ class PersistenceTest < ActiveRecord::TestCase
543
+ # We can not UPDATE identity columns.
544
+ coerce_tests! :test_update_columns_changing_id
545
+
546
+ # Previous test required updating a identity column.
547
+ coerce_tests! :test_update_all_doesnt_ignore_order
548
+ def test_update_all_doesnt_ignore_order_coerced
549
+ david, mary = authors(:david), authors(:mary)
550
+ david.id.must_equal 1
551
+ mary.id.must_equal 2
552
+ david.name.wont_equal mary.name
553
+ assert_sql(/UPDATE.*\(SELECT \[authors\].\[id\] FROM \[authors\].*ORDER BY \[authors\].\[id\]/i) do
554
+ Author.where('[id] > 1').order(:id).update_all(name: 'Test')
555
+ end
556
+ david.reload.name.must_equal 'David'
557
+ mary.reload.name.must_equal 'Test'
558
+ end
559
+
560
+ # We can not UPDATE identity columns.
561
+ coerce_tests! :test_update_attributes
562
+ def test_update_attributes_coerced
563
+ topic = Topic.find(1)
564
+ assert !topic.approved?
565
+ assert_equal "The First Topic", topic.title
566
+ topic.update_attributes("approved" => true, "title" => "The First Topic Updated")
567
+ topic.reload
568
+ assert topic.approved?
569
+ assert_equal "The First Topic Updated", topic.title
570
+ topic.update_attributes(approved: false, title: "The First Topic")
571
+ topic.reload
572
+ assert !topic.approved?
573
+ assert_equal "The First Topic", topic.title
574
+ # SQLServer: Here is where it breaks down. No exceptions.
575
+ # assert_raise(ActiveRecord::RecordNotUnique, ActiveRecord::StatementInvalid) do
576
+ # topic.update_attributes(id: 3, title: "Hm is it possible?")
577
+ # end
578
+ # assert_not_equal "Hm is it possible?", Topic.find(3).title
579
+ # topic.update_attributes(id: 1234)
580
+ # assert_nothing_raised { topic.reload }
581
+ # assert_equal topic.title, Topic.find(1234).title
582
+ end
583
+ end
584
+
585
+
586
+
587
+
588
+ require 'models/topic'
589
+ module ActiveRecord
590
+ class PredicateBuilderTest < ActiveRecord::TestCase
591
+ coerce_tests! :test_registering_new_handlers
592
+ def test_registering_new_handlers_coerced
593
+ Topic.predicate_builder.register_handler(Regexp, proc do |column, value|
594
+ Arel::Nodes::InfixOperation.new('~', column, Arel.sql(value.source))
595
+ end)
596
+ assert_match %r{\[topics\].\[title\] ~ rails}i, Topic.where(title: /rails/).to_sql
597
+ ensure
598
+ Topic.reset_column_information
599
+ end
600
+ end
601
+ end
602
+
603
+
604
+
605
+
606
+ require 'models/task'
607
+ class QueryCacheTest < ActiveRecord::TestCase
608
+ coerce_tests! :test_cache_does_not_wrap_string_results_in_arrays
609
+ def test_cache_does_not_wrap_string_results_in_arrays_coerced
610
+ Task.cache do
611
+ assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
612
+ end
613
+ end
614
+ end
615
+
616
+
617
+
618
+
619
+ require 'models/post'
620
+ class RelationTest < ActiveRecord::TestCase
621
+ # Use LEN vs LENGTH function.
622
+ coerce_tests! :test_reverse_order_with_function
623
+ def test_reverse_order_with_function_coerced
624
+ topics = Topic.order("LEN(title)").reverse_order
625
+ assert_equal topics(:second).title, topics.first.title
626
+ end
627
+
628
+ # Use LEN vs LENGTH function.
629
+ coerce_tests! :test_reverse_order_with_function_other_predicates
630
+ def test_reverse_order_with_function_other_predicates_coerced
631
+ topics = Topic.order("author_name, LEN(title), id").reverse_order
632
+ assert_equal topics(:second).title, topics.first.title
633
+ topics = Topic.order("LEN(author_name), id, LEN(title)").reverse_order
634
+ assert_equal topics(:fifth).title, topics.first.title
635
+ end
636
+
637
+ # We have implicit ordering, via FETCH.
638
+ coerce_tests! %r{doesn't have implicit ordering}
639
+
640
+ # We are not doing order duplicate removal anymore.
641
+ coerce_tests! :test_order_using_scoping
642
+
643
+ # We are not doing order duplicate removal anymore.
644
+ coerce_tests! :test_default_scope_order_with_scope_order
645
+
646
+ # Leave it up to users to format selects/functions so HAVING works correctly.
647
+ coerce_tests! :test_multiple_where_and_having_clauses
648
+ coerce_tests! :test_having_with_binds_for_both_where_and_having
649
+ end
650
+
651
+
652
+
653
+
654
+ require 'models/post'
655
+ class SanitizeTest < ActiveRecord::TestCase
656
+ coerce_tests! :test_sanitize_sql_like_example_use_case
657
+ def test_sanitize_sql_like_example_use_case_coerced
658
+ searchable_post = Class.new(Post) do
659
+ def self.search(term)
660
+ where("title LIKE ?", sanitize_sql_like(term, '!'))
661
+ end
662
+ end
663
+ assert_sql(/\(title LIKE N'20!% !_reduction!_!!'\)/) do
664
+ searchable_post.search("20% _reduction_!").to_a
665
+ end
666
+ end
667
+ end
668
+
669
+
670
+
671
+
672
+ class SchemaDumperTest < ActiveRecord::TestCase
673
+ # We have precision to 38.
674
+ coerce_tests! :test_schema_dump_keeps_large_precision_integer_columns_as_decimal
675
+ def test_schema_dump_keeps_large_precision_integer_columns_as_decimal_coerced
676
+ output = standard_dump
677
+ assert_match %r{t.decimal\s+"atoms_in_universe",\s+precision: 38}, output
678
+ end
679
+
680
+ # This accidently returns the wrong number because of our tables too.
681
+ coerce_tests! :test_types_line_up
682
+
683
+ # This is a poorly written test and really does not catch the bottom'ness it is meant too. Ours throw it off.
684
+ coerce_tests! :test_foreign_keys_are_dumped_at_the_bottom_to_circumvent_dependency_issues
685
+
686
+ # Fall through false positive with no filter.
687
+ coerce_tests! :test_schema_dumps_partial_indices
688
+ def test_schema_dumps_partial_indices_coerced
689
+ index_definition = standard_dump.split(/\n/).grep(/t.index.*company_partial_index/).first.strip
690
+ assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", where: "([rating]>(10))"', index_definition
691
+ end
692
+
693
+ # We do not quote the 2.78 string default.
694
+ coerce_tests! :test_schema_dump_includes_decimal_options
695
+ def test_schema_dump_includes_decimal_options_coerced
696
+ output = dump_all_table_schema([/^[^n]/])
697
+ assert_match %r{precision: 3,[[:space:]]+scale: 2,[[:space:]]+default: 2\.78}, output
698
+ end
699
+ end
700
+
701
+ class SchemaDumperDefaultsTest < ActiveRecord::TestCase
702
+ # These date formats do not match ours. We got these covered in our dumper tests.
703
+ coerce_tests! :test_schema_dump_defaults_with_universally_supported_types
704
+ end
705
+
706
+
707
+
708
+
709
+ class TestAdapterWithInvalidConnection < ActiveRecord::TestCase
710
+ # We trust Rails on this since we do not want to install mysql.
711
+ coerce_tests! %r{inspect on Model class does not raise}
712
+ end
713
+
714
+
715
+
716
+
717
+ require 'models/topic'
718
+ class TransactionTest < ActiveRecord::TestCase
719
+ coerce_tests! :test_releasing_named_savepoints
720
+ def test_releasing_named_savepoints_coerced
721
+ Topic.transaction do
722
+ Topic.connection.create_savepoint("another")
723
+ Topic.connection.release_savepoint("another")
724
+ # We do not have a notion of releasing, so this does nothing vs raise an error.
725
+ Topic.connection.release_savepoint("another")
726
+ end
727
+ end
728
+ end unless defined? JRUBY_VERSION # The rails version of this test passes
729
+
730
+
731
+
732
+
733
+ require 'models/tag'
734
+ class TransactionIsolationTest < ActiveRecord::TestCase
735
+ # SQL Server will lock the table for counts even when both
736
+ # connections are `READ COMMITTED`. So we bypass with `READPAST`.
737
+ coerce_tests! %r{read committed}
738
+ test "read committed coerced" do
739
+ Tag.transaction(isolation: :read_committed) do
740
+ assert_equal 0, Tag.count
741
+ Tag2.transaction do
742
+ Tag2.create
743
+ assert_equal 0, Tag.lock('WITH(READPAST)').count
744
+ end
745
+ end
746
+ assert_equal 1, Tag.count
747
+ end
748
+
749
+ # I really need some help understanding this one.
750
+ coerce_tests! %r{repeatable read}
751
+ end
752
+
753
+
754
+
755
+
756
+ require 'models/book'
757
+ class ViewWithPrimaryKeyTest < ActiveRecord::TestCase
758
+ # We have a few view tables. use includes vs equality.
759
+ coerce_tests! :test_views
760
+ def test_views_coerced
761
+ assert_includes @connection.views, Ebook.table_name
762
+ end
763
+
764
+ # We do better than ActiveRecord and find the views PK.
765
+ coerce_tests! :test_does_not_assume_id_column_as_primary_key
766
+ def test_does_not_assume_id_column_as_primary_key_coerced
767
+ model = Class.new(ActiveRecord::Base) { self.table_name = "ebooks" }
768
+ assert_equal 'id', model.primary_key
769
+ end
770
+ end
771
+ class ViewWithoutPrimaryKeyTest < ActiveRecord::TestCase
772
+ # We have a few view tables. use includes vs equality.
773
+ coerce_tests! :test_views
774
+ def test_views_coerced
775
+ assert_includes @connection.views, Paperback.table_name
776
+ end
777
+ end
778
+
779
+
780
+
781
+
782
+ require 'models/author'
783
+ class YamlSerializationTest < ActiveRecord::TestCase
784
+ coerce_tests! :test_types_of_virtual_columns_are_not_changed_on_round_trip
785
+ def test_types_of_virtual_columns_are_not_changed_on_round_trip_coerced
786
+ author = Author.select('authors.*, 5 as posts_count').first
787
+ dumped = YAML.load(YAML.dump(author))
788
+ assert_equal 5, author.posts_count
789
+ assert_equal 5, dumped.posts_count
790
+ end
791
+ end
792
+
793
+
794
+
795
+
796
+ class DateTimePrecisionTest < ActiveRecord::TestCase
797
+ # Original test had `7` which we support vs `8` which we use.
798
+ coerce_tests! :test_invalid_datetime_precision_raises_error
799
+ def test_invalid_datetime_precision_raises_error_coerced
800
+ assert_raises ActiveRecord::ActiveRecordError do
801
+ @connection.create_table(:foos, force: true) do |t|
802
+ t.timestamps precision: 8
803
+ end
804
+ end
805
+ end
806
+ end
807
+
808
+
809
+
810
+
811
+ class DefaultNumbersTest < ActiveRecord::TestCase
812
+ # We do better with native types and do not return strings for everything.
813
+ coerce_tests! :test_default_positive_integer
814
+ def test_default_positive_integer_coerced
815
+ record = DefaultNumber.new
816
+ assert_equal 7, record.positive_integer
817
+ assert_equal 7, record.positive_integer_before_type_cast
818
+ end
819
+ coerce_tests! :test_default_negative_integer
820
+ def test_default_negative_integer_coerced
821
+ record = DefaultNumber.new
822
+ assert_equal -5, record.negative_integer
823
+ assert_equal -5, record.negative_integer_before_type_cast
824
+ end
825
+ end
826
+
827
+
828
+
829
+
830
+ module ActiveRecord
831
+ class CollectionCacheKeyTest < ActiveRecord::TestCase
832
+ # Will trust rails has this sorted since you cant offset without a limit.
833
+ coerce_tests! %r{with offset which return 0 rows}
834
+ end
835
+ end
836
+
837
+
838
+
839
+
840
+ module ActiveRecord
841
+ class StatementCacheTest < ActiveRecord::TestCase
842
+ # Getting random failures.
843
+ #coerce_tests! :test_find_does_not_use_statement_cache_if_table_name_is_changed
844
+ end
845
+ end