Skip to content

Commit 0f13f1f

Browse files
committed
Added tests and don't remove ordering if limit or offset
1 parent 58df95a commit 0f13f1f

File tree

2 files changed

+105
-4
lines changed

2 files changed

+105
-4
lines changed

lib/arel/visitors/sqlserver.rb

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@ def visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, options = {}
138138
end
139139

140140
def visit_Orders_And_Let_Fetch_Happen o, collector
141+
142+
# if $debugger
143+
# puts collector.value
144+
# binding.pry
145+
# end
146+
141147
make_Fetch_Possible_And_Deterministic o
142148
unless o.orders.empty?
143149
collector << " "
@@ -160,7 +166,11 @@ def visit_Make_Fetch_Happen o, collector
160166

161167
def collect_in_clause(left, right, collector)
162168

163-
# binding.pry if $debugger
169+
# if $debugger
170+
# puts collector.value
171+
# binding.pry
172+
# end
173+
164174
#
165175
# if $debugger
166176
# binding.pry
@@ -172,16 +182,33 @@ def collect_in_clause(left, right, collector)
172182

173183
if Array === right
174184
right.each do |node|
185+
remove_invalid_ordering_from_in_clause(node)
175186

176-
if Arel::Nodes::SelectStatement === node
177-
node.orders = []
178-
end
187+
# if Arel::Nodes::SelectStatement === node
188+
# unless node.offset || node.limit
189+
# node.orders = []
190+
# end
191+
# end
179192
end
193+
else
194+
remove_invalid_ordering_from_in_clause(right)
195+
# elsif Arel::Nodes::SelectStatement === right
196+
# right.orders = []
180197
end
181198

182199
super
183200
end
184201

202+
203+
def remove_invalid_ordering_from_in_clause(node)
204+
return unless Arel::Nodes::SelectStatement === node
205+
206+
unless node.offset || node.limit
207+
node.orders = []
208+
end
209+
end
210+
211+
185212
# SQLServer Helpers
186213

187214
def node_value(node)
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
require 'cases/helper_sqlserver'
2+
require 'models/post'
3+
require 'models/author'
4+
5+
class InClauseTestSQLServer < ActiveRecord::TestCase
6+
7+
fixtures :posts, :authors
8+
9+
# The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
10+
11+
it 'removes ordering from subqueries' do
12+
13+
ActiveSupport::Notifications.subscribe('sql.active_record') do |_name, _start, _finish, _id, payload|
14+
puts payload[:sql]
15+
end
16+
17+
# binding.pry
18+
19+
# $debugger = true
20+
21+
# authors_subquery = Author.where(name: ['David', 'Mary']).order(:id)
22+
authors_subquery = Author.where(name: ['David', 'Mary', 'Bob']).order(:name)
23+
posts = Post.where(author: authors_subquery)
24+
25+
assert_includes authors_subquery.to_sql, "ORDER BY [authors].[name]"
26+
assert_not_includes posts.to_sql, "ORDER BY [authors].[name]"
27+
assert_equal 10, posts.length
28+
29+
30+
end
31+
32+
it 'does not remove ordering from subquery that includes a limit' do
33+
ActiveSupport::Notifications.subscribe('sql.active_record') do |_name, _start, _finish, _id, payload|
34+
puts payload[:sql]
35+
end
36+
37+
38+
39+
# EXEC sp_executesql N'SELECT [posts].* FROM [posts] WHERE [posts].[author_id] IN (SELECT [authors].[id] FROM [authors]
40+
# WHERE [authors].[name] IN (@0, @1, @2) ORDER BY [authors].[name] ASC OFFSET 0 ROWS FETCH NEXT @3 ROWS ONLY)',
41+
# N'@0 nvarchar(4000), @1 nvarchar(4000), @2 nvarchar(4000), @3 int', @0 = N'David', @1 = N'Mary', @2 = N'Bob', @3 = 2
42+
43+
authors_subquery = Author.where(name: ['David', 'Mary', 'Bob']).order(:name).limit(2)
44+
posts = Post.where(author: authors_subquery)
45+
46+
assert_includes authors_subquery.to_sql, "ORDER BY [authors].[name]"
47+
48+
# $debugger = true
49+
50+
assert_includes posts.to_sql, "ORDER BY [authors].[name]"
51+
assert_equal 7, posts.length
52+
end
53+
54+
#
55+
it 'does not remove ordering from subquery that includes an offset' do
56+
ActiveSupport::Notifications.subscribe('sql.active_record') do |_name, _start, _finish, _id, payload|
57+
puts payload[:sql]
58+
end
59+
60+
# EXEC sp_executesql N'SELECT [posts].* FROM [posts] WHERE [posts].[author_id] IN (SELECT [authors].[id] FROM [authors]
61+
# WHERE [authors].[name] IN (@0, @1, @2) ORDER BY [authors].[name] ASC OFFSET @3 ROWS)',
62+
# N'@0 nvarchar(4000), @1 nvarchar(4000), @2 nvarchar(4000), @3 int', @0 = N'David', @1 = N'Mary', @2 = N'Bob', @3 = 1
63+
64+
65+
authors_subquery = Author.where(name: ['David', 'Mary', 'Bob']).order(:name).offset(1)
66+
posts = Post.where(author: authors_subquery)
67+
68+
assert_includes authors_subquery.to_sql, "ORDER BY [authors].[name]"
69+
assert_includes posts.to_sql, "ORDER BY [authors].[name]"
70+
assert_equal 8, posts.length
71+
end
72+
73+
74+
end

0 commit comments

Comments
 (0)