Hacks for the order clauses specific to Oracle
# File lib/arel/visitors/oracle.rb, line 81 81: def order_hacks o 82: return o if o.orders.empty? 83: return o unless o.cores.any? do |core| 84: core.projections.any? do |projection| 85: /DISTINCT.*FIRST_VALUE/ === projection 86: end 87: end 88: # Previous version with join and split broke ORDER BY clause 89: # if it contained functions with several arguments (separated by ','). 90: # 91: # orders = o.orders.map { |x| visit x }.join(', ').split(',') 92: orders = o.orders.map do |x| 93: string = visit x 94: if string.include?(',') 95: split_order_string(string) 96: else 97: string 98: end 99: end.flatten 100: o.orders = [] 101: orders.each_with_index do |order, i| 102: o.orders << 103: Nodes::SqlLiteral.new("alias_#{i}__#{' DESC' if /\bdesc$/i === order}") 104: end 105: o 106: end
Split string by commas but count opening and closing brackets and ignore commas inside brackets.
# File lib/arel/visitors/oracle.rb, line 110 110: def split_order_string(string) 111: array = [] 112: i = 0 113: string.split(',').each do |part| 114: if array[i] 115: array[i] << ',' << part 116: else 117: # to ensure that array[i] will be String and not Arel::Nodes::SqlLiteral 118: array[i] = '' << part 119: end 120: i += 1 if array[i].count('(') == array[i].count(')') 121: end 122: array 123: end
# File lib/arel/visitors/oracle.rb, line 63 63: def visit_Arel_Nodes_Except o 64: "( #{visit o.left} MINUS #{visit o.right} )" 65: end
# File lib/arel/visitors/oracle.rb, line 56 56: def visit_Arel_Nodes_Limit o 57: end
# File lib/arel/visitors/oracle.rb, line 59 59: def visit_Arel_Nodes_Offset o 60: "raw_rnum_ > #{visit o.expr}" 61: end
# File lib/arel/visitors/oracle.rb, line 6 6: def visit_Arel_Nodes_SelectStatement o 7: o = order_hacks(o) 8: 9: # if need to select first records without ORDER BY and GROUP BY and without DISTINCT 10: # then can use simple ROWNUM in WHERE clause 11: if o.limit && o.orders.empty? && !o.offset && o.cores.first.projections.first !~ /^DISTINCT / 12: o.cores.last.wheres.push Nodes::LessThanOrEqual.new( 13: Nodes::SqlLiteral.new('ROWNUM'), o.limit.expr 14: ) 15: return super 16: end 17: 18: if o.limit && o.offset 19: o = o.dup 20: limit = o.limit.expr.to_i 21: offset = o.offset 22: o.offset = nil 23: sql = super(o) 24: return SELECT * FROM ( SELECT raw_sql_.*, rownum raw_rnum_ FROM (#{sql}) raw_sql_ ) WHERE raw_rnum_ between #{offset.expr.to_i + 1 } and #{offset.expr.to_i + limit} 25: end 26: 27: if o.limit 28: o = o.dup 29: limit = o.limit.expr 30: return "SELECT * FROM (#{super(o)}) WHERE ROWNUM <= #{visit limit}" 31: end 32: 33: if o.offset 34: o = o.dup 35: offset = o.offset 36: o.offset = nil 37: sql = super(o) 38: return SELECT * FROM ( SELECT raw_sql_.*, rownum raw_rnum_ FROM (#{sql}) raw_sql_ ) WHERE #{visit offset} 39: end 40: 41: super 42: end
# File lib/arel/visitors/oracle.rb, line 67 67: def visit_Arel_Nodes_UpdateStatement o 68: # Oracle does not allow ORDER BY/LIMIT in UPDATEs. 69: if o.orders.any? && o.limit.nil? 70: # However, there is no harm in silently eating the ORDER BY clause if no LIMIT has been provided, 71: # otherwise let the user deal with the error 72: o = o.dup 73: o.orders = [] 74: end 75: 76: super 77: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.