Skip to content

Commit bebee28

Browse files
jrafaniemetaskills
authored andcommitted
Fix custom order method which created invalid syntax for order by clauses containing case expressions, inline functions or other non-column expressions. Moved ordering tests into a new test file.
1 parent aeca034 commit bebee28

File tree

3 files changed

+140
-8
lines changed

3 files changed

+140
-8
lines changed

lib/arel/visitors/sqlserver.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ def order(*expr)
4141
x
4242
when String
4343
x.split(',').map do |s|
44-
e, d = s.split
44+
s.strip!
45+
d = s =~ /(asc|desc)$/i ? $1.upcase : nil
46+
e = d.nil? ? s : s[0...-d.length].strip
4547
e = Arel.sql(e)
46-
d =~ /desc/i ? Arel::Nodes::Descending.new(e) : Arel::Nodes::Ascending.new(e)
48+
d && d == "DESC" ? Arel::Nodes::Descending.new(e) : Arel::Nodes::Ascending.new(e)
4749
end
4850
else
4951
e = Arel.sql(x.to_s)

test/cases/adapter_test_sqlserver.rb

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,6 @@ def setup
1919

2020
context 'For abstract behavior' do
2121

22-
should 'not mangel complex order clauses' do
23-
xyz_order = "CASE WHEN [title] LIKE N'XYZ%' THEN 0 ELSE 1 END"
24-
xyz_post = Post.create :title => 'XYZ Post', :body => 'Test cased orders.'
25-
assert_equal xyz_post, Post.order(Arel::Nodes::Ordering.new(Arel.sql(xyz_order))).first
26-
end
27-
2822
should 'have a 128 max #table_alias_length' do
2923
assert @connection.table_alias_length <= 128
3024
end

test/cases/order_test_sqlserver.rb

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
require 'cases/sqlserver_helper'
2+
require 'models/post'
3+
4+
class OrderTestSqlserver < ActiveRecord::TestCase
5+
6+
fixtures :posts
7+
8+
context 'Order by' do
9+
10+
should 'not mangel complex order clauses' do
11+
xyz_order = "CASE WHEN [title] LIKE N'XYZ%' THEN 0 ELSE 1 END"
12+
xyz_post = Post.create :title => 'XYZ Post', :body => 'Test cased orders.'
13+
assert_equal xyz_post, Post.order(Arel::Nodes::Ordering.new(Arel.sql(xyz_order))).first
14+
end
15+
16+
should 'support column' do
17+
order = "title"
18+
post1 = Post.create :title => 'AAA Post', :body => 'Test cased orders.'
19+
assert_equal post1, Post.order(order).first
20+
end
21+
22+
should 'support column ASC' do
23+
order = "title ASC"
24+
post1 = Post.create :title => 'AAA Post', :body => 'Test cased orders.'
25+
assert_equal post1, Post.order(order).first
26+
end
27+
28+
should 'support column DESC' do
29+
order = "title DESC"
30+
post1 = Post.create :title => 'ZZZ Post', :body => 'Test cased orders.'
31+
assert_equal post1, Post.order(order).first
32+
end
33+
34+
should 'support column as symbol' do
35+
order = :title
36+
post1 = Post.create :title => 'AAA Post', :body => 'Test cased orders.'
37+
assert_equal post1, Post.order(order).first
38+
end
39+
40+
should 'support table and column' do
41+
order = "posts.title"
42+
post1 = Post.create :title => 'AAA Post', :body => 'Test cased orders.'
43+
assert_equal post1, Post.order(order).first
44+
end
45+
46+
should 'support quoted column' do
47+
order = "[title]"
48+
post1 = Post.create :title => 'AAA Post', :body => 'Test cased orders.'
49+
assert_equal post1, Post.order(order).first
50+
end
51+
52+
should 'support quoted table and column' do
53+
order = "[posts].[title]"
54+
post1 = Post.create :title => 'AAA Post', :body => 'Test cased orders.'
55+
assert_equal post1, Post.order(order).first
56+
end
57+
58+
should 'support primary: column, secondary: column' do
59+
order = "title DESC, body"
60+
post1 = Post.create :title => 'ZZZ Post', :body => 'Test cased orders.'
61+
post2 = Post.create :title => 'ZZZ Post', :body => 'ZZZ Test cased orders.'
62+
assert_equal post1, Post.order(order).first
63+
assert_equal post2, Post.order(order).second
64+
end
65+
66+
should 'support primary: table and column, secondary: column' do
67+
order = "posts.title DESC, body"
68+
post1 = Post.create :title => 'ZZZ Post', :body => 'Test cased orders.'
69+
post2 = Post.create :title => 'ZZZ Post', :body => 'ZZZ Test cased orders.'
70+
assert_equal post1, Post.order(order).first
71+
assert_equal post2, Post.order(order).second
72+
end
73+
74+
should 'support primary: case expression, secondary: column' do
75+
order = "(CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END) DESC, body"
76+
post1 = Post.create :title => 'ZZZ Post', :body => 'Test cased orders.'
77+
post2 = Post.create :title => 'ZZZ Post', :body => 'ZZZ Test cased orders.'
78+
assert_equal post1, Post.order(order).first
79+
assert_equal post2, Post.order(order).second
80+
end
81+
82+
should 'support primary: quoted table and column, secondary: case expresion' do
83+
order = "[posts].[body] DESC, (CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END) DESC"
84+
post1 = Post.create :title => 'ZZZ Post', :body => 'ZZZ Test cased orders.'
85+
post2 = Post.create :title => 'ZZY Post', :body => 'ZZZ Test cased orders.'
86+
assert_equal post1, Post.order(order).first
87+
assert_equal post2, Post.order(order).second
88+
end
89+
90+
should 'support inline function' do
91+
order = "LEN(title)"
92+
post1 = Post.create :title => 'A', :body => 'AAA Test cased orders.'
93+
assert_equal post1, Post.order(order).first
94+
end
95+
96+
should 'support primary: inline function, secondary: column' do
97+
order = "LEN(title), body"
98+
post1 = Post.create :title => 'A', :body => 'AAA Test cased orders.'
99+
post2 = Post.create :title => 'A', :body => 'Test cased orders.'
100+
assert_equal post1, Post.order(order).first
101+
assert_equal post2, Post.order(order).second
102+
end
103+
104+
should 'support primary: inline function, secondary: column with direction' do
105+
order = "LEN(title) ASC, body DESC"
106+
post1 = Post.create :title => 'A', :body => 'ZZZ Test cased orders.'
107+
post2 = Post.create :title => 'A', :body => 'Test cased orders.'
108+
assert_equal post1, Post.order(order).first
109+
assert_equal post2, Post.order(order).second
110+
end
111+
112+
should 'support primary: column, secondary: inline function' do
113+
order = "body DESC, LEN(title)"
114+
post1 = Post.create :title => 'Post', :body => 'ZZZ Test cased orders.'
115+
post2 = Post.create :title => 'Longer Post', :body => 'ZZZ Test cased orders.'
116+
assert_equal post1, Post.order(order).first
117+
assert_equal post2, Post.order(order).second
118+
end
119+
120+
should 'support primary: case expression, secondary: inline function' do
121+
order = "CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END DESC, LEN(body) ASC"
122+
post1 = Post.create :title => 'ZZZ Post', :body => 'Z'
123+
post2 = Post.create :title => 'ZZZ Post', :body => 'Test cased orders.'
124+
assert_equal post1, Post.order(order).first
125+
assert_equal post2, Post.order(order).second
126+
end
127+
128+
should 'support primary: inline function, secondary: case expression' do
129+
order = "LEN(body), CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END DESC"
130+
post1 = Post.create :title => 'ZZZ Post', :body => 'Z'
131+
post2 = Post.create :title => 'Post', :body => 'Z'
132+
assert_equal post1, Post.order(order).first
133+
assert_equal post2, Post.order(order).second
134+
end
135+
end
136+
end

0 commit comments

Comments
 (0)