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.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.travis.yml +27 -0
- data/CHANGELOG.md +124 -0
- data/CODE_OF_CONDUCT.md +31 -0
- data/Dockerfile +20 -0
- data/Gemfile +77 -0
- data/Guardfile +29 -0
- data/MIT-LICENSE +20 -0
- data/RAILS5-TODO.md +5 -0
- data/README.md +93 -0
- data/RUNNING_UNIT_TESTS.md +96 -0
- data/Rakefile +46 -0
- data/VERSION +1 -0
- data/activerecord-jdbcsqlserver-adapter.gemspec +21 -0
- data/appveyor.yml +39 -0
- data/docker-compose.ci.yml +11 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +27 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +25 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/date_time.rb +58 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +47 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +4 -0
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +49 -0
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +362 -0
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +67 -0
- data/lib/active_record/connection_adapters/sqlserver/errors.rb +7 -0
- data/lib/active_record/connection_adapters/sqlserver/jdbc_overrides.rb +192 -0
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +99 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +34 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +517 -0
- data/lib/active_record/connection_adapters/sqlserver/showplan.rb +66 -0
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +66 -0
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +22 -0
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +20 -0
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +112 -0
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +64 -0
- data/lib/active_record/connection_adapters/sqlserver/type.rb +49 -0
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +19 -0
- data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +21 -0
- data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +15 -0
- data/lib/active_record/connection_adapters/sqlserver/type/char.rb +32 -0
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +30 -0
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +61 -0
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +71 -0
- data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +17 -0
- data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +23 -0
- data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +21 -0
- data/lib/active_record/connection_adapters/sqlserver/type/float.rb +19 -0
- data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +15 -0
- data/lib/active_record/connection_adapters/sqlserver/type/json.rb +11 -0
- data/lib/active_record/connection_adapters/sqlserver/type/money.rb +25 -0
- data/lib/active_record/connection_adapters/sqlserver/type/real.rb +19 -0
- data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +15 -0
- data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +25 -0
- data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +29 -0
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +12 -0
- data/lib/active_record/connection_adapters/sqlserver/type/text.rb +19 -0
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +68 -0
- data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +93 -0
- data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +19 -0
- data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +25 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +21 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +12 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +19 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +26 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +24 -0
- data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +36 -0
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +26 -0
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +24 -0
- data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +26 -0
- data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +24 -0
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +146 -0
- data/lib/active_record/connection_adapters/sqlserver/version.rb +11 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +445 -0
- data/lib/active_record/connection_adapters/sqlserver_column.rb +28 -0
- data/lib/active_record/jdbc_sqlserver_connection_methods.rb +31 -0
- data/lib/active_record/sqlserver_base.rb +16 -0
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +131 -0
- data/lib/activerecord-jdbcsqlserver-adapter.rb +24 -0
- data/lib/activerecord-sqlserver-adapter.rb +1 -0
- data/lib/arel/visitors/sqlserver.rb +205 -0
- data/lib/arel_sqlserver.rb +3 -0
- data/test/appveyor/dbsetup.ps1 +27 -0
- data/test/appveyor/dbsetup.sql +11 -0
- data/test/bin/wait-for.sh +79 -0
- data/test/cases/adapter_test_sqlserver.rb +430 -0
- data/test/cases/coerced_tests.rb +845 -0
- data/test/cases/column_test_sqlserver.rb +812 -0
- data/test/cases/connection_test_sqlserver.rb +71 -0
- data/test/cases/execute_procedure_test_sqlserver.rb +45 -0
- data/test/cases/fetch_test_sqlserver.rb +57 -0
- data/test/cases/fully_qualified_identifier_test_sqlserver.rb +76 -0
- data/test/cases/helper_sqlserver.rb +44 -0
- data/test/cases/index_test_sqlserver.rb +47 -0
- data/test/cases/json_test_sqlserver.rb +32 -0
- data/test/cases/migration_test_sqlserver.rb +61 -0
- data/test/cases/order_test_sqlserver.rb +147 -0
- data/test/cases/pessimistic_locking_test_sqlserver.rb +94 -0
- data/test/cases/rake_test_sqlserver.rb +169 -0
- data/test/cases/schema_dumper_test_sqlserver.rb +234 -0
- data/test/cases/schema_test_sqlserver.rb +54 -0
- data/test/cases/scratchpad_test_sqlserver.rb +8 -0
- data/test/cases/showplan_test_sqlserver.rb +65 -0
- data/test/cases/specific_schema_test_sqlserver.rb +180 -0
- data/test/cases/transaction_test_sqlserver.rb +91 -0
- data/test/cases/utils_test_sqlserver.rb +129 -0
- data/test/cases/uuid_test_sqlserver.rb +49 -0
- data/test/config.yml +38 -0
- data/test/debug.rb +14 -0
- data/test/fixtures/1px.gif +0 -0
- data/test/migrations/transaction_table/1_table_will_never_be_created.rb +11 -0
- data/test/models/sqlserver/booking.rb +3 -0
- data/test/models/sqlserver/customers_view.rb +3 -0
- data/test/models/sqlserver/datatype.rb +3 -0
- data/test/models/sqlserver/datatype_migration.rb +8 -0
- data/test/models/sqlserver/dollar_table_name.rb +3 -0
- data/test/models/sqlserver/dot_table_name.rb +3 -0
- data/test/models/sqlserver/edge_schema.rb +13 -0
- data/test/models/sqlserver/fk_has_fk.rb +3 -0
- data/test/models/sqlserver/fk_has_pk.rb +3 -0
- data/test/models/sqlserver/natural_pk_data.rb +4 -0
- data/test/models/sqlserver/natural_pk_int_data.rb +3 -0
- data/test/models/sqlserver/no_pk_data.rb +3 -0
- data/test/models/sqlserver/object_default.rb +3 -0
- data/test/models/sqlserver/quoted_table.rb +7 -0
- data/test/models/sqlserver/quoted_view_1.rb +3 -0
- data/test/models/sqlserver/quoted_view_2.rb +3 -0
- data/test/models/sqlserver/sst_memory.rb +3 -0
- data/test/models/sqlserver/string_default.rb +3 -0
- data/test/models/sqlserver/string_defaults_big_view.rb +3 -0
- data/test/models/sqlserver/string_defaults_view.rb +3 -0
- data/test/models/sqlserver/tinyint_pk.rb +3 -0
- data/test/models/sqlserver/upper.rb +3 -0
- data/test/models/sqlserver/uppered.rb +3 -0
- data/test/models/sqlserver/uuid.rb +3 -0
- data/test/schema/datatypes/2012.sql +55 -0
- data/test/schema/enable-in-memory-oltp.sql +81 -0
- data/test/schema/sqlserver_specific_schema.rb +238 -0
- data/test/support/coerceable_test_sqlserver.rb +49 -0
- data/test/support/connection_reflection.rb +34 -0
- data/test/support/load_schema_sqlserver.rb +29 -0
- data/test/support/minitest_sqlserver.rb +1 -0
- data/test/support/paths_sqlserver.rb +50 -0
- data/test/support/rake_helpers.rb +41 -0
- data/test/support/sql_counter_sqlserver.rb +28 -0
- data/test/support/test_in_memory_oltp.rb +15 -0
- 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
|