From 69e9be95ac233eb7b446920bb49399277ea594ce Mon Sep 17 00:00:00 2001 From: Alexander Staubo Date: Tue, 19 Feb 2013 22:27:17 +0100 Subject: Windowing support for PARTITION BY clause. --- lib/arel/nodes/window.rb | 15 +++++++++++++-- lib/arel/visitors/dot.rb | 2 ++ lib/arel/visitors/to_sql.rb | 6 ++++++ 3 files changed, 21 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/arel/nodes/window.rb b/lib/arel/nodes/window.rb index 60259e8c05..6578a414d2 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,6 +17,14 @@ 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 @@ -39,7 +49,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/visitors/dot.rb b/lib/arel/visitors/dot.rb index d96cf7a6a0..f0cefeabd7 100644 --- a/lib/arel/visitors/dot.rb +++ b/lib/arel/visitors/dot.rb @@ -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 7f74ebb402..8a5e1dbf25 100644 --- a/lib/arel/visitors/to_sql.rb +++ b/lib/arel/visitors/to_sql.rb @@ -336,6 +336,12 @@ 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 << "ORDER BY " collector = inject_join o.orders, collector, ", " -- cgit v1.2.3 From d9347943a22076911155d9a56d9a3ef6e022994b Mon Sep 17 00:00:00 2001 From: Alexander Staubo Date: Tue, 19 Feb 2013 22:28:16 +0100 Subject: Windowing: Calling #rows or #range should assign framing only once. --- lib/arel/nodes/window.rb | 12 ++++++++++-- lib/arel/visitors/to_sql.rb | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/arel/nodes/window.rb b/lib/arel/nodes/window.rb index 6578a414d2..fee8eeff7a 100644 --- a/lib/arel/nodes/window.rb +++ b/lib/arel/nodes/window.rb @@ -30,11 +30,19 @@ module Arel 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 diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb index 8a5e1dbf25..8c63070084 100644 --- a/lib/arel/visitors/to_sql.rb +++ b/lib/arel/visitors/to_sql.rb @@ -343,11 +343,13 @@ module Arel 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 -- cgit v1.2.3