aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--History.txt1
-rw-r--r--Manifest.txt4
-rw-r--r--lib/arel/nodes.rb1
-rw-r--r--lib/arel/nodes/count.rb3
-rw-r--r--lib/arel/nodes/function.rb3
-rw-r--r--lib/arel/nodes/named_function.rb12
-rw-r--r--lib/arel/visitors/depth_first.rb8
-rw-r--r--lib/arel/visitors/dot.rb25
-rw-r--r--lib/arel/visitors/to_sql.rb6
-rw-r--r--test/nodes/test_named_function.rb13
-rw-r--r--test/nodes/test_node.rb1
-rw-r--r--test/visitors/test_depth_first.rb8
-rw-r--r--test/visitors/test_dot.rb19
-rw-r--r--test/visitors/test_to_sql.rb10
14 files changed, 102 insertions, 12 deletions
diff --git a/History.txt b/History.txt
index d301854236..51e950512f 100644
--- a/History.txt
+++ b/History.txt
@@ -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
diff --git a/Manifest.txt b/Manifest.txt
index 4b6e08319f..8ecf21693e 100644
--- a/Manifest.txt
+++ b/Manifest.txt
@@ -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
diff --git a/lib/arel/nodes.rb b/lib/arel/nodes.rb
index c43134bb50..64f2cc13fd 100644
--- a/lib/arel/nodes.rb
+++ b/lib/arel/nodes.rb
@@ -28,6 +28,7 @@ require 'arel/nodes/and'
require 'arel/nodes/function'
require 'arel/nodes/count'
require 'arel/nodes/values'
+require 'arel/nodes/named_function'
# joins
require 'arel/nodes/inner_join'
diff --git a/lib/arel/nodes/count.rb b/lib/arel/nodes/count.rb
index c6e19afb34..5c8ade1cf9 100644
--- a/lib/arel/nodes/count.rb
+++ b/lib/arel/nodes/count.rb
@@ -1,9 +1,6 @@
module Arel
module Nodes
class Count < Arel::Nodes::Function
-
- attr_accessor :distinct
-
def initialize expr, distinct = false, aliaz = nil
super(expr, aliaz)
@distinct = distinct
diff --git a/lib/arel/nodes/function.rb b/lib/arel/nodes/function.rb
index e4e45bff31..b58eba7f38 100644
--- a/lib/arel/nodes/function.rb
+++ b/lib/arel/nodes/function.rb
@@ -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
diff --git a/lib/arel/nodes/named_function.rb b/lib/arel/nodes/named_function.rb
new file mode 100644
index 0000000000..56669bf858
--- /dev/null
+++ b/lib/arel/nodes/named_function.rb
@@ -0,0 +1,12 @@
+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
diff --git a/lib/arel/visitors/depth_first.rb b/lib/arel/visitors/depth_first.rb
index ed95cad472..914b2d1999 100644
--- a/lib/arel/visitors/depth_first.rb
+++ b/lib/arel/visitors/depth_first.rb
@@ -28,6 +28,7 @@ module Arel
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 @@ module Arel
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
diff --git a/lib/arel/visitors/dot.rb b/lib/arel/visitors/dot.rb
index 3c4fe12d1f..92d05c7b67 100644
--- a/lib/arel/visitors/dot.rb
+++ b/lib/arel/visitors/dot.rb
@@ -38,13 +38,6 @@ module Arel
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 @@ module Arel
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"
diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb
index 4eae5a9ae5..d5534384f8 100644
--- a/lib/arel/visitors/to_sql.rb
+++ b/lib/arel/visitors/to_sql.rb
@@ -183,6 +183,12 @@ eowarn
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
diff --git a/test/nodes/test_named_function.rb b/test/nodes/test_named_function.rb
new file mode 100644
index 0000000000..18ecdd2851
--- /dev/null
+++ b/test/nodes/test_named_function.rb
@@ -0,0 +1,13 @@
+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
diff --git a/test/nodes/test_node.rb b/test/nodes/test_node.rb
index ffa3f273ea..b8d06b9ccc 100644
--- a/test/nodes/test_node.rb
+++ b/test/nodes/test_node.rb
@@ -11,6 +11,7 @@ module Arel
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
diff --git a/test/visitors/test_depth_first.rb b/test/visitors/test_depth_first.rb
index 306605b7c6..6d74926743 100644
--- a/test/visitors/test_depth_first.rb
+++ b/test/visitors/test_depth_first.rb
@@ -52,10 +52,16 @@ module Arel
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
diff --git a/test/visitors/test_dot.rb b/test/visitors/test_dot.rb
index 3c7da8958a..2909d87799 100644
--- a/test/visitors/test_dot.rb
+++ b/test/visitors/test_dot.rb
@@ -7,6 +7,25 @@ module Arel
@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,
diff --git a/test/visitors/test_to_sql.rb b/test/visitors/test_to_sql.rb
index 34ebb2b278..0c7baab923 100644
--- a/test/visitors/test_to_sql.rb
+++ b/test/visitors/test_to_sql.rb
@@ -15,6 +15,16 @@ module Arel
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)