提交 f0c4e371 编写于 作者: A Aaron Patterson

Added Arel::Nodes::NamedFunction for representing generic SQL functions

上级 dd1a6545
......@@ -5,6 +5,7 @@
* AST is now Enumerable
* AND nodes are now n-ary nodes
* SQL Literals may be used as Attribute names
* Added Arel::Nodes::NamedFunction for representing generic SQL functions
* Deprecations
......
......@@ -28,6 +28,7 @@ lib/arel/nodes/inner_join.rb
lib/arel/nodes/insert_statement.rb
lib/arel/nodes/join_source.rb
lib/arel/nodes/lock.rb
lib/arel/nodes/named_function.rb
lib/arel/nodes/node.rb
lib/arel/nodes/ordering.rb
lib/arel/nodes/outer_join.rb
......@@ -52,6 +53,7 @@ lib/arel/visitors.rb
lib/arel/visitors/depth_first.rb
lib/arel/visitors/dot.rb
lib/arel/visitors/join_sql.rb
lib/arel/visitors/mssql.rb
lib/arel/visitors/mysql.rb
lib/arel/visitors/oracle.rb
lib/arel/visitors/order_clauses.rb
......@@ -67,6 +69,7 @@ test/nodes/test_count.rb
test/nodes/test_delete_statement.rb
test/nodes/test_equality.rb
test/nodes/test_insert_statement.rb
test/nodes/test_named_function.rb
test/nodes/test_node.rb
test/nodes/test_not.rb
test/nodes/test_or.rb
......@@ -88,6 +91,7 @@ test/test_update_manager.rb
test/visitors/test_depth_first.rb
test/visitors/test_dot.rb
test/visitors/test_join_sql.rb
test/visitors/test_mssql.rb
test/visitors/test_mysql.rb
test/visitors/test_oracle.rb
test/visitors/test_postgres.rb
......
......@@ -28,6 +28,7 @@
require 'arel/nodes/function'
require 'arel/nodes/count'
require 'arel/nodes/values'
require 'arel/nodes/named_function'
# joins
require 'arel/nodes/inner_join'
......
module Arel
module Nodes
class Count < Arel::Nodes::Function
attr_accessor :distinct
def initialize expr, distinct = false, aliaz = nil
super(expr, aliaz)
@distinct = distinct
......
......@@ -2,11 +2,12 @@ module Arel
module Nodes
class Function < Arel::Nodes::Node
include Arel::Expression
attr_accessor :expressions, :alias
attr_accessor :expressions, :alias, :distinct
def initialize expr, aliaz = nil
@expressions = expr
@alias = aliaz
@distinct = false
end
def as aliaz
......
module Arel
module Nodes
class NamedFunction < Arel::Nodes::Function
attr_accessor :name
def initialize name, expr, aliaz = nil
super(expr, aliaz)
@name = name
end
end
end
end
......@@ -28,6 +28,7 @@ def unary o
def function o
visit o.expressions
visit o.alias
visit o.distinct
end
alias :visit_Arel_Nodes_Avg :function
alias :visit_Arel_Nodes_Exists :function
......@@ -35,6 +36,13 @@ def function o
alias :visit_Arel_Nodes_Min :function
alias :visit_Arel_Nodes_Sum :function
def visit_Arel_Nodes_NamedFunction o
visit o.name
visit o.expressions
visit o.distinct
visit o.alias
end
def visit_Arel_Nodes_Count o
visit o.expressions
visit o.alias
......
......@@ -38,13 +38,6 @@ def visit_Arel_Nodes_TableAlias o
visit_edge o, "relation"
end
def visit_Arel_Nodes_Sum o
visit_edge o, "expressions"
visit_edge o, "alias"
end
alias :visit_Arel_Nodes_Max :visit_Arel_Nodes_Sum
alias :visit_Arel_Nodes_Avg :visit_Arel_Nodes_Sum
def visit_Arel_Nodes_Count o
visit_edge o, "expressions"
visit_edge o, "distinct"
......@@ -82,6 +75,24 @@ def unary o
alias :visit_Arel_Nodes_Top :unary
alias :visit_Arel_Nodes_UnqualifiedColumn :unary
def function o
visit_edge o, "expressions"
visit_edge o, "distinct"
visit_edge o, "alias"
end
alias :visit_Arel_Nodes_Exists :function
alias :visit_Arel_Nodes_Min :function
alias :visit_Arel_Nodes_Max :function
alias :visit_Arel_Nodes_Avg :function
alias :visit_Arel_Nodes_Sum :function
def visit_Arel_Nodes_NamedFunction o
visit_edge o, "name"
visit_edge o, "expressions"
visit_edge o, "distinct"
visit_edge o, "alias"
end
def visit_Arel_Nodes_InsertStatement o
visit_edge o, "relation"
visit_edge o, "columns"
......
......@@ -183,6 +183,12 @@ def visit_Arel_Nodes_Group o
visit o.expr
end
def visit_Arel_Nodes_NamedFunction o
"#{o.name}(#{o.distinct ? 'DISTINCT ' : ''}#{o.expressions.map { |x|
visit x
}.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
end
def visit_Arel_Nodes_Count o
"COUNT(#{o.distinct ? 'DISTINCT ' : ''}#{o.expressions.map { |x|
visit x
......
require 'helper'
module Arel
module Nodes
class TestNamedFunction < MiniTest::Unit::TestCase
def test_construct
function = NamedFunction.new 'omg', 'zomg'
assert_equal 'omg', function.name
assert_equal 'zomg', function.expressions
end
end
end
end
......@@ -11,6 +11,7 @@ def test_all_nodes_are_nodes
Nodes.const_get(k)
}.grep(Class).each do |klass|
next if Nodes::SqlLiteral == klass
next if klass.name =~ /^Arel::Nodes::Test/
assert klass.ancestors.include?(Nodes::Node), klass.name
end
end
......
......@@ -52,10 +52,16 @@ def test_raises_with_object
define_method("test_#{klass.name.gsub('::', '_')}") do
func = klass.new(:a, :b)
@visitor.accept func
assert_equal [:a, :b, func], @collector.calls
assert_equal [:a, :b, false, func], @collector.calls
end
end
def test_named_function
func = Arel::Nodes::NamedFunction.new(:a, :b, :c)
@visitor.accept func
assert_equal [:a, :b, false, :c, func], @collector.calls
end
def test_lock
lock = Nodes::Lock.new
@visitor.accept lock
......
......@@ -7,6 +7,25 @@ def setup
@visitor = Visitors::Dot.new
end
# functions
[
Nodes::Sum,
Nodes::Exists,
Nodes::Max,
Nodes::Min,
Nodes::Avg,
].each do |klass|
define_method("test_#{klass.name.gsub('::', '_')}") do
op = klass.new(:a, :z)
@visitor.accept op
end
end
def test_named_function
func = Nodes::NamedFunction.new 'omg', 'omg'
@visitor.accept func
end
# unary ops
[
Arel::Nodes::Not,
......
......@@ -15,6 +15,16 @@ module Visitors
sql.must_be_like '"users".*'
end
it 'should visit named functions' do
function = Nodes::NamedFunction.new('omg', [Arel.star])
assert_equal 'omg(*)', @visitor.accept(function)
end
it 'works with lists' do
function = Nodes::NamedFunction.new('omg', [Arel.star, Arel.star])
assert_equal 'omg(*, *)', @visitor.accept(function)
end
describe 'equality' do
it 'should handle false' do
sql = @visitor.accept Nodes::Equality.new(false, false)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册