aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/arel/visitors/oracle.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/arel/visitors/oracle.rb')
-rw-r--r--activerecord/lib/arel/visitors/oracle.rb250
1 files changed, 125 insertions, 125 deletions
diff --git a/activerecord/lib/arel/visitors/oracle.rb b/activerecord/lib/arel/visitors/oracle.rb
index d4749bbae3..7811c18a8c 100644
--- a/activerecord/lib/arel/visitors/oracle.rb
+++ b/activerecord/lib/arel/visitors/oracle.rb
@@ -1,153 +1,153 @@
# frozen_string_literal: true
+
module Arel
module Visitors
class Oracle < Arel::Visitors::ToSql
private
- def visit_Arel_Nodes_SelectStatement o, collector
- o = order_hacks(o)
+ def visit_Arel_Nodes_SelectStatement(o, collector)
+ o = order_hacks(o)
- # if need to select first records without ORDER BY and GROUP BY and without DISTINCT
- # then can use simple ROWNUM in WHERE clause
- if o.limit && o.orders.empty? && o.cores.first.groups.empty? && !o.offset && o.cores.first.set_quantifier.class.to_s !~ /Distinct/
- o.cores.last.wheres.push Nodes::LessThanOrEqual.new(
- Nodes::SqlLiteral.new('ROWNUM'), o.limit.expr
- )
- return super
- end
+ # if need to select first records without ORDER BY and GROUP BY and without DISTINCT
+ # then can use simple ROWNUM in WHERE clause
+ if o.limit && o.orders.empty? && o.cores.first.groups.empty? && !o.offset && o.cores.first.set_quantifier.class.to_s !~ /Distinct/
+ o.cores.last.wheres.push Nodes::LessThanOrEqual.new(
+ Nodes::SqlLiteral.new("ROWNUM"), o.limit.expr
+ )
+ return super
+ end
+
+ if o.limit && o.offset
+ o = o.dup
+ limit = o.limit.expr
+ offset = o.offset
+ o.offset = nil
+ collector << "
+ SELECT * FROM (
+ SELECT raw_sql_.*, rownum raw_rnum_
+ FROM ("
+
+ collector = super(o, collector)
+
+ if offset.expr.is_a? Nodes::BindParam
+ collector << ") raw_sql_ WHERE rownum <= ("
+ collector = visit offset.expr, collector
+ collector << " + "
+ collector = visit limit, collector
+ collector << ") ) WHERE raw_rnum_ > "
+ collector = visit offset.expr, collector
+ return collector
+ else
+ collector << ") raw_sql_
+ WHERE rownum <= #{offset.expr.to_i + limit}
+ )
+ WHERE "
+ return visit(offset, collector)
+ end
+ end
- if o.limit && o.offset
- o = o.dup
- limit = o.limit.expr
- offset = o.offset
- o.offset = nil
- collector << "
- SELECT * FROM (
- SELECT raw_sql_.*, rownum raw_rnum_
- FROM ("
-
- collector = super(o, collector)
-
- if offset.expr.is_a? Nodes::BindParam
- collector << ') raw_sql_ WHERE rownum <= ('
- collector = visit offset.expr, collector
- collector << ' + '
- collector = visit limit, collector
- collector << ") ) WHERE raw_rnum_ > "
- collector = visit offset.expr, collector
- return collector
- else
+ if o.limit
+ o = o.dup
+ limit = o.limit.expr
+ collector << "SELECT * FROM ("
+ collector = super(o, collector)
+ collector << ") WHERE ROWNUM <= "
+ return visit limit, collector
+ end
+
+ if o.offset
+ o = o.dup
+ offset = o.offset
+ o.offset = nil
+ collector << "SELECT * FROM (
+ SELECT raw_sql_.*, rownum raw_rnum_
+ FROM ("
+ collector = super(o, collector)
collector << ") raw_sql_
- WHERE rownum <= #{offset.expr.to_i + limit}
- )
- WHERE "
- return visit(offset, collector)
+ )
+ WHERE "
+ return visit offset, collector
end
- end
- if o.limit
- o = o.dup
- limit = o.limit.expr
- collector << "SELECT * FROM ("
- collector = super(o, collector)
- collector << ") WHERE ROWNUM <= "
- return visit limit, collector
+ super
end
- if o.offset
- o = o.dup
- offset = o.offset
- o.offset = nil
- collector << "SELECT * FROM (
- SELECT raw_sql_.*, rownum raw_rnum_
- FROM ("
- collector = super(o, collector)
- collector << ") raw_sql_
- )
- WHERE "
- return visit offset, collector
+ def visit_Arel_Nodes_Limit(o, collector)
+ collector
end
- super
- end
-
- def visit_Arel_Nodes_Limit o, collector
- collector
- end
-
- def visit_Arel_Nodes_Offset o, collector
- collector << "raw_rnum_ > "
- visit o.expr, collector
- 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 = []
+ def visit_Arel_Nodes_Offset(o, collector)
+ collector << "raw_rnum_ > "
+ visit o.expr, collector
end
- super
- end
+ def visit_Arel_Nodes_Except(o, collector)
+ collector << "( "
+ collector = infix_value o, collector, " MINUS "
+ collector << " )"
+ end
- ###
- # Hacks for the order clauses specific to Oracle
- def order_hacks o
- return o if o.orders.empty?
- return o unless o.cores.any? do |core|
- core.projections.any? do |projection|
- /FIRST_VALUE/ === projection
+ 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
- # Previous version with join and split broke ORDER BY clause
- # if it contained functions with several arguments (separated by ',').
- #
- # orders = o.orders.map { |x| visit x }.join(', ').split(',')
- orders = o.orders.map do |x|
- string = visit(x, Arel::Collectors::SQLString.new).value
- if string.include?(',')
- split_order_string(string)
- else
- string
+
+ ###
+ # Hacks for the order clauses specific to Oracle
+ def order_hacks(o)
+ return o if o.orders.empty?
+ return o unless o.cores.any? do |core|
+ core.projections.any? do |projection|
+ /FIRST_VALUE/ === projection
+ end
end
- end.flatten
- o.orders = []
- orders.each_with_index do |order, i|
- o.orders <<
- Nodes::SqlLiteral.new("alias_#{i}__#{' DESC' if /\bdesc$/i === order}")
- end
- o
- end
-
- # Split string by commas but count opening and closing brackets
- # and ignore commas inside brackets.
- def split_order_string(string)
- array = []
- i = 0
- string.split(',').each do |part|
- if array[i]
- array[i] << ',' << part
- else
- # to ensure that array[i] will be String and not Arel::Nodes::SqlLiteral
- array[i] = part.to_s
+ # Previous version with join and split broke ORDER BY clause
+ # if it contained functions with several arguments (separated by ',').
+ #
+ # orders = o.orders.map { |x| visit x }.join(', ').split(',')
+ orders = o.orders.map do |x|
+ string = visit(x, Arel::Collectors::SQLString.new).value
+ if string.include?(",")
+ split_order_string(string)
+ else
+ string
+ end
+ end.flatten
+ o.orders = []
+ orders.each_with_index do |order, i|
+ o.orders <<
+ Nodes::SqlLiteral.new("alias_#{i}__#{' DESC' if /\bdesc$/i === order}")
end
- i += 1 if array[i].count('(') == array[i].count(')')
+ o
end
- array
- end
- def visit_Arel_Nodes_BindParam o, collector
- collector.add_bind(o.value) { |i| ":a#{i}" }
- end
+ # Split string by commas but count opening and closing brackets
+ # and ignore commas inside brackets.
+ def split_order_string(string)
+ array = []
+ i = 0
+ string.split(",").each do |part|
+ if array[i]
+ array[i] << "," << part
+ else
+ # to ensure that array[i] will be String and not Arel::Nodes::SqlLiteral
+ array[i] = part.to_s
+ end
+ i += 1 if array[i].count("(") == array[i].count(")")
+ end
+ array
+ end
+ def visit_Arel_Nodes_BindParam(o, collector)
+ collector.add_bind(o.value) { |i| ":a#{i}" }
+ end
end
end
end