activerecord-sqlserver-adapter_new 4.2.15
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/CHANGELOG.md +212 -0
- data/CODE_OF_CONDUCT.md +31 -0
- data/Gemfile +61 -0
- data/Guardfile +29 -0
- data/MIT-LICENSE +20 -0
- data/README.md +201 -0
- data/RUNNING_UNIT_TESTS.md +121 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/activerecord-sqlserver-adapter_new.gemspec +20 -0
- data/appveyor.yml +39 -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/explain.rb +40 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +4 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/odbc.rb +34 -0
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +49 -0
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +386 -0
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +68 -0
- data/lib/active_record/connection_adapters/sqlserver/errors.rb +7 -0
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +69 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_cache.rb +114 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +52 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +473 -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/table_definition.rb +76 -0
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +57 -0
- data/lib/active_record/connection_adapters/sqlserver/type.rb +46 -0
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +15 -0
- data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +15 -0
- data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +12 -0
- data/lib/active_record/connection_adapters/sqlserver/type/char.rb +38 -0
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +21 -0
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +41 -0
- data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +17 -0
- data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +31 -0
- data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +12 -0
- data/lib/active_record/connection_adapters/sqlserver/type/float.rb +15 -0
- data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +12 -0
- data/lib/active_record/connection_adapters/sqlserver/type/money.rb +21 -0
- data/lib/active_record/connection_adapters/sqlserver/type/real.rb +15 -0
- data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +13 -0
- data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +21 -0
- data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +22 -0
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +12 -0
- data/lib/active_record/connection_adapters/sqlserver/type/text.rb +15 -0
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +40 -0
- data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +76 -0
- data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +22 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +15 -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 +15 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +20 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +20 -0
- data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +23 -0
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +20 -0
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +20 -0
- data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +20 -0
- data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +20 -0
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +136 -0
- data/lib/active_record/connection_adapters/sqlserver/version.rb +11 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +405 -0
- data/lib/active_record/connection_adapters/sqlserver_column.rb +53 -0
- data/lib/active_record/sqlserver_base.rb +20 -0
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +131 -0
- data/lib/activerecord-sqlserver-adapter.rb +1 -0
- data/lib/arel/visitors/sqlserver.rb +214 -0
- data/lib/arel_sqlserver.rb +3 -0
- data/test/appveyor/dbsetup.ps1 +27 -0
- data/test/appveyor/dbsetup.sql +11 -0
- data/test/cases/adapter_test_sqlserver.rb +444 -0
- data/test/cases/coerced_tests.rb +713 -0
- data/test/cases/column_test_sqlserver.rb +780 -0
- data/test/cases/connection_test_sqlserver.rb +142 -0
- data/test/cases/execute_procedure_test_sqlserver.rb +44 -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 +54 -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 +90 -0
- data/test/cases/rake_test_sqlserver.rb +163 -0
- data/test/cases/schema_dumper_test_sqlserver.rb +198 -0
- data/test/cases/schema_test_sqlserver.rb +54 -0
- data/test/cases/scratchpad_test_sqlserver.rb +9 -0
- data/test/cases/showplan_test_sqlserver.rb +65 -0
- data/test/cases/specific_schema_test_sqlserver.rb +167 -0
- data/test/cases/transaction_test_sqlserver.rb +66 -0
- data/test/cases/utils_test_sqlserver.rb +129 -0
- data/test/cases/uuid_test_sqlserver.rb +48 -0
- data/test/config.yml +41 -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 +3 -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/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/sqlserver_specific_schema.rb +207 -0
- data/test/support/coerceable_test_sqlserver.rb +45 -0
- data/test/support/connection_reflection.rb +37 -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 +32 -0
- metadata +253 -0
|
@@ -0,0 +1,713 @@
|
|
|
1
|
+
require 'cases/helper_sqlserver'
|
|
2
|
+
|
|
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
|
|
14
|
+
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.
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
module ActiveRecord
|
|
23
|
+
class AdapterTest < ActiveRecord::TestCase
|
|
24
|
+
|
|
25
|
+
# As far as I can tell, SQL Server does not support null bytes in strings.
|
|
26
|
+
coerce_tests! :test_update_prepared_statement
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
require 'models/topic'
|
|
35
|
+
class AttributeMethodsTest < ActiveRecord::TestCase
|
|
36
|
+
|
|
37
|
+
coerce_tests! :test_typecast_attribute_from_select_to_false
|
|
38
|
+
def test_typecast_attribute_from_select_to_false_coerced
|
|
39
|
+
Topic.create(:title => 'Budget')
|
|
40
|
+
topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 2, 1, 0) as is_test").first
|
|
41
|
+
assert !topic.is_test?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
coerce_tests! :test_typecast_attribute_from_select_to_true
|
|
45
|
+
def test_typecast_attribute_from_select_to_true_coerced
|
|
46
|
+
Topic.create(:title => 'Budget')
|
|
47
|
+
topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 1, 1, 0) as is_test").first
|
|
48
|
+
assert topic.is_test?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class BasicsTest < ActiveRecord::TestCase
|
|
57
|
+
|
|
58
|
+
coerce_tests! :test_column_names_are_escaped
|
|
59
|
+
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
|
|
65
|
+
end
|
|
66
|
+
|
|
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.
|
|
70
|
+
coerce_tests! :test_numeric_fields
|
|
71
|
+
coerce_tests! :test_numeric_fields_with_scale
|
|
72
|
+
|
|
73
|
+
# Just like PostgreSQLAdapter does.
|
|
74
|
+
coerce_tests! :test_respect_internal_encoding
|
|
75
|
+
|
|
76
|
+
# Caused in Rails v4.2.5 by adding `firm_id` column in this http://git.io/vBfMs
|
|
77
|
+
# commit. Trust Rails has this covered.
|
|
78
|
+
coerce_tests! :test_find_keeps_multiple_group_values
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class BelongsToAssociationsTest < ActiveRecord::TestCase
|
|
86
|
+
|
|
87
|
+
# Since @client.firm is a single first/top, and we use FETCH the order clause is used.
|
|
88
|
+
coerce_tests! :test_belongs_to_does_not_use_order_by
|
|
89
|
+
|
|
90
|
+
coerce_tests! :test_belongs_to_with_primary_key_joins_on_correct_column
|
|
91
|
+
def test_belongs_to_with_primary_key_joins_on_correct_column_coerced
|
|
92
|
+
sql = Client.joins(:firm_with_primary_key).to_sql
|
|
93
|
+
assert_no_match(/\[firm_with_primary_keys_companies\]\.\[id\]/, sql)
|
|
94
|
+
assert_match(/\[firm_with_primary_keys_companies\]\.\[name\]/, sql)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
module ActiveRecord
|
|
103
|
+
class BindParameterTest < ActiveRecord::TestCase
|
|
104
|
+
|
|
105
|
+
# 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
|
+
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class CalculationsTest < ActiveRecord::TestCase
|
|
116
|
+
|
|
117
|
+
# Are decimal, not integer.
|
|
118
|
+
coerce_tests! :test_should_return_decimal_average_of_integer_field
|
|
119
|
+
def test_should_return_decimal_average_of_integer_field_coerced
|
|
120
|
+
value = Account.average(:id)
|
|
121
|
+
assert_equal BigDecimal('3.0').to_s, BigDecimal(value).to_s
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
coerce_tests! :test_limit_is_kept
|
|
125
|
+
def test_limit_is_kept_coerced
|
|
126
|
+
queries = assert_sql { Account.limit(1).count }
|
|
127
|
+
assert_equal 1, queries.length
|
|
128
|
+
queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY}
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
coerce_tests! :test_limit_with_offset_is_kept
|
|
132
|
+
def test_limit_with_offset_is_kept_coerced
|
|
133
|
+
queries = assert_sql { Account.limit(1).offset(1).count }
|
|
134
|
+
assert_equal 1, queries.length
|
|
135
|
+
queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY}
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
module ActiveRecord
|
|
144
|
+
class Migration
|
|
145
|
+
class ChangeSchemaTest < ActiveRecord::TestCase
|
|
146
|
+
|
|
147
|
+
# We test these.
|
|
148
|
+
coerce_tests! :test_create_table_with_bigint,
|
|
149
|
+
:test_create_table_with_defaults
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
end
|
|
153
|
+
class ChangeSchemaWithDependentObjectsTest < ActiveRecord::TestCase
|
|
154
|
+
|
|
155
|
+
# In SQL Server you have to delete the tables yourself in the right order.
|
|
156
|
+
coerce_tests! :test_create_table_with_force_cascade_drops_dependent_objects
|
|
157
|
+
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
module ActiveRecord
|
|
166
|
+
class Migration
|
|
167
|
+
class ColumnAttributesTest < ActiveRecord::TestCase
|
|
168
|
+
|
|
169
|
+
# We have a default 4000 varying character limit.
|
|
170
|
+
coerce_tests! :test_add_column_without_limit
|
|
171
|
+
def test_add_column_without_limit_coerced
|
|
172
|
+
add_column :test_models, :description, :string, limit: nil
|
|
173
|
+
TestModel.reset_column_information
|
|
174
|
+
TestModel.columns_hash["description"].limit.must_equal 4000
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
module ActiveRecord
|
|
185
|
+
class Migration
|
|
186
|
+
class ColumnsTest
|
|
187
|
+
|
|
188
|
+
# Our defaults are reall 70000 integers vs '70000' strings.
|
|
189
|
+
coerce_tests! :test_rename_column_preserves_default_value_not_null
|
|
190
|
+
def test_rename_column_preserves_default_value_not_null_coerced
|
|
191
|
+
add_column 'test_models', 'salary', :integer, :default => 70000
|
|
192
|
+
default_before = connection.columns("test_models").find { |c| c.name == "salary" }.default
|
|
193
|
+
assert_equal 70000, default_before
|
|
194
|
+
rename_column "test_models", "salary", "annual_salary"
|
|
195
|
+
assert TestModel.column_names.include?("annual_salary")
|
|
196
|
+
default_after = connection.columns("test_models").find { |c| c.name == "annual_salary" }.default
|
|
197
|
+
assert_equal 70000, default_after
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Dropping the column removes the single index.
|
|
201
|
+
coerce_tests! :test_remove_column_with_multi_column_index
|
|
202
|
+
def test_remove_column_with_multi_column_index_coerced
|
|
203
|
+
add_column "test_models", :hat_size, :integer
|
|
204
|
+
add_column "test_models", :hat_style, :string, :limit => 100
|
|
205
|
+
add_index "test_models", ["hat_style", "hat_size"], :unique => true
|
|
206
|
+
assert_equal 1, connection.indexes('test_models').size
|
|
207
|
+
remove_column("test_models", "hat_size")
|
|
208
|
+
assert_equal [], connection.indexes('test_models').map(&:name)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class CoreTest < ActiveRecord::TestCase
|
|
219
|
+
|
|
220
|
+
# I think fixtures are useing the wrong time zone and the `:first`
|
|
221
|
+
# `topics`.`bonus_time` attribute of 2005-01-30t15:28:00.00+01:00 is
|
|
222
|
+
# getting local EST time for me and set to "09:28:00.0000000".
|
|
223
|
+
coerce_tests! :test_pretty_print_persisted
|
|
224
|
+
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
module ActiveRecord
|
|
231
|
+
module ConnectionAdapters
|
|
232
|
+
|
|
233
|
+
# Just like PostgreSQLAdapter does.
|
|
234
|
+
TypeLookupTest.coerce_all_tests! if defined?(TypeLookupTest)
|
|
235
|
+
|
|
236
|
+
# All sorts of errors due to how we test. Even setting ENV['RAILS_ENV'] to
|
|
237
|
+
# a value of 'default_env' will still show tests failing. Just ignoring all
|
|
238
|
+
# of them since we have no monkey in this circus.
|
|
239
|
+
MergeAndResolveDefaultUrlConfigTest.coerce_all_tests! if defined?(MergeAndResolveDefaultUrlConfigTest)
|
|
240
|
+
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
module ActiveRecord
|
|
248
|
+
class DatabaseTasksCreateAllTest < ActiveRecord::TestCase
|
|
249
|
+
# We extend `local_database?` so that common VM IPs can be used.
|
|
250
|
+
coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
|
|
251
|
+
end
|
|
252
|
+
class DatabaseTasksDropAllTest < ActiveRecord::TestCase
|
|
253
|
+
# We extend `local_database?` so that common VM IPs can be used.
|
|
254
|
+
coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class DefaultScopingTest < ActiveRecord::TestCase
|
|
262
|
+
|
|
263
|
+
# We are not doing order duplicate removal anymore.
|
|
264
|
+
coerce_tests! :test_order_in_default_scope_should_not_prevail
|
|
265
|
+
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
require 'models/post'
|
|
272
|
+
require 'models/subscriber'
|
|
273
|
+
class EachTest < ActiveRecord::TestCase
|
|
274
|
+
|
|
275
|
+
coerce_tests! :test_find_in_batches_should_quote_batch_order
|
|
276
|
+
def test_find_in_batches_should_quote_batch_order_coerced
|
|
277
|
+
c = Post.connection
|
|
278
|
+
assert_sql(/ORDER BY \[posts\]\.\[id\]/) do
|
|
279
|
+
Post.find_in_batches(:batch_size => 1) do |batch|
|
|
280
|
+
assert_kind_of Array, batch
|
|
281
|
+
assert_kind_of Post, batch.first
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
|
|
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
|
+
class EagerAssociationTest < ActiveRecord::TestCase
|
|
299
|
+
|
|
300
|
+
# Use LEN() vs length() function.
|
|
301
|
+
coerce_tests! :test_count_with_include
|
|
302
|
+
def test_count_with_include_coerced
|
|
303
|
+
assert_equal 3, authors(:david).posts_with_comments.where("LEN(comments.body) > 15").references(:comments).count
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# Use TOP (1) in scope vs limit 1.
|
|
307
|
+
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
|
+
end
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
require 'models/topic'
|
|
318
|
+
class FinderTest < ActiveRecord::TestCase
|
|
319
|
+
|
|
320
|
+
coerce_tests! %r{doesn't have implicit ordering},
|
|
321
|
+
:test_find_doesnt_have_implicit_ordering # We have implicit ordering, via FETCH.
|
|
322
|
+
|
|
323
|
+
coerce_tests! :test_exists_does_not_select_columns_without_alias
|
|
324
|
+
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
|
|
326
|
+
Topic.exists?
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
coerce_tests! :test_string_sanitation
|
|
331
|
+
def test_string_sanitation_coerced
|
|
332
|
+
assert_not_equal "'something ' 1=1'", ActiveRecord::Base.sanitize("something ' 1=1")
|
|
333
|
+
assert_equal "N'something; select table'", ActiveRecord::Base.sanitize("something; select table")
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
coerce_tests! :test_take_and_first_and_last_with_integer_should_use_sql_limit
|
|
337
|
+
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 }
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
# This fails only when run in the full test suite task. Just taking it out of the mix.
|
|
344
|
+
coerce_tests! :test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct
|
|
345
|
+
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
module ActiveRecord
|
|
352
|
+
class Migration
|
|
353
|
+
class ForeignKeyTest < ActiveRecord::TestCase
|
|
354
|
+
|
|
355
|
+
# We do not support :restrict.
|
|
356
|
+
coerce_tests! :test_add_on_delete_restrict_foreign_key
|
|
357
|
+
def test_add_on_delete_restrict_foreign_key_coerced
|
|
358
|
+
assert_raises ArgumentError do
|
|
359
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_delete: :restrict
|
|
360
|
+
end
|
|
361
|
+
assert_raises ArgumentError do
|
|
362
|
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_update: :restrict
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
class HasOneAssociationsTest < ActiveRecord::TestCase
|
|
374
|
+
|
|
375
|
+
# We use OFFSET/FETCH vs TOP. So we always have an order.
|
|
376
|
+
coerce_tests! :test_has_one_does_not_use_order_by
|
|
377
|
+
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
require 'models/company'
|
|
384
|
+
class InheritanceTest < ActiveRecord::TestCase
|
|
385
|
+
|
|
386
|
+
coerce_tests! :test_a_bad_type_column
|
|
387
|
+
def test_a_bad_type_column_coerced
|
|
388
|
+
Company.connection.with_identity_insert_enabled('companies') do
|
|
389
|
+
Company.connection.insert "INSERT INTO companies (id, #{QUOTED_TYPE}, name) VALUES(100, 'bad_class!', 'Not happening')"
|
|
390
|
+
end
|
|
391
|
+
assert_raise(ActiveRecord::SubclassNotFound) { Company.find(100) }
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
coerce_tests! :test_eager_load_belongs_to_primary_key_quoting
|
|
395
|
+
def test_eager_load_belongs_to_primary_key_quoting_coerced
|
|
396
|
+
con = Account.connection
|
|
397
|
+
assert_sql(/\[companies\]\.\[id\] IN \(1\)/) do
|
|
398
|
+
Account.all.merge!(:includes => :firm).find(1)
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
|
|
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
|
+
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
class NamedScopingTest < ActiveRecord::TestCase
|
|
422
|
+
|
|
423
|
+
# This works now because we add an `order(:id)` sort to break the order tie for deterministic results.
|
|
424
|
+
coerce_tests! :test_scopes_honor_current_scopes_from_when_defined
|
|
425
|
+
def test_scopes_honor_current_scopes_from_when_defined_coerced
|
|
426
|
+
assert !Post.ranked_by_comments.order(:id).limit_by(5).empty?
|
|
427
|
+
assert !authors(:david).posts.ranked_by_comments.order(:id).limit_by(5).empty?
|
|
428
|
+
assert_not_equal Post.ranked_by_comments.order(:id).limit_by(5), authors(:david).posts.ranked_by_comments.order(:id).limit_by(5)
|
|
429
|
+
assert_not_equal Post.order(:id).top(5), authors(:david).posts.order(:id).top(5)
|
|
430
|
+
# Oracle sometimes sorts differently if WHERE condition is changed
|
|
431
|
+
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
|
+
assert_equal Post.ranked_by_comments.limit_by(5), Post.top(5)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
require 'models/developer'
|
|
441
|
+
require 'models/computer'
|
|
442
|
+
class NestedRelationScopingTest < ActiveRecord::TestCase
|
|
443
|
+
|
|
444
|
+
coerce_tests! :test_merge_options
|
|
445
|
+
def test_merge_options_coerced
|
|
446
|
+
Developer.where('salary = 80000').scoping do
|
|
447
|
+
Developer.limit(10).scoping do
|
|
448
|
+
devs = Developer.all
|
|
449
|
+
sql = devs.to_sql
|
|
450
|
+
assert_match '(salary = 80000)', sql
|
|
451
|
+
assert_match 'FETCH NEXT 10 ROWS ONLY', sql
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
require 'models/topic'
|
|
462
|
+
class PersistenceTest < ActiveRecord::TestCase
|
|
463
|
+
|
|
464
|
+
# We can not UPDATE identity columns.
|
|
465
|
+
coerce_tests! :test_update_columns_changing_id
|
|
466
|
+
|
|
467
|
+
# Previous test required updating a identity column.
|
|
468
|
+
coerce_tests! :test_update_all_doesnt_ignore_order
|
|
469
|
+
def test_update_all_doesnt_ignore_order_coerced
|
|
470
|
+
david, mary = authors(:david), authors(:mary)
|
|
471
|
+
david.id.must_equal 1
|
|
472
|
+
mary.id.must_equal 2
|
|
473
|
+
david.name.wont_equal mary.name
|
|
474
|
+
assert_sql(/UPDATE.*\(SELECT \[authors\].\[id\] FROM \[authors\].*ORDER BY \[authors\].\[id\]/i) do
|
|
475
|
+
Author.where('[id] > 1').order(:id).update_all(name: 'Test')
|
|
476
|
+
end
|
|
477
|
+
david.reload.name.must_equal 'David'
|
|
478
|
+
mary.reload.name.must_equal 'Test'
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
# We can not UPDATE identity columns.
|
|
482
|
+
coerce_tests! :test_update_attributes
|
|
483
|
+
def test_update_attributes_coerced
|
|
484
|
+
topic = Topic.find(1)
|
|
485
|
+
assert !topic.approved?
|
|
486
|
+
assert_equal "The First Topic", topic.title
|
|
487
|
+
topic.update_attributes("approved" => true, "title" => "The First Topic Updated")
|
|
488
|
+
topic.reload
|
|
489
|
+
assert topic.approved?
|
|
490
|
+
assert_equal "The First Topic Updated", topic.title
|
|
491
|
+
topic.update_attributes(approved: false, title: "The First Topic")
|
|
492
|
+
topic.reload
|
|
493
|
+
assert !topic.approved?
|
|
494
|
+
assert_equal "The First Topic", topic.title
|
|
495
|
+
# SQLServer: Here is where it breaks down. No exceptions.
|
|
496
|
+
# assert_raise(ActiveRecord::RecordNotUnique, ActiveRecord::StatementInvalid) do
|
|
497
|
+
# topic.update_attributes(id: 3, title: "Hm is it possible?")
|
|
498
|
+
# end
|
|
499
|
+
# assert_not_equal "Hm is it possible?", Topic.find(3).title
|
|
500
|
+
# topic.update_attributes(id: 1234)
|
|
501
|
+
# assert_nothing_raised { topic.reload }
|
|
502
|
+
# assert_equal topic.title, Topic.find(1234).title
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
require 'models/topic'
|
|
511
|
+
module ActiveRecord
|
|
512
|
+
class PredicateBuilderTest < ActiveRecord::TestCase
|
|
513
|
+
|
|
514
|
+
coerce_tests! :test_registering_new_handlers
|
|
515
|
+
def test_registering_new_handlers_coerced
|
|
516
|
+
PredicateBuilder.register_handler(Regexp, proc do |column, value|
|
|
517
|
+
Arel::Nodes::InfixOperation.new('~', column, Arel.sql(value.source))
|
|
518
|
+
end)
|
|
519
|
+
assert_match %r{\[topics\]\.\[title\] ~ rails}i, Topic.where(title: /rails/).to_sql
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
require 'models/task'
|
|
529
|
+
class QueryCacheTest < ActiveRecord::TestCase
|
|
530
|
+
|
|
531
|
+
coerce_tests! :test_cache_does_not_wrap_string_results_in_arrays
|
|
532
|
+
def test_cache_does_not_wrap_string_results_in_arrays_coerced
|
|
533
|
+
Task.cache do
|
|
534
|
+
assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
require 'models/post'
|
|
544
|
+
class RelationTest < ActiveRecord::TestCase
|
|
545
|
+
|
|
546
|
+
# We have implicit ordering, via FETCH.
|
|
547
|
+
coerce_tests! %r{doesn't have implicit ordering}
|
|
548
|
+
|
|
549
|
+
# We are not doing order duplicate removal anymore.
|
|
550
|
+
coerce_tests! :test_order_using_scoping
|
|
551
|
+
|
|
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
|
+
# We are not doing order duplicate removal anymore.
|
|
562
|
+
coerce_tests! :test_default_scope_order_with_scope_order
|
|
563
|
+
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
require 'models/post'
|
|
570
|
+
class SanitizeTest < ActiveRecord::TestCase
|
|
571
|
+
|
|
572
|
+
coerce_tests! :test_sanitize_sql_like_example_use_case
|
|
573
|
+
def test_sanitize_sql_like_example_use_case_coerced
|
|
574
|
+
searchable_post = Class.new(Post) do
|
|
575
|
+
def self.search(term)
|
|
576
|
+
where("title LIKE ?", sanitize_sql_like(term, '!'))
|
|
577
|
+
end
|
|
578
|
+
end
|
|
579
|
+
assert_sql(/\(title LIKE N''20!% !_reduction!_!!''\)/) do
|
|
580
|
+
searchable_post.search("20% _reduction_!").to_a
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
class SchemaDumperTest < ActiveRecord::TestCase
|
|
590
|
+
|
|
591
|
+
# We have precision to 38.
|
|
592
|
+
coerce_tests! :test_schema_dump_keeps_large_precision_integer_columns_as_decimal
|
|
593
|
+
def test_schema_dump_keeps_large_precision_integer_columns_as_decimal_coerced
|
|
594
|
+
output = standard_dump
|
|
595
|
+
assert_match %r{t.decimal\s+"atoms_in_universe",\s+precision: 38}, output
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
# This accidently returns the wrong number because of our tables too.
|
|
599
|
+
coerce_tests! :test_types_line_up
|
|
600
|
+
|
|
601
|
+
# This is a poorly written test and really does not catch the bottom'ness it is meant too. Ours throw it off.
|
|
602
|
+
coerce_tests! :test_foreign_keys_are_dumped_at_the_bottom_to_circumvent_dependency_issues
|
|
603
|
+
|
|
604
|
+
# Fall through false positive with no filter.
|
|
605
|
+
coerce_tests! :test_schema_dumps_partial_indices
|
|
606
|
+
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
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
class SchemaDumperDefaultsTest < ActiveRecord::TestCase
|
|
614
|
+
|
|
615
|
+
# These date formats do not match ours. We got these covered in our dumper tests.
|
|
616
|
+
coerce_tests! :test_schema_dump_defaults_with_universally_supported_types
|
|
617
|
+
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
class TestAdapterWithInvalidConnection < ActiveRecord::TestCase
|
|
624
|
+
|
|
625
|
+
# We trust Rails on this since we do not want to install mysql.
|
|
626
|
+
coerce_tests! %r{inspect on Model class does not raise}
|
|
627
|
+
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
require 'models/topic'
|
|
634
|
+
class TransactionTest < ActiveRecord::TestCase
|
|
635
|
+
|
|
636
|
+
coerce_tests! :test_releasing_named_savepoints
|
|
637
|
+
def test_releasing_named_savepoints_coerced
|
|
638
|
+
Topic.transaction do
|
|
639
|
+
Topic.connection.create_savepoint("another")
|
|
640
|
+
Topic.connection.release_savepoint("another")
|
|
641
|
+
# We do not have a notion of releasing, so this does nothing vs raise an error.
|
|
642
|
+
Topic.connection.release_savepoint("another")
|
|
643
|
+
end
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
require 'models/tag'
|
|
652
|
+
class TransactionIsolationTest < ActiveRecord::TestCase
|
|
653
|
+
|
|
654
|
+
# SQL Server will lock the table for counts even when both
|
|
655
|
+
# connections are `READ COMMITTED`. So we bypass with `READPAST`.
|
|
656
|
+
coerce_tests! %r{read committed}
|
|
657
|
+
test "read committed coerced" do
|
|
658
|
+
Tag.transaction(isolation: :read_committed) do
|
|
659
|
+
assert_equal 0, Tag.count
|
|
660
|
+
Tag2.transaction do
|
|
661
|
+
Tag2.create
|
|
662
|
+
assert_equal 0, Tag.lock('WITH(READPAST)').count
|
|
663
|
+
end
|
|
664
|
+
end
|
|
665
|
+
assert_equal 1, Tag.count
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
# I really need some help understanding this one.
|
|
669
|
+
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
|
+
end
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
class ViewWithPrimaryKeyTest < ActiveRecord::TestCase
|
|
692
|
+
|
|
693
|
+
# We do better than ActiveRecord and find the views PK.
|
|
694
|
+
coerce_tests! :test_does_not_assume_id_column_as_primary_key
|
|
695
|
+
|
|
696
|
+
end
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
require 'models/author'
|
|
702
|
+
class YamlSerializationTest < ActiveRecord::TestCase
|
|
703
|
+
|
|
704
|
+
coerce_tests! :test_types_of_virtual_columns_are_not_changed_on_round_trip
|
|
705
|
+
def test_types_of_virtual_columns_are_not_changed_on_round_trip_coerced
|
|
706
|
+
author = Author.select('authors.*, 5 as posts_count').first
|
|
707
|
+
dumped = YAML.load(YAML.dump(author))
|
|
708
|
+
assert_equal 5, author.posts_count
|
|
709
|
+
assert_equal 5, dumped.posts_count
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
end
|
|
713
|
+
|