Skip to content

Commit 9931ab6

Browse files
Apply parameterization to sql query after it has been logged by ActiveRecord
Prevents sensitive values from by-passing ActiveRecord filtered attributes.
1 parent 3e3cf0a commit 9931ab6

File tree

6 files changed

+77
-69
lines changed

6 files changed

+77
-69
lines changed

lib/active_record/connection_adapters/sqlserver/database_statements.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ def write_query?(sql) # :nodoc:
1414
end
1515

1616
def perform_query(raw_connection, sql, binds, type_casted_binds, prepare:, notification_payload:, batch:)
17+
unless binds.nil? || binds.empty?
18+
types, params = sp_executesql_types_and_parameters(binds)
19+
sql = sp_executesql_sql(sql, types, params, notification_payload[:name])
20+
end
21+
1722
result = if id_insert_table_name = query_requires_identity_insert?(sql)
1823
with_identity_insert_enabled(id_insert_table_name, raw_connection) do
1924
internal_exec_sql_query(sql, raw_connection)
@@ -41,11 +46,6 @@ def affected_rows(raw_result)
4146
end
4247

4348
def raw_execute(sql, name = nil, binds = [], prepare: false, async: false, allow_retry: false, materialize_transactions: true, batch: false)
44-
unless binds.nil? || binds.empty?
45-
types, params = sp_executesql_types_and_parameters(binds)
46-
sql = sp_executesql_sql(sql, types, params, name)
47-
end
48-
4949
super
5050
end
5151

test/cases/coerced_tests.rb

Lines changed: 40 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def test_belongs_to_with_primary_key_joins_on_correct_column_coerced
248248
def test_belongs_to_coerced
249249
client = Client.find(3)
250250
first_firm = companies(:first_firm)
251-
assert_queries_match(/FETCH NEXT @(\d) ROWS ONLY(.)*@\1 = 1/) do
251+
assert_queries_and_values_match(/FETCH NEXT @3 ROWS ONLY/, ['Firm', 'Agency', 1, 1]) do
252252
assert_equal first_firm, client.firm
253253
assert_equal first_firm.name, client.firm.name
254254
end
@@ -257,21 +257,6 @@ def test_belongs_to_coerced
257257

258258
module ActiveRecord
259259
class BindParameterTest < ActiveRecord::TestCase
260-
# Same as original coerced test except log is found using `EXEC sp_executesql` wrapper.
261-
coerce_tests! :test_binds_are_logged
262-
def test_binds_are_logged_coerced
263-
sub = Arel::Nodes::BindParam.new(1)
264-
binds = [Relation::QueryAttribute.new("id", 1, Type::Value.new)]
265-
sql = "select * from topics where id = #{sub.to_sql}"
266-
267-
@connection.exec_query(sql, "SQL", binds)
268-
269-
logged_sql = "EXEC sp_executesql N'#{sql}', N'#{sub.to_sql} int', #{sub.to_sql} = 1"
270-
message = @subscriber.calls.find { |args| args[4][:sql] == logged_sql }
271-
272-
assert_equal binds, message[4][:binds]
273-
end
274-
275260
# SQL Server adapter does not use a statement cache as query plans are already reused using `EXEC sp_executesql`.
276261
coerce_tests! :test_statement_cache
277262
coerce_tests! :test_statement_cache_with_query_cache
@@ -307,7 +292,7 @@ def assert_bind_params_to_sql_coerced(prepared:)
307292
# SELECT [authors].* FROM [authors] WHERE ([authors].[id] IN (1, 2, 3) OR [authors].[id] IS NULL)
308293
#
309294
sql_unprepared = "SELECT #{table}.* FROM #{table} WHERE (#{pk} IN (#{bind_params(1..3)}) OR #{pk} IS NULL)"
310-
sql_prepared = "EXEC sp_executesql N'SELECT #{table}.* FROM #{table} WHERE (#{pk} IN (#{bind_params(1..3)}) OR #{pk} IS NULL)', N'@0 bigint, @1 bigint, @2 bigint', @0 = 1, @1 = 2, @2 = 3"
295+
sql_prepared = "SELECT #{table}.* FROM #{table} WHERE (#{pk} IN (#{bind_params(1..3)}) OR #{pk} IS NULL)"
311296

312297
authors = Author.where(id: [1, 2, 3, nil])
313298
assert_equal sql_unprepared, @connection.to_sql(authors.arel)
@@ -322,7 +307,7 @@ def assert_bind_params_to_sql_coerced(prepared:)
322307
# SELECT [authors].* FROM [authors] WHERE [authors].[id] IN (1, 2, 3)
323308
#
324309
sql_unprepared = "SELECT #{table}.* FROM #{table} WHERE #{pk} IN (#{bind_params(1..3)})"
325-
sql_prepared = "EXEC sp_executesql N'SELECT #{table}.* FROM #{table} WHERE #{pk} IN (#{bind_params(1..3)})', N'@0 bigint, @1 bigint, @2 bigint', @0 = 1, @1 = 2, @2 = 3"
310+
sql_prepared = "SELECT #{table}.* FROM #{table} WHERE #{pk} IN (#{bind_params(1..3)})"
326311

327312
authors = Author.where(id: [1, 2, 3, 9223372036854775808])
328313
assert_equal sql_unprepared, @connection.to_sql(authors.arel)
@@ -391,7 +376,7 @@ def test_should_count_with_group_by_qualified_name_on_loaded_coerced
391376
assert_predicate accounts, :loaded?
392377
assert_equal expected, accounts.count(:id)
393378
end
394-
379+
395380
# Fix randomly failing test. The loading of the model's schema was affecting the test.
396381
coerce_tests! :test_offset_is_kept
397382
def test_offset_is_kept_coerced
@@ -512,15 +497,15 @@ def test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_ar_coerced
512497
def test_limit_is_kept_coerced
513498
queries = capture_sql { Account.limit(1).count }
514499
assert_equal 1, queries.length
515-
assert_match(/ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/, queries.first)
500+
assert_match(/ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY/, queries.first)
516501
end
517502

518503
# Match SQL Server limit implementation
519504
coerce_tests! :test_limit_with_offset_is_kept
520505
def test_limit_with_offset_is_kept_coerced
521506
queries = capture_sql { Account.limit(1).offset(1).count }
522507
assert_equal 1, queries.length
523-
assert_match(/ORDER BY \[accounts\]\.\[id\] ASC OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY.*@0 = 1, @1 = 1/, queries.first)
508+
assert_match(/ORDER BY \[accounts\]\.\[id\] ASC OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY/, queries.first)
524509
end
525510

526511
# SQL Server needs an alias for the calculated column
@@ -987,9 +972,9 @@ class FinderTest < ActiveRecord::TestCase
987972
# Assert SQL Server limit implementation
988973
coerce_tests! :test_take_and_first_and_last_with_integer_should_use_sql_limit
989974
def test_take_and_first_and_last_with_integer_should_use_sql_limit_coerced
990-
assert_queries_match(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 3/) { Topic.take(3).entries }
991-
assert_queries_match(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 2/) { Topic.first(2).entries }
992-
assert_queries_match(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 5/) { Topic.last(5).entries }
975+
assert_queries_and_values_match(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY/, [3]) { Topic.take(3).entries }
976+
assert_queries_and_values_match(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY/, [2]) { Topic.first(2).entries }
977+
assert_queries_and_values_match(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY/, [5]) { Topic.last(5).entries }
993978
end
994979

995980
# This fails only when run in the full test suite task. Just taking it out of the mix.
@@ -1020,31 +1005,31 @@ def test_condition_local_time_interpolation_with_default_timezone_utc_coerced
10201005
# Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
10211006
coerce_tests! :test_include_on_unloaded_relation_with_match
10221007
def test_include_on_unloaded_relation_with_match_coerced
1023-
assert_queries_match(/1 AS one.*FETCH NEXT @2 ROWS ONLY.*@2 = 1/) do
1008+
assert_queries_match(/1 AS one.*FETCH NEXT @2 ROWS ONLY/) do
10241009
assert_equal true, Customer.where(name: "David").include?(customers(:david))
10251010
end
10261011
end
10271012

10281013
# Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
10291014
coerce_tests! :test_include_on_unloaded_relation_without_match
10301015
def test_include_on_unloaded_relation_without_match_coerced
1031-
assert_queries_match(/1 AS one.*FETCH NEXT @2 ROWS ONLY.*@2 = 1/) do
1016+
assert_queries_match(/1 AS one.*FETCH NEXT @2 ROWS ONLY/) do
10321017
assert_equal false, Customer.where(name: "David").include?(customers(:mary))
10331018
end
10341019
end
10351020

10361021
# Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
10371022
coerce_tests! :test_member_on_unloaded_relation_with_match
10381023
def test_member_on_unloaded_relation_with_match_coerced
1039-
assert_queries_match(/1 AS one.*FETCH NEXT @2 ROWS ONLY.*@2 = 1/) do
1024+
assert_queries_match(/1 AS one.*FETCH NEXT @2 ROWS ONLY/) do
10401025
assert_equal true, Customer.where(name: "David").member?(customers(:david))
10411026
end
10421027
end
10431028

10441029
# Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
10451030
coerce_tests! :test_member_on_unloaded_relation_without_match
10461031
def test_member_on_unloaded_relation_without_match_coerced
1047-
assert_queries_match(/1 AS one.*FETCH NEXT @2 ROWS ONLY.*@2 = 1/) do
1032+
assert_queries_match(/1 AS one.*FETCH NEXT @2 ROWS ONLY/) do
10481033
assert_equal false, Customer.where(name: "David").member?(customers(:mary))
10491034
end
10501035
end
@@ -1059,7 +1044,7 @@ def test_implicit_order_column_is_configurable_coerced
10591044
assert_equal topics(:third), Topic.last
10601045

10611046
c = Topic.lease_connection
1062-
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.title"))} DESC, #{Regexp.escape(c.quote_table_name("topics.id"))} DESC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) {
1047+
assert_queries_and_values_match(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.title"))} DESC, #{Regexp.escape(c.quote_table_name("topics.id"))} DESC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY/i, [1]) {
10631048
Topic.last
10641049
}
10651050
ensure
@@ -1073,7 +1058,7 @@ def test_implicit_order_set_to_primary_key_coerced
10731058
Topic.implicit_order_column = "id"
10741059

10751060
c = Topic.lease_connection
1076-
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.id"))} DESC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) {
1061+
assert_queries_and_values_match(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.id"))} DESC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY/i, [1]) {
10771062
Topic.last
10781063
}
10791064
ensure
@@ -1088,7 +1073,7 @@ def test_implicit_order_for_model_without_primary_key_coerced
10881073

10891074
c = NonPrimaryKey.lease_connection
10901075

1091-
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("non_primary_keys.created_at"))} DESC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) {
1076+
assert_queries_and_values_match(/ORDER BY #{Regexp.escape(c.quote_table_name("non_primary_keys.created_at"))} DESC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY/i, [1]) {
10921077
NonPrimaryKey.last
10931078
}
10941079
ensure
@@ -1098,7 +1083,7 @@ def test_implicit_order_for_model_without_primary_key_coerced
10981083
# Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
10991084
coerce_tests! :test_member_on_unloaded_relation_with_composite_primary_key
11001085
def test_member_on_unloaded_relation_with_composite_primary_key_coerced
1101-
assert_queries_match(/1 AS one.* FETCH NEXT @(\d) ROWS ONLY.*@\1 = 1/) do
1086+
assert_queries_match(/1 AS one.* FETCH NEXT @3 ROWS ONLY/) do
11021087
book = cpk_books(:cpk_great_author_first_book)
11031088
assert Cpk::Book.where(title: "The first book").member?(book)
11041089
end
@@ -1113,7 +1098,7 @@ def test_implicit_order_column_prepends_query_constraints_coerced
11131098
quoted_color = Regexp.escape(c.quote_table_name("clothing_items.color"))
11141099
quoted_descrption = Regexp.escape(c.quote_table_name("clothing_items.description"))
11151100

1116-
assert_queries_match(/ORDER BY #{quoted_descrption} ASC, #{quoted_type} ASC, #{quoted_color} ASC OFFSET 0 ROWS FETCH NEXT @(\d) ROWS ONLY.*@\1 = 1/i) do
1101+
assert_queries_match(/ORDER BY #{quoted_descrption} ASC, #{quoted_type} ASC, #{quoted_color} ASC OFFSET 0 ROWS FETCH NEXT @(\d) ROWS ONLY/i) do
11171102
assert_kind_of ClothingItem, ClothingItem.first
11181103
end
11191104
ensure
@@ -1127,7 +1112,7 @@ def test_implicit_order_column_prepends_query_constraints_coerced
11271112
quoted_type = Regexp.escape(c.quote_table_name("clothing_items.clothing_type"))
11281113
quoted_color = Regexp.escape(c.quote_table_name("clothing_items.color"))
11291114

1130-
assert_queries_match(/ORDER BY #{quoted_type} DESC, #{quoted_color} DESC OFFSET 0 ROWS FETCH NEXT @(\d) ROWS ONLY.*@\1 = 1/i) do
1115+
assert_queries_match(/ORDER BY #{quoted_type} DESC, #{quoted_color} DESC OFFSET 0 ROWS FETCH NEXT @(\d) ROWS ONLY/i) do
11311116
assert_kind_of ClothingItem, ClothingItem.last
11321117
end
11331118
end
@@ -1139,7 +1124,7 @@ def test_implicit_order_column_prepends_query_constraints_coerced
11391124
quoted_type = Regexp.escape(c.quote_table_name("clothing_items.clothing_type"))
11401125
quoted_color = Regexp.escape(c.quote_table_name("clothing_items.color"))
11411126

1142-
assert_queries_match(/ORDER BY #{quoted_type} ASC, #{quoted_color} ASC OFFSET 0 ROWS FETCH NEXT @(\d) ROWS ONLY.*@\1 = 1/i) do
1127+
assert_queries_match(/ORDER BY #{quoted_type} ASC, #{quoted_color} ASC OFFSET 0 ROWS FETCH NEXT @(\d) ROWS ONLY/i) do
11431128
assert_kind_of ClothingItem, ClothingItem.first
11441129
end
11451130
end
@@ -1152,7 +1137,7 @@ def test_implicit_order_column_reorders_query_constraints_coerced
11521137
quoted_type = Regexp.escape(c.quote_table_name("clothing_items.clothing_type"))
11531138
quoted_color = Regexp.escape(c.quote_table_name("clothing_items.color"))
11541139

1155-
assert_queries_match(/ORDER BY #{quoted_color} ASC, #{quoted_type} ASC OFFSET 0 ROWS FETCH NEXT @(\d) ROWS ONLY.*@\1 = 1/i) do
1140+
assert_queries_match(/ORDER BY #{quoted_color} ASC, #{quoted_type} ASC OFFSET 0 ROWS FETCH NEXT @(\d) ROWS ONLY/i) do
11561141
assert_kind_of ClothingItem, ClothingItem.first
11571142
end
11581143
ensure
@@ -1162,7 +1147,7 @@ def test_implicit_order_column_reorders_query_constraints_coerced
11621147
# Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
11631148
coerce_tests! :test_include_on_unloaded_relation_with_composite_primary_key
11641149
def test_include_on_unloaded_relation_with_composite_primary_key_coerced
1165-
assert_queries_match(/1 AS one.*OFFSET 0 ROWS FETCH NEXT @(\d) ROWS ONLY.*@\1 = 1/) do
1150+
assert_queries_match(/1 AS one.*OFFSET 0 ROWS FETCH NEXT @(\d) ROWS ONLY/) do
11661151
book = cpk_books(:cpk_great_author_first_book)
11671152
assert Cpk::Book.where(title: "The first book").include?(book)
11681153
end
@@ -1172,11 +1157,11 @@ def test_include_on_unloaded_relation_with_composite_primary_key_coerced
11721157
coerce_tests! :test_nth_to_last_with_order_uses_limit
11731158
def test_nth_to_last_with_order_uses_limit_coerced
11741159
c = Topic.lease_connection
1175-
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.id"))} DESC OFFSET @(\d) ROWS FETCH NEXT @(\d) ROWS ONLY.*@\1 = 1.*@\2 = 1/i) do
1160+
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.id"))} DESC OFFSET @(\d) ROWS FETCH NEXT @(\d) ROWS ONLY/i) do
11761161
Topic.second_to_last
11771162
end
11781163

1179-
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.updated_at"))} DESC OFFSET @(\d) ROWS FETCH NEXT @(\d) ROWS ONLY.*@\1 = 1.*@\2 = 1/i) do
1164+
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.updated_at"))} DESC OFFSET @(\d) ROWS FETCH NEXT @(\d) ROWS ONLY/i) do
11801165
Topic.order(:updated_at).second_to_last
11811166
end
11821167
end
@@ -1227,7 +1212,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
12271212
def test_has_one_coerced
12281213
firm = companies(:first_firm)
12291214
first_account = Account.find(1)
1230-
assert_queries_match(/FETCH NEXT @(\d) ROWS ONLY(.)*@\1 = 1/) do
1215+
assert_queries_match(/FETCH NEXT @(\d) ROWS ONLY/) do
12311216
assert_equal first_account, firm.account
12321217
assert_equal first_account.credit_limit, firm.account.credit_limit
12331218
end
@@ -1239,7 +1224,7 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
12391224
coerce_tests! :test_has_one_through_executes_limited_query
12401225
def test_has_one_through_executes_limited_query_coerced
12411226
boring_club = clubs(:boring_club)
1242-
assert_queries_match(/FETCH NEXT @(\d) ROWS ONLY(.)*@\1 = 1/) do
1227+
assert_queries_match(/FETCH NEXT @(\d) ROWS ONLY/) do
12431228
assert_equal boring_club, @member.general_club
12441229
end
12451230
end
@@ -1460,7 +1445,7 @@ def test_having_with_binds_for_both_where_and_having
14601445
# Find any limit via our expression.
14611446
coerce_tests! %r{relations don't load all records in #inspect}
14621447
def test_relations_dont_load_all_records_in_inspect_coerced
1463-
assert_queries_match(/NEXT @0 ROWS.*@0 = \d+/) do
1448+
assert_queries_match(/NEXT @0 ROWS/) do
14641449
Post.all.inspect
14651450
end
14661451
end
@@ -1568,10 +1553,10 @@ def test_dump_schema_information_outputs_lexically_reverse_ordered_versions_rega
15681553

15691554
schema_info = ActiveRecord::Base.lease_connection.dump_schema_information
15701555
expected = <<~STR
1571-
INSERT INTO #{ActiveRecord::Base.lease_connection.quote_table_name("schema_migrations")} (version) VALUES
1572-
(N'20100301010101'),
1573-
(N'20100201010101'),
1574-
(N'20100101010101');
1556+
INSERT INTO #{ActiveRecord::Base.lease_connection.quote_table_name("schema_migrations")} (version) VALUES
1557+
(N'20100301010101'),
1558+
(N'20100201010101'),
1559+
(N'20100101010101');
15751560
STR
15761561
assert_equal expected.strip, schema_info
15771562
ensure
@@ -2148,7 +2133,7 @@ def test_merge_doesnt_duplicate_same_clauses_coerced
21482133
non_mary_and_bob = Author.where.not(id: [mary, bob])
21492134

21502135
author_id = Author.lease_connection.quote_table_name("authors.id")
2151-
assert_queries_match(/WHERE #{Regexp.escape(author_id)} NOT IN \((@\d), \g<1>\)'/) do
2136+
assert_queries_match(/WHERE #{Regexp.escape(author_id)} NOT IN \((@\d), \g<1>\)/) do
21522137
assert_equal [david], non_mary_and_bob.merge(non_mary_and_bob)
21532138
end
21542139

@@ -2313,7 +2298,7 @@ def test_preloads_has_many_on_model_with_a_composite_primary_key_through_id_attr
23132298

23142299
c = Cpk::OrderAgreement.lease_connection
23152300
order_id_column = Regexp.escape(c.quote_table_name("cpk_order_agreements.order_id"))
2316-
order_id_constraint = /#{order_id_column} = @0.*@0 = \d+$/
2301+
order_id_constraint = /#{order_id_column} = @0$/
23172302
expectation = /SELECT.*WHERE.* #{order_id_constraint}/
23182303

23192304
assert_match(expectation, preload_sql)
@@ -2337,7 +2322,7 @@ def test_preloads_belongs_to_a_composite_primary_key_model_through_id_attribute_
23372322

23382323
c = Cpk::Order.lease_connection
23392324
order_id = Regexp.escape(c.quote_table_name("cpk_orders.id"))
2340-
order_constraint = /#{order_id} = @0.*@0 = \d+$/
2325+
order_constraint = /#{order_id} = @0$/
23412326
expectation = /SELECT.*WHERE.* #{order_constraint}/
23422327

23432328
assert_match(expectation, preload_sql)
@@ -2410,7 +2395,7 @@ def test_sql_commenter_format_coerced
24102395
ActiveRecord::QueryLogs.tags_formatter = :sqlcommenter
24112396
ActiveRecord::QueryLogs.tags = [:application]
24122397

2413-
assert_queries_match(%r{/\*application=''active_record''\*/}) do
2398+
assert_queries_match(%r{/\*application='active_record'\*/}) do
24142399
Dashboard.first
24152400
end
24162401
end
@@ -2425,7 +2410,7 @@ def test_sqlcommenter_format_value_coerced
24252410
{ tracestate: "congo=t61rcWkgMzE,rojo=00f067aa0ba902b7", custom_proc: -> { "Joe's Shack" } },
24262411
]
24272412

2428-
assert_queries_match(%r{custom_proc=''Joe%27s%20Shack'',tracestate=''congo%3Dt61rcWkgMzE%2Crojo%3D00f067aa0ba902b7''\*/}) do
2413+
assert_queries_match(%r{custom_proc='Joe%27s%20Shack',tracestate='congo%3Dt61rcWkgMzE%2Crojo%3D00f067aa0ba902b7'\*/}) do
24292414
Dashboard.first
24302415
end
24312416
end
@@ -2440,7 +2425,7 @@ def test_sqlcommenter_format_value_string_coercible_coerced
24402425
{ custom_proc: -> { 1234 } },
24412426
]
24422427

2443-
assert_queries_match(%r{custom_proc=''1234''\*/}) do
2428+
assert_queries_match(%r{custom_proc='1234'\*/}) do
24442429
Dashboard.first
24452430
end
24462431
end
@@ -2459,7 +2444,7 @@ def test_sqlcommenter_format_allows_string_keys_coerced
24592444
},
24602445
]
24612446

2462-
assert_queries_match(%r{custom_proc=''Joe%27s%20Shack'',string=''value'',tracestate=''congo%3Dt61rcWkgMzE%2Crojo%3D00f067aa0ba902b7''\*/}) do
2447+
assert_queries_match(%r{custom_proc='Joe%27s%20Shack',string='value',tracestate='congo%3Dt61rcWkgMzE%2Crojo%3D00f067aa0ba902b7'\*/}) do
24632448
Dashboard.first
24642449
end
24652450
end
@@ -2719,7 +2704,7 @@ class ExplainTest < ActiveRecord::TestCase
27192704
def test_relation_explain_with_first_coerced
27202705
expected_query = capture_sql {
27212706
Car.all.first
2722-
}.first[/EXEC sp_executesql N'(.*?) NEXT/, 1]
2707+
}.first[/(.*?) NEXT/, 1]
27232708
message = Car.all.explain.first
27242709
assert_match(/^EXPLAIN/, message)
27252710
assert_match(expected_query, message)
@@ -2730,7 +2715,7 @@ def test_relation_explain_with_first_coerced
27302715
def test_relation_explain_with_last_coerced
27312716
expected_query = capture_sql {
27322717
Car.all.last
2733-
}.first[/EXEC sp_executesql N'(.*?) NEXT/, 1]
2718+
}.first[/(.*?) NEXT/, 1]
27342719
expected_query = expected_query
27352720
message = Car.all.explain.last
27362721

test/cases/optimizer_hints_test_sqlserver.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class OptimizerHitsTestSQLServer < ActiveRecord::TestCase
2929
end
3030

3131
it "support subqueries" do
32-
assert_queries_match(%r{.*'SELECT COUNT\(count_column\) FROM \(SELECT .*\) subquery_for_count OPTION \(MAXDOP 2\)'.*}) do
32+
assert_queries_match(%r{SELECT COUNT\(count_column\) FROM \(SELECT .*\) subquery_for_count OPTION \(MAXDOP 2\)}) do
3333
companies = Company.optimizer_hints("MAXDOP 2")
3434
companies = companies.select(:id).where(firm_id: [0, 1]).limit(3)
3535
assert_equal 3, companies.count

0 commit comments

Comments
 (0)