Skip to content

Commit 1300331

Browse files
authored
Merge pull request #758 from aidanharan/in-clause-no-ordering
Rails 6: Subqueries cannot include ordering unless TOP/LIMIT also specified
2 parents b10e2b2 + 3d3faf8 commit 1300331

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

lib/arel/visitors/sqlserver.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,19 @@ def visit_Arel_Nodes_OuterJoin o, collector
127127
visit o.right, collector
128128
end
129129

130+
# Need to remove ordering from subqueries unless TOP/OFFSET also used. Otherwise, SQLServer
131+
# returns error "The ORDER BY clause is invalid in views, inline functions, derived tables,
132+
# subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified."
133+
def collect_in_clause(left, right, collector)
134+
if Array === right
135+
right.each { |node| remove_invalid_ordering_from_in_clause(node) }
136+
else
137+
remove_invalid_ordering_from_in_clause(right)
138+
end
139+
140+
super
141+
end
142+
130143
# SQLServer ToSql/Visitor (Additions)
131144

132145
def visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, options = {}
@@ -219,6 +232,11 @@ def remote_server_table_name o
219232
).quoted
220233
end
221234

235+
def remove_invalid_ordering_from_in_clause(node)
236+
return unless Arel::Nodes::SelectStatement === node
237+
238+
node.orders = [] unless node.offset || node.limit
239+
end
222240
end
223241
end
224242
end
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
require 'cases/helper_sqlserver'
2+
require 'models/post'
3+
require 'models/author'
4+
5+
class InClauseTestSQLServer < ActiveRecord::TestCase
6+
fixtures :posts, :authors
7+
8+
it 'removes ordering from subqueries' do
9+
authors_subquery = Author.where(name: ['David', 'Mary', 'Bob']).order(:name)
10+
posts = Post.where(author: authors_subquery)
11+
12+
assert_includes authors_subquery.to_sql, "ORDER BY [authors].[name]"
13+
assert_not_includes posts.to_sql, "ORDER BY [authors].[name]"
14+
assert_equal 10, posts.length
15+
end
16+
17+
it 'does not remove ordering from subquery that includes a limit' do
18+
authors_subquery = Author.where(name: ['David', 'Mary', 'Bob']).order(:name).limit(2)
19+
posts = Post.where(author: authors_subquery)
20+
21+
assert_includes authors_subquery.to_sql, "ORDER BY [authors].[name]"
22+
assert_includes posts.to_sql, "ORDER BY [authors].[name]"
23+
assert_equal 7, posts.length
24+
end
25+
26+
it 'does not remove ordering from subquery that includes an offset' do
27+
authors_subquery = Author.where(name: ['David', 'Mary', 'Bob']).order(:name).offset(1)
28+
posts = Post.where(author: authors_subquery)
29+
30+
assert_includes authors_subquery.to_sql, "ORDER BY [authors].[name]"
31+
assert_includes posts.to_sql, "ORDER BY [authors].[name]"
32+
assert_equal 8, posts.length
33+
end
34+
end

0 commit comments

Comments
 (0)