Class: ActiveRecord::Refined::AST::Over

Inherits:
Node
  • Object
show all
Includes:
Arithmetics, Predications
Defined in:
lib/active_record/refined/ast.rb

Overview

A function with a window. The window is built by chaining, the way Arel's own is, and each method returns a new node rather than adding to this one, so a window can be finished more than one way.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Arithmetics

#&, #*, #+, #-, #/, #<<, #>>, #^, #|, #~

Methods included from Predications

#!=, #!~, #<, #<=, #==, #=~, #>, #>=, #between?, #bury, #casecmp?, #contains?, #dig, #dig_text, #distinct_from?, #end_with?, #except, #false?, #ilike?, #in?, #include?, #intersect?, #key?, #keys, #like?, #member?, #not_between?, #not_distinct_from?, #not_false?, #not_ilike?, #not_in?, #not_like?, #not_null?, #not_true?, #null?, #start_with?, #subset?, #superset?, #true?, #when

Methods inherited from Node

#as, #asc, #collate, #desc

Constructor Details

#initialize(function, partitions = [], orders = [], frame = nil) ⇒ Over

Returns a new instance of Over.



1506
1507
1508
1509
1510
1511
# File 'lib/active_record/refined/ast.rb', line 1506

def initialize(function, partitions = [], orders = [], frame = nil)
  @function = function
  @partitions = partitions
  @orders = orders
  @frame = frame
end

Instance Attribute Details

#frameObject (readonly)

Returns the value of attribute frame.



1504
1505
1506
# File 'lib/active_record/refined/ast.rb', line 1504

def frame
  @frame
end

#functionObject (readonly)

Returns the value of attribute function.



1504
1505
1506
# File 'lib/active_record/refined/ast.rb', line 1504

def function
  @function
end

#ordersObject (readonly)

Returns the value of attribute orders.



1504
1505
1506
# File 'lib/active_record/refined/ast.rb', line 1504

def orders
  @orders
end

#partitionsObject (readonly)

Returns the value of attribute partitions.



1504
1505
1506
# File 'lib/active_record/refined/ast.rb', line 1504

def partitions
  @partitions
end

Instance Method Details

#order(*exprs) ⇒ AST::Over

ORDER BY within the window: columns, or orderings such as :age.desc.

Returns:

Raises:

  • (ArgumentError)


1522
1523
1524
1525
# File 'lib/active_record/refined/ast.rb', line 1522

def order(*exprs)
  raise ArgumentError, "order needs an expression" if exprs.empty?
  Over.new(function, partitions, orders + exprs, frame)
end

#partition(*exprs) ⇒ AST::Over

PARTITION BY, the columns or expressions given.

Returns:

Raises:

  • (ArgumentError)


1515
1516
1517
1518
# File 'lib/active_record/refined/ast.rb', line 1515

def partition(*exprs)
  raise ArgumentError, "partition needs an expression" if exprs.empty?
  Over.new(function, partitions + exprs, orders, frame)
end

#range(bounds) ⇒ AST::Over

RANGE BETWEEN, with the bounds as #rows takes them.

Parameters:

  • bounds (Range)

Returns:



1537
1538
1539
# File 'lib/active_record/refined/ast.rb', line 1537

def range(bounds)
  Over.new(function, partitions, orders, framing(:range, bounds))
end

#rows(bounds) ⇒ AST::Over

ROWS BETWEEN, as a range of rows counted from the current one: negative before it, positive after, 0 the row itself, an open end unbounded. rows(..0) is a running total, rows(-1..1) the row and its neighbours.

Parameters:

  • bounds (Range)

Returns:



1530
1531
1532
# File 'lib/active_record/refined/ast.rb', line 1530

def rows(bounds)
  Over.new(function, partitions, orders, framing(:rows, bounds))
end

#to_arel(table, model) ⇒ Object



1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
# File 'lib/active_record/refined/ast.rb', line 1541

def to_arel(table, model)
  window = Arel::Nodes::Window.new
  partitions.each { |expr| window.partition(to_arel_operand(expr, table, model)) }
  orders.each { |expr| window.order(to_arel_operand(expr, table, model)) }
  frame_arel(window) if frame

  # Not every aggregate can ride a window everywhere; the node itself
  # says where, once the adapter is known.
  function.check_window(model) if function.respond_to?(:check_window)

  # A window-only function refuses to build on its own; here is where
  # it is asked for the call itself.
  arel_function =
    function.is_a?(WindowFunction) ? function.call_arel(table, model)
                                   : function.to_arel(table, model)
  Arel::Nodes::Over.new(arel_function, window)
end