diff options
Diffstat (limited to 'lib/arel')
-rw-r--r-- | lib/arel/collectors/plain_string.rb | 18 | ||||
-rw-r--r-- | lib/arel/collectors/sql_string.rb | 17 | ||||
-rw-r--r-- | lib/arel/expressions.rb | 9 | ||||
-rw-r--r-- | lib/arel/nodes.rb | 2 | ||||
-rw-r--r-- | lib/arel/nodes/and.rb | 6 | ||||
-rw-r--r-- | lib/arel/nodes/window.rb | 27 | ||||
-rw-r--r-- | lib/arel/predications.rb | 40 | ||||
-rw-r--r-- | lib/arel/select_manager.rb | 2 | ||||
-rw-r--r-- | lib/arel/table.rb | 2 | ||||
-rw-r--r-- | lib/arel/tree_manager.rb | 4 | ||||
-rw-r--r-- | lib/arel/visitors/bind_substitute.rb | 2 | ||||
-rw-r--r-- | lib/arel/visitors/dot.rb | 6 | ||||
-rw-r--r-- | lib/arel/visitors/to_sql.rb | 17 |
13 files changed, 95 insertions, 57 deletions
diff --git a/lib/arel/collectors/plain_string.rb b/lib/arel/collectors/plain_string.rb new file mode 100644 index 0000000000..2505bc376e --- /dev/null +++ b/lib/arel/collectors/plain_string.rb @@ -0,0 +1,18 @@ +module Arel + module Collectors + class PlainString + def initialize + @str = '' + end + + def value + @str + end + + def << str + @str << str + self + end + end + end +end diff --git a/lib/arel/collectors/sql_string.rb b/lib/arel/collectors/sql_string.rb index 45001bb507..8ca89ca7bd 100644 --- a/lib/arel/collectors/sql_string.rb +++ b/lib/arel/collectors/sql_string.rb @@ -1,21 +1,10 @@ # encoding: utf-8 +require 'arel/collectors/plain_string' + module Arel module Collectors - class SQLString - def initialize - @str = '' - end - - def value - @str - end - - def << str - @str << str - self - end - + class SQLString < PlainString def add_bind bind self << bind.to_s self diff --git a/lib/arel/expressions.rb b/lib/arel/expressions.rb index fa18f15b67..d40268c292 100644 --- a/lib/arel/expressions.rb +++ b/lib/arel/expressions.rb @@ -5,23 +5,24 @@ module Arel end def sum - Nodes::Sum.new [self], Nodes::SqlLiteral.new('sum_id') + Nodes::Sum.new [self] end def maximum - Nodes::Max.new [self], Nodes::SqlLiteral.new('max_id') + Nodes::Max.new [self] end def minimum - Nodes::Min.new [self], Nodes::SqlLiteral.new('min_id') + Nodes::Min.new [self] end def average - Nodes::Avg.new [self], Nodes::SqlLiteral.new('avg_id') + Nodes::Avg.new [self] end def extract field Nodes::Extract.new [self], field end + end end diff --git a/lib/arel/nodes.rb b/lib/arel/nodes.rb index a68e327983..c6bde8c3cc 100644 --- a/lib/arel/nodes.rb +++ b/lib/arel/nodes.rb @@ -78,7 +78,7 @@ module Arel def self.build_quoted other, attribute = nil case other - when Arel::Nodes::Node, Arel::Attributes::Attribute, Arel::Nodes::SelectStatement, Arel::Table, Arel::Nodes::BindParam + when Arel::Nodes::Node, Arel::Attributes::Attribute, Arel::Table, Arel::Nodes::BindParam, Arel::SelectManager other else case attribute diff --git a/lib/arel/nodes/and.rb b/lib/arel/nodes/and.rb index 62e8ef6f11..8e1afda709 100644 --- a/lib/arel/nodes/and.rb +++ b/lib/arel/nodes/and.rb @@ -3,12 +3,8 @@ module Arel class And < Arel::Nodes::Node attr_reader :children - def initialize children, right = nil + def initialize children super() - unless Array === children - warn "(#{caller.first}) AND nodes should be created with a list" - children = [children, right] - end @children = children end diff --git a/lib/arel/nodes/window.rb b/lib/arel/nodes/window.rb index 60259e8c05..fee8eeff7a 100644 --- a/lib/arel/nodes/window.rb +++ b/lib/arel/nodes/window.rb @@ -1,10 +1,12 @@ module Arel module Nodes class Window < Arel::Nodes::Node - attr_accessor :orders, :framing + attr_accessor :orders, :framing, :partitions def initialize @orders = [] + @partitions = [] + @framing = nil end def order *expr @@ -15,16 +17,32 @@ module Arel self end + def partition *expr + # FIXME: We SHOULD NOT be converting these to SqlLiteral automatically + @partitions.concat expr.map { |x| + String === x || Symbol === x ? Nodes::SqlLiteral.new(x.to_s) : x + } + self + end + def frame(expr) @framing = expr end def rows(expr = nil) - frame(Rows.new(expr)) + if @framing + Rows.new(expr) + else + frame(Rows.new(expr)) + end end def range(expr = nil) - frame(Range.new(expr)) + if @framing + Range.new(expr) + else + frame(Range.new(expr)) + end end def initialize_copy other @@ -39,7 +57,8 @@ module Arel def eql? other self.class == other.class && self.orders == other.orders && - self.framing == other.framing + self.framing == other.framing && + self.partitions == other.partitions end alias :== :eql? end diff --git a/lib/arel/predications.rb b/lib/arel/predications.rb index 2ef4837548..78cd87d430 100644 --- a/lib/arel/predications.rb +++ b/lib/arel/predications.rb @@ -29,14 +29,16 @@ module Arel when Arel::SelectManager Arel::Nodes::In.new(self, other.ast) when Range - if other.begin == -Float::INFINITY && other.end == Float::INFINITY - Nodes::NotIn.new self, [] + if other.begin == -Float::INFINITY + if other.end == Float::INFINITY + Nodes::NotIn.new self, [] + elsif other.exclude_end? + Nodes::LessThan.new(self, Nodes.build_quoted(other.end, self)) + else + Nodes::LessThanOrEqual.new(self, Nodes.build_quoted(other.end, self)) + end elsif other.end == Float::INFINITY Nodes::GreaterThanOrEqual.new(self, Nodes.build_quoted(other.begin, self)) - elsif other.begin == -Float::INFINITY && other.exclude_end? - Nodes::LessThan.new(self, Nodes.build_quoted(other.end, self)) - elsif other.begin == -Float::INFINITY - Nodes::LessThanOrEqual.new(self, Nodes.build_quoted(other.end, self)) elsif other.exclude_end? left = Nodes::GreaterThanOrEqual.new(self, Nodes.build_quoted(other.begin, self)) right = Nodes::LessThan.new(self, Nodes.build_quoted(other.end, self)) @@ -64,21 +66,23 @@ module Arel when Arel::SelectManager Arel::Nodes::NotIn.new(self, other.ast) when Range - if other.begin == -Float::INFINITY && other.end == Float::INFINITY - Nodes::In.new self, [] - elsif other.end == Float::INFINITY + if other.begin == -Float::INFINITY # The range begins with negative infinity + if other.end == Float::INFINITY + Nodes::In.new self, [] # The range is infinite, so return an empty range + elsif other.exclude_end? + Nodes::GreaterThanOrEqual.new(self, Nodes.build_quoted(other.end, self)) + else + Nodes::GreaterThan.new(self, Nodes.build_quoted(other.end, self)) + end + elsif other.end == Float::INFINITY Nodes::LessThan.new(self, Nodes.build_quoted(other.begin, self)) - elsif other.begin == -Float::INFINITY && other.exclude_end? - Nodes::GreaterThanOrEqual.new(self, Nodes.build_quoted(other.end, self)) - elsif other.begin == -Float::INFINITY - Nodes::GreaterThan.new(self, Nodes.build_quoted(other.end, self)) - elsif other.exclude_end? - left = Nodes::LessThan.new(self, Nodes.build_quoted(other.begin, self)) - right = Nodes::GreaterThanOrEqual.new(self, Nodes.build_quoted(other.end, self)) - Nodes::Or.new left, right else left = Nodes::LessThan.new(self, Nodes.build_quoted(other.begin, self)) - right = Nodes::GreaterThan.new(self, Nodes.build_quoted(other.end, self)) + if other.exclude_end? + right = Nodes::GreaterThanOrEqual.new(self, Nodes.build_quoted(other.end, self)) + else + right = Nodes::GreaterThan.new(self, Nodes.build_quoted(other.end, self)) + end Nodes::Or.new left, right end when Array diff --git a/lib/arel/select_manager.rb b/lib/arel/select_manager.rb index f1dde6403a..4a652f2c9c 100644 --- a/lib/arel/select_manager.rb +++ b/lib/arel/select_manager.rb @@ -106,7 +106,7 @@ module Arel case relation when String, Nodes::SqlLiteral - raise if relation.blank? + raise if relation.empty? klass = Nodes::StringJoin end diff --git a/lib/arel/table.rb b/lib/arel/table.rb index 545e73e3ae..01d4561ff1 100644 --- a/lib/arel/table.rb +++ b/lib/arel/table.rb @@ -57,7 +57,7 @@ primary_key (#{caller.first}) is deprecated and will be removed in Arel 4.0.0 case relation when String, Nodes::SqlLiteral - raise if relation.blank? + raise if relation.empty? klass = Nodes::StringJoin end diff --git a/lib/arel/tree_manager.rb b/lib/arel/tree_manager.rb index 87887800d0..8bff97af78 100644 --- a/lib/arel/tree_manager.rb +++ b/lib/arel/tree_manager.rb @@ -15,7 +15,9 @@ module Arel end def to_dot - Visitors::Dot.new.accept @ast + collector = Arel::Collectors::PlainString.new + collector = Visitors::Dot.new.accept @ast, collector + collector.value end def visitor diff --git a/lib/arel/visitors/bind_substitute.rb b/lib/arel/visitors/bind_substitute.rb index 0503a9c986..ce0fb5c924 100644 --- a/lib/arel/visitors/bind_substitute.rb +++ b/lib/arel/visitors/bind_substitute.rb @@ -1,7 +1,7 @@ module Arel module Visitors class BindSubstitute - def initialize delegte + def initialize delegate @delegate = delegate end end diff --git a/lib/arel/visitors/dot.rb b/lib/arel/visitors/dot.rb index ba35223ac9..f0cefeabd7 100644 --- a/lib/arel/visitors/dot.rb +++ b/lib/arel/visitors/dot.rb @@ -22,9 +22,9 @@ module Arel @seen = {} end - def accept object + def accept object, collector visit object - to_dot + collector << to_dot end private @@ -82,12 +82,14 @@ module Arel alias :visit_Arel_Nodes_Range :unary def window o + visit_edge o, "partitions" visit_edge o, "orders" visit_edge o, "framing" end alias :visit_Arel_Nodes_Window :window def named_window o + visit_edge o, "partitions" visit_edge o, "orders" visit_edge o, "framing" visit_edge o, "name" diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb index 264521f4c6..ae1b7930af 100644 --- a/lib/arel/visitors/to_sql.rb +++ b/lib/arel/visitors/to_sql.rb @@ -103,9 +103,7 @@ module Arel collector << "UPDATE " collector = visit o.relation, collector - values = false unless o.values.empty? - values = true collector << " SET " collector = inject_join o.values, collector, ", " end @@ -300,8 +298,9 @@ module Arel raise NotImplementedError, 'DISTINCT ON not implemented for this db' end - def visit_Arel_Nodes_With o - "WITH #{o.children.map { |x| visit x }.join(', ')}" + def visit_Arel_Nodes_With o, collector + collector << "WITH " + inject_join o.children, collector, ', ' end def visit_Arel_Nodes_WithRecursive o, collector @@ -337,12 +336,20 @@ module Arel def visit_Arel_Nodes_Window o, collector collector << "(" + + if o.partitions.any? + collector << "PARTITION BY " + collector = inject_join o.partitions, collector, ", " + end + if o.orders.any? + collector << ' ' if o.partitions.any? collector << "ORDER BY " collector = inject_join o.orders, collector, ", " end if o.framing + collector << ' ' if o.partitions.any? or o.orders.any? collector = visit o.framing, collector end @@ -719,7 +726,7 @@ module Arel quote(o, column_for(a)) end - def unsupported o + def unsupported o, collector raise "unsupported: #{o.class.name}" end |