diff options
-rw-r--r-- | lib/arel/visitors/oracle.rb | 24 | ||||
-rw-r--r-- | spec/arel/visitors/oracle_spec.rb | 15 |
2 files changed, 38 insertions, 1 deletions
diff --git a/lib/arel/visitors/oracle.rb b/lib/arel/visitors/oracle.rb index afea683080..c3af68cc36 100644 --- a/lib/arel/visitors/oracle.rb +++ b/lib/arel/visitors/oracle.rb @@ -1,8 +1,10 @@ module Arel module Visitors class Oracle < Arel::Visitors::ToSql + private + def visit_Arel_Nodes_SelectStatement o - if o.limit && o.orders.empty? + if o.limit && o.orders.empty? && !o.offset o.cores.last.wheres.push Nodes::LessThanOrEqual.new( Nodes::SqlLiteral.new('ROWNUM'), o.limit ) @@ -10,6 +12,22 @@ module Arel return super end + if o.limit && o.offset + limit = o.limit.to_i + offset = o.offset + o.limit = nil + o.offset = nil + sql = super + return <<-eosql + SELECT * FROM ( + SELECT raw_sql_.*, rownum raw_rnum_ + FROM (#{sql}) raw_sql_ + WHERE rownum <= #{offset.value.to_i + limit} + ) + WHERE #{visit offset} + eosql + end + if o.limit && !o.orders.empty? limit = o.limit o.limit = nil @@ -18,6 +36,10 @@ module Arel super end + + def visit_Arel_Nodes_Offset o + "raw_rnum_ > #{visit o.value}" + end end end end diff --git a/spec/arel/visitors/oracle_spec.rb b/spec/arel/visitors/oracle_spec.rb index 87a1c378ac..07ac352893 100644 --- a/spec/arel/visitors/oracle_spec.rb +++ b/spec/arel/visitors/oracle_spec.rb @@ -25,6 +25,21 @@ module Arel SELECT * FROM (SELECT ORDER BY foo) WHERE ROWNUM <= 10 } end + + it 'creates a different subquery when there is an offset' do + stmt = Nodes::SelectStatement.new + stmt.limit = 10 + stmt.offset = Nodes::Offset.new(10) + sql = @visitor.accept stmt + sql.should be_like %{ + SELECT * FROM ( + SELECT raw_sql_.*, rownum raw_rnum_ + FROM (SELECT ) raw_sql_ + WHERE rownum <= 20 + ) + WHERE raw_rnum_ > 10 + } + end end end end |