diff options
Diffstat (limited to 'activerecord/lib/arel')
21 files changed, 94 insertions, 124 deletions
diff --git a/activerecord/lib/arel/collectors/composite.rb b/activerecord/lib/arel/collectors/composite.rb index d040d8598d..0533544993 100644 --- a/activerecord/lib/arel/collectors/composite.rb +++ b/activerecord/lib/arel/collectors/composite.rb @@ -24,8 +24,7 @@ module Arel # :nodoc: all [left.value, right.value] end - protected - + private attr_reader :left, :right end end diff --git a/activerecord/lib/arel/collectors/plain_string.rb b/activerecord/lib/arel/collectors/plain_string.rb index 687d7fbf2f..c0e9fff399 100644 --- a/activerecord/lib/arel/collectors/plain_string.rb +++ b/activerecord/lib/arel/collectors/plain_string.rb @@ -4,7 +4,7 @@ module Arel # :nodoc: all module Collectors class PlainString def initialize - @str = "".dup + @str = +"" end def value diff --git a/activerecord/lib/arel/collectors/sql_string.rb b/activerecord/lib/arel/collectors/sql_string.rb index c293a89a74..54e1e562c2 100644 --- a/activerecord/lib/arel/collectors/sql_string.rb +++ b/activerecord/lib/arel/collectors/sql_string.rb @@ -15,10 +15,6 @@ module Arel # :nodoc: all @bind_index += 1 self end - - def compile(bvs) - value - end end end end diff --git a/activerecord/lib/arel/collectors/substitute_binds.rb b/activerecord/lib/arel/collectors/substitute_binds.rb index 3f40eec8a8..4b894bc4b1 100644 --- a/activerecord/lib/arel/collectors/substitute_binds.rb +++ b/activerecord/lib/arel/collectors/substitute_binds.rb @@ -21,8 +21,7 @@ module Arel # :nodoc: all delegate.value end - protected - + private attr_reader :quoter, :delegate end end diff --git a/activerecord/lib/arel/delete_manager.rb b/activerecord/lib/arel/delete_manager.rb index 2def581009..fdba937d64 100644 --- a/activerecord/lib/arel/delete_manager.rb +++ b/activerecord/lib/arel/delete_manager.rb @@ -2,6 +2,8 @@ module Arel # :nodoc: all class DeleteManager < Arel::TreeManager + include TreeManager::StatementMethods + def initialize super @ast = Nodes::DeleteStatement.new @@ -12,14 +14,5 @@ module Arel # :nodoc: all @ast.relation = relation self end - - def take(limit) - @ast.limit = Nodes::Limit.new(Nodes.build_quoted(limit)) if limit - self - end - - def wheres=(list) - @ast.wheres = list - end end end diff --git a/activerecord/lib/arel/factory_methods.rb b/activerecord/lib/arel/factory_methods.rb index b828bc274e..83ec23e403 100644 --- a/activerecord/lib/arel/factory_methods.rb +++ b/activerecord/lib/arel/factory_methods.rb @@ -41,5 +41,9 @@ module Arel # :nodoc: all def lower(column) Nodes::NamedFunction.new "LOWER", [Nodes.build_quoted(column)] end + + def coalesce(*exprs) + Nodes::NamedFunction.new "COALESCE", exprs + end end end diff --git a/activerecord/lib/arel/nodes/bind_param.rb b/activerecord/lib/arel/nodes/bind_param.rb index 53c5563d93..91e9b2b70f 100644 --- a/activerecord/lib/arel/nodes/bind_param.rb +++ b/activerecord/lib/arel/nodes/bind_param.rb @@ -3,7 +3,7 @@ module Arel # :nodoc: all module Nodes class BindParam < Node - attr_accessor :value + attr_reader :value def initialize(value) @value = value diff --git a/activerecord/lib/arel/nodes/delete_statement.rb b/activerecord/lib/arel/nodes/delete_statement.rb index eaac05e2f6..5be42a084a 100644 --- a/activerecord/lib/arel/nodes/delete_statement.rb +++ b/activerecord/lib/arel/nodes/delete_statement.rb @@ -3,8 +3,7 @@ module Arel # :nodoc: all module Nodes class DeleteStatement < Arel::Nodes::Node - attr_accessor :left, :right - attr_accessor :limit + attr_accessor :left, :right, :orders, :limit, :key alias :relation :left alias :relation= :left= @@ -15,6 +14,9 @@ module Arel # :nodoc: all super() @left = relation @right = wheres + @orders = [] + @limit = nil + @key = nil end def initialize_copy(other) @@ -24,13 +26,16 @@ module Arel # :nodoc: all end def hash - [self.class, @left, @right].hash + [self.class, @left, @right, @orders, @limit, @key].hash end def eql?(other) self.class == other.class && self.left == other.left && - self.right == other.right + self.right == other.right && + self.orders == other.orders && + self.limit == other.limit && + self.key == other.key end alias :== :eql? end diff --git a/activerecord/lib/arel/nodes/node.rb b/activerecord/lib/arel/nodes/node.rb index 2b9b1e9828..8086102bde 100644 --- a/activerecord/lib/arel/nodes/node.rb +++ b/activerecord/lib/arel/nodes/node.rb @@ -8,16 +8,6 @@ module Arel # :nodoc: all include Arel::FactoryMethods include Enumerable - if $DEBUG - def _caller - @caller - end - - def initialize - @caller = caller.dup - end - end - ### # Factory method to create a Nodes::Not node that has the recipient of # the caller as a child. diff --git a/activerecord/lib/arel/nodes/select_core.rb b/activerecord/lib/arel/nodes/select_core.rb index 2defe61974..73461ff683 100644 --- a/activerecord/lib/arel/nodes/select_core.rb +++ b/activerecord/lib/arel/nodes/select_core.rb @@ -3,13 +3,12 @@ module Arel # :nodoc: all module Nodes class SelectCore < Arel::Nodes::Node - attr_accessor :top, :projections, :wheres, :groups, :windows + attr_accessor :projections, :wheres, :groups, :windows attr_accessor :havings, :source, :set_quantifier def initialize super() @source = JoinSource.new nil - @top = nil # https://ronsavage.github.io/SQL/sql-92.bnf.html#set%20quantifier @set_quantifier = nil @@ -43,7 +42,7 @@ module Arel # :nodoc: all def hash [ - @source, @top, @set_quantifier, @projections, + @source, @set_quantifier, @projections, @wheres, @groups, @havings, @windows ].hash end @@ -51,7 +50,6 @@ module Arel # :nodoc: all def eql?(other) self.class == other.class && self.source == other.source && - self.top == other.top && self.set_quantifier == other.set_quantifier && self.projections == other.projections && self.wheres == other.wheres && diff --git a/activerecord/lib/arel/nodes/unary.rb b/activerecord/lib/arel/nodes/unary.rb index a3c0045897..00639304e4 100644 --- a/activerecord/lib/arel/nodes/unary.rb +++ b/activerecord/lib/arel/nodes/unary.rb @@ -37,7 +37,6 @@ module Arel # :nodoc: all On Ordering RollUp - Top }.each do |name| const_set(name, Class.new(Unary)) end diff --git a/activerecord/lib/arel/nodes/update_statement.rb b/activerecord/lib/arel/nodes/update_statement.rb index 5184b1180f..017a553c4c 100644 --- a/activerecord/lib/arel/nodes/update_statement.rb +++ b/activerecord/lib/arel/nodes/update_statement.rb @@ -3,8 +3,7 @@ module Arel # :nodoc: all module Nodes class UpdateStatement < Arel::Nodes::Node - attr_accessor :relation, :wheres, :values, :orders, :limit - attr_accessor :key + attr_accessor :relation, :wheres, :values, :orders, :limit, :key def initialize @relation = nil diff --git a/activerecord/lib/arel/select_manager.rb b/activerecord/lib/arel/select_manager.rb index 22a04b00c6..a2b2838a3d 100644 --- a/activerecord/lib/arel/select_manager.rb +++ b/activerecord/lib/arel/select_manager.rb @@ -222,10 +222,8 @@ module Arel # :nodoc: all def take(limit) if limit @ast.limit = Nodes::Limit.new(limit) - @ctx.top = Nodes::Top.new(limit) else @ast.limit = nil - @ctx.top = nil end self end @@ -252,9 +250,9 @@ module Arel # :nodoc: all end private - def collapse(exprs, existing = nil) - exprs = exprs.unshift(existing.expr) if existing - exprs = exprs.compact.map { |expr| + def collapse(exprs) + exprs = exprs.compact + exprs.map! { |expr| if String === expr # FIXME: Don't do this automatically Arel.sql(expr) diff --git a/activerecord/lib/arel/table.rb b/activerecord/lib/arel/table.rb index 686fcdf962..c40c68715a 100644 --- a/activerecord/lib/arel/table.rb +++ b/activerecord/lib/arel/table.rb @@ -104,8 +104,7 @@ module Arel # :nodoc: all !type_caster.nil? end - protected - + private attr_reader :type_caster end end diff --git a/activerecord/lib/arel/tree_manager.rb b/activerecord/lib/arel/tree_manager.rb index ed47b09a37..149c69ce7a 100644 --- a/activerecord/lib/arel/tree_manager.rb +++ b/activerecord/lib/arel/tree_manager.rb @@ -4,6 +4,35 @@ module Arel # :nodoc: all class TreeManager include Arel::FactoryMethods + module StatementMethods + def take(limit) + @ast.limit = Nodes::Limit.new(Nodes.build_quoted(limit)) if limit + self + end + + def order(*expr) + @ast.orders = expr + self + end + + def key=(key) + @ast.key = Nodes.build_quoted(key) + end + + def key + @ast.key + end + + def wheres=(exprs) + @ast.wheres = exprs + end + + def where(expr) + @ast.wheres << expr + self + end + end + attr_reader :ast def initialize diff --git a/activerecord/lib/arel/update_manager.rb b/activerecord/lib/arel/update_manager.rb index fe444343ba..a809dbb307 100644 --- a/activerecord/lib/arel/update_manager.rb +++ b/activerecord/lib/arel/update_manager.rb @@ -2,30 +2,14 @@ module Arel # :nodoc: all class UpdateManager < Arel::TreeManager + include TreeManager::StatementMethods + def initialize super @ast = Nodes::UpdateStatement.new @ctx = @ast end - def take(limit) - @ast.limit = Nodes::Limit.new(Nodes.build_quoted(limit)) if limit - self - end - - def key=(key) - @ast.key = Nodes.build_quoted(key) - end - - def key - @ast.key - end - - def order(*expr) - @ast.orders = expr - self - end - ### # UPDATE +table+ def table(table) @@ -33,15 +17,6 @@ module Arel # :nodoc: all self end - def wheres=(exprs) - @ast.wheres = exprs - end - - def where(expr) - @ast.wheres << expr - self - end - def set(values) if String === values @ast.values = [values] diff --git a/activerecord/lib/arel/visitors/depth_first.rb b/activerecord/lib/arel/visitors/depth_first.rb index bcf8f8f980..8f65d303ac 100644 --- a/activerecord/lib/arel/visitors/depth_first.rb +++ b/activerecord/lib/arel/visitors/depth_first.rb @@ -34,7 +34,6 @@ module Arel # :nodoc: all alias :visit_Arel_Nodes_Ordering :unary alias :visit_Arel_Nodes_Ascending :unary alias :visit_Arel_Nodes_Descending :unary - alias :visit_Arel_Nodes_Top :unary alias :visit_Arel_Nodes_UnqualifiedColumn :unary def function(o) @@ -136,12 +135,10 @@ module Arel # :nodoc: all alias :visit_Arel_Nodes_True :terminal alias :visit_Arel_Nodes_False :terminal alias :visit_BigDecimal :terminal - alias :visit_Bignum :terminal alias :visit_Class :terminal alias :visit_Date :terminal alias :visit_DateTime :terminal alias :visit_FalseClass :terminal - alias :visit_Fixnum :terminal alias :visit_Float :terminal alias :visit_Integer :terminal alias :visit_NilClass :terminal diff --git a/activerecord/lib/arel/visitors/dot.rb b/activerecord/lib/arel/visitors/dot.rb index d352b81914..9054f0159b 100644 --- a/activerecord/lib/arel/visitors/dot.rb +++ b/activerecord/lib/arel/visitors/dot.rb @@ -81,7 +81,6 @@ module Arel # :nodoc: all alias :visit_Arel_Nodes_Not :unary alias :visit_Arel_Nodes_Offset :unary alias :visit_Arel_Nodes_On :unary - alias :visit_Arel_Nodes_Top :unary alias :visit_Arel_Nodes_UnqualifiedColumn :unary alias :visit_Arel_Nodes_Preceding :unary alias :visit_Arel_Nodes_Following :unary @@ -212,7 +211,6 @@ module Arel # :nodoc: all alias :visit_TrueClass :visit_String alias :visit_FalseClass :visit_String alias :visit_Integer :visit_String - alias :visit_Fixnum :visit_String alias :visit_BigDecimal :visit_String alias :visit_Float :visit_String alias :visit_Symbol :visit_String diff --git a/activerecord/lib/arel/visitors/mssql.rb b/activerecord/lib/arel/visitors/mssql.rb index 9aedc51d15..d564e19089 100644 --- a/activerecord/lib/arel/visitors/mssql.rb +++ b/activerecord/lib/arel/visitors/mssql.rb @@ -12,13 +12,6 @@ module Arel # :nodoc: all private - # `top` wouldn't really work here. I.e. User.select("distinct first_name").limit(10) would generate - # "select top 10 distinct first_name from users", which is invalid query! it should be - # "select distinct top 10 first_name from users" - def visit_Arel_Nodes_Top(o) - "" - end - def visit_Arel_Visitors_MSSQL_RowNumber(o, collector) collector << "ROW_NUMBER() OVER (ORDER BY " inject_join(o.children, collector, ", ") << ") as _row_num" diff --git a/activerecord/lib/arel/visitors/mysql.rb b/activerecord/lib/arel/visitors/mysql.rb index 37bfb661f0..0f7d5aa803 100644 --- a/activerecord/lib/arel/visitors/mysql.rb +++ b/activerecord/lib/arel/visitors/mysql.rb @@ -37,6 +37,10 @@ module Arel # :nodoc: all visit o.expr, collector end + def visit_Arel_Nodes_UnqualifiedColumn(o, collector) + visit o.expr, collector + end + ### # :'( # http://dev.mysql.com/doc/refman/5.0/en/select.html#id3482214 @@ -61,6 +65,19 @@ module Arel # :nodoc: all collector = inject_join o.values, collector, ", " end + collect_where_for(o, collector) + end + + def visit_Arel_Nodes_Concat(o, collector) + collector << " CONCAT(" + visit o.left, collector + collector << ", " + visit o.right, collector + collector << ") " + collector + end + + def collect_where_for(o, collector) unless o.wheres.empty? collector << " WHERE " collector = inject_join o.wheres, collector, " AND " @@ -73,15 +90,6 @@ module Arel # :nodoc: all maybe_visit o.limit, collector end - - def visit_Arel_Nodes_Concat(o, collector) - collector << " CONCAT(" - visit o.left, collector - collector << ", " - visit o.right, collector - collector << ") " - collector - end end end end diff --git a/activerecord/lib/arel/visitors/to_sql.rb b/activerecord/lib/arel/visitors/to_sql.rb index 5986fd5576..575bfd6e36 100644 --- a/activerecord/lib/arel/visitors/to_sql.rb +++ b/activerecord/lib/arel/visitors/to_sql.rb @@ -67,8 +67,8 @@ module Arel # :nodoc: all @connection = connection end - def compile(node, &block) - accept(node, Arel::Collectors::SQLString.new, &block).value + def compile(node, collector = Arel::Collectors::SQLString.new) + accept(node, collector).value end private @@ -76,12 +76,8 @@ module Arel # :nodoc: all def visit_Arel_Nodes_DeleteStatement(o, collector) collector << "DELETE FROM " collector = visit o.relation, collector - if o.wheres.any? - collector << WHERE - collector = inject_join o.wheres, collector, AND - end - maybe_visit o.limit, collector + collect_where_for(o, collector) end # FIXME: we should probably have a 2-pass visitor for this @@ -97,12 +93,6 @@ module Arel # :nodoc: all end def visit_Arel_Nodes_UpdateStatement(o, collector) - if o.orders.empty? && o.limit.nil? - wheres = o.wheres - else - wheres = [Nodes::In.new(o.key, [build_subselect(o.key, o)])] - end - collector << "UPDATE " collector = visit o.relation, collector unless o.values.empty? @@ -110,12 +100,7 @@ module Arel # :nodoc: all collector = inject_join o.values, collector, ", " end - unless wheres.empty? - collector << " WHERE " - collector = inject_join wheres, collector, " AND " - end - - collector + collect_where_for(o, collector) end def visit_Arel_Nodes_InsertStatement(o, collector) @@ -237,8 +222,6 @@ module Arel # :nodoc: all def visit_Arel_Nodes_SelectCore(o, collector) collector << "SELECT" - collector = maybe_visit o.top, collector - collector = maybe_visit o.set_quantifier, collector collect_nodes_for o.projections, collector, SPACE @@ -405,11 +388,6 @@ module Arel # :nodoc: all visit o.expr, collector end - # FIXME: this does nothing on most databases, but does on MSSQL - def visit_Arel_Nodes_Top(o, collector) - collector - end - def visit_Arel_Nodes_Lock(o, collector) visit o.expr, collector end @@ -644,7 +622,7 @@ module Arel # :nodoc: all def visit_Arel_Nodes_Assignment(o, collector) case o.right - when Arel::Nodes::UnqualifiedColumn, Arel::Attributes::Attribute, Arel::Nodes::BindParam + when Arel::Nodes::Node, Arel::Attributes::Attribute collector = visit o.left, collector collector << " = " visit o.right, collector @@ -739,8 +717,6 @@ module Arel # :nodoc: all end alias :visit_Arel_Nodes_SqlLiteral :literal - alias :visit_Bignum :literal - alias :visit_Fixnum :literal alias :visit_Integer :literal def quoted(o, a) @@ -823,6 +799,21 @@ module Arel # :nodoc: all } end + def collect_where_for(o, collector) + if o.orders.empty? && o.limit.nil? + wheres = o.wheres + else + wheres = [Nodes::In.new(o.key, [build_subselect(o.key, o)])] + end + + unless wheres.empty? + collector << " WHERE " + collector = inject_join wheres, collector, " AND " + end + + collector + end + def infix_value(o, collector, value) collector = visit o.left, collector collector << value |