aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/arel.rb2
-rw-r--r--lib/arel/collectors/plain_string.rb18
-rw-r--r--lib/arel/collectors/sql_string.rb17
-rw-r--r--lib/arel/expressions.rb9
-rw-r--r--lib/arel/nodes.rb2
-rw-r--r--lib/arel/nodes/and.rb6
-rw-r--r--lib/arel/nodes/window.rb27
-rw-r--r--lib/arel/predications.rb40
-rw-r--r--lib/arel/select_manager.rb2
-rw-r--r--lib/arel/table.rb2
-rw-r--r--lib/arel/tree_manager.rb4
-rw-r--r--lib/arel/visitors/bind_substitute.rb2
-rw-r--r--lib/arel/visitors/dot.rb6
-rw-r--r--lib/arel/visitors/to_sql.rb17
14 files changed, 96 insertions, 58 deletions
diff --git a/lib/arel.rb b/lib/arel.rb
index 1e3c51a254..80677953df 100644
--- a/lib/arel.rb
+++ b/lib/arel.rb
@@ -21,7 +21,7 @@ require 'arel/delete_manager'
require 'arel/nodes'
module Arel
- VERSION = '6.0.0'
+ VERSION = '6.0.0.beta1'
def self.sql raw_sql
Arel::Nodes::SqlLiteral.new raw_sql
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