Skip to content

Commit 3eddc2f

Browse files
authored
Merge pull request #450 from roooodcastro/issue-438
Use Arel::Nodes::BindParam in Oracle visitor for queries using both LIMIT and OFFSET
2 parents 44d2ef9 + 9d6e569 commit 3eddc2f

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

lib/arel/visitors/oracle.rb

+13-2
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,22 @@ def visit_Arel_Nodes_SelectStatement o, collector
2626
FROM ("
2727

2828
collector = super(o, collector)
29-
collector << ") raw_sql_
29+
30+
if offset.expr.is_a? Nodes::BindParam
31+
offset_bind = nil
32+
collector << ') raw_sql_ WHERE rownum <= ('
33+
collector.add_bind(offset.expr) { |i| offset_bind = ":a#{i}" }
34+
collector << ' + '
35+
collector.add_bind(limit) { |i| ":a#{i}" }
36+
collector << ") ) WHERE raw_rnum_ > #{offset_bind}"
37+
return collector
38+
else
39+
collector << ") raw_sql_
3040
WHERE rownum <= #{offset.expr.to_i + limit}
3141
)
3242
WHERE "
33-
return visit(offset, collector)
43+
return visit(offset, collector)
44+
end
3445
end
3546

3647
if o.limit

test/visitors/test_oracle.rb

+15-1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,21 @@ def compile node
124124
}
125125
end
126126

127+
it 'creates a subquery when there is limit and offset with BindParams' do
128+
stmt = Nodes::SelectStatement.new
129+
stmt.limit = Nodes::Limit.new(Nodes::BindParam.new)
130+
stmt.offset = Nodes::Offset.new(Nodes::BindParam.new)
131+
sql = compile stmt
132+
sql.must_be_like %{
133+
SELECT * FROM (
134+
SELECT raw_sql_.*, rownum raw_rnum_
135+
FROM (SELECT ) raw_sql_
136+
WHERE rownum <= (:a1 + :a2)
137+
)
138+
WHERE raw_rnum_ > :a1
139+
}
140+
end
141+
127142
it 'is idempotent with different subquery' do
128143
stmt = Nodes::SelectStatement.new
129144
stmt.limit = Nodes::Limit.new(10)
@@ -148,7 +163,6 @@ def compile node
148163
}
149164
end
150165
end
151-
152166
end
153167

154168
it 'modified except to be minus' do

0 commit comments

Comments
 (0)