aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorYasuo Honda <yasuo.honda@gmail.com>2014-11-04 04:44:01 +0900
committerYasuo Honda <yasuo.honda@gmail.com>2015-06-19 23:02:58 +0000
commit0e1427e917a4e47dce9f02ad9309600073622c73 (patch)
treeaa87b1860def6939c47cb46b236105f8b8c42bc2 /lib
parent8d04c28b619212f99e6ce534f75ebda59bb200a1 (diff)
downloadrails-0e1427e917a4e47dce9f02ad9309600073622c73.tar.gz
rails-0e1427e917a4e47dce9f02ad9309600073622c73.tar.bz2
rails-0e1427e917a4e47dce9f02ad9309600073622c73.zip
Create Arel::Visitors::Oracle12 to provide better top-N query
to support `FETCH FIRST n ROWS` and `OFFSET` for Oracle 12c database
Diffstat (limited to 'lib')
-rw-r--r--lib/arel/visitors.rb1
-rw-r--r--lib/arel/visitors/oracle12.rb53
2 files changed, 54 insertions, 0 deletions
diff --git a/lib/arel/visitors.rb b/lib/arel/visitors.rb
index 4a8d254ba7..f492ca2d9d 100644
--- a/lib/arel/visitors.rb
+++ b/lib/arel/visitors.rb
@@ -6,6 +6,7 @@ require 'arel/visitors/postgresql'
require 'arel/visitors/mysql'
require 'arel/visitors/mssql'
require 'arel/visitors/oracle'
+require 'arel/visitors/oracle12'
require 'arel/visitors/where_sql'
require 'arel/visitors/dot'
require 'arel/visitors/ibm_db'
diff --git a/lib/arel/visitors/oracle12.rb b/lib/arel/visitors/oracle12.rb
new file mode 100644
index 0000000000..4a42343c9b
--- /dev/null
+++ b/lib/arel/visitors/oracle12.rb
@@ -0,0 +1,53 @@
+module Arel
+ module Visitors
+ class Oracle12 < Arel::Visitors::ToSql
+ private
+
+ def visit_Arel_Nodes_SelectStatement o, collector
+ # Oracle does not allow LIMIT clause with select for update
+ if o.limit && o.lock
+ o = o.dup
+ o.limit = []
+ end
+
+ super
+ end
+
+ def visit_Arel_Nodes_SelectOptions o, collector
+ collector = maybe_visit o.offset, collector
+ collector = maybe_visit o.limit, collector
+ collector = maybe_visit o.lock, collector
+ end
+
+ def visit_Arel_Nodes_Limit o, collector
+ collector << "FETCH FIRST "
+ collector = visit o.expr, collector
+ collector << " ROWS ONLY"
+ end
+
+ def visit_Arel_Nodes_Offset o, collector
+ collector << "OFFSET "
+ visit o.expr, collector
+ collector << " ROWS"
+ end
+
+ def visit_Arel_Nodes_Except o, collector
+ collector << "( "
+ collector = infix_value o, collector, " MINUS "
+ collector << " )"
+ end
+
+ def visit_Arel_Nodes_UpdateStatement o, collector
+ # Oracle does not allow ORDER BY/LIMIT in UPDATEs.
+ if o.orders.any? && o.limit.nil?
+ # However, there is no harm in silently eating the ORDER BY clause if no LIMIT has been provided,
+ # otherwise let the user deal with the error
+ o = o.dup
+ o.orders = []
+ end
+
+ super
+ end
+ end
+ end
+end