diff options
-rw-r--r-- | History.txt | 1 | ||||
-rw-r--r-- | Manifest.txt | 4 | ||||
-rw-r--r-- | lib/arel/nodes.rb | 1 | ||||
-rw-r--r-- | lib/arel/nodes/count.rb | 3 | ||||
-rw-r--r-- | lib/arel/nodes/function.rb | 3 | ||||
-rw-r--r-- | lib/arel/nodes/named_function.rb | 12 | ||||
-rw-r--r-- | lib/arel/visitors/depth_first.rb | 8 | ||||
-rw-r--r-- | lib/arel/visitors/dot.rb | 25 | ||||
-rw-r--r-- | lib/arel/visitors/to_sql.rb | 6 | ||||
-rw-r--r-- | test/nodes/test_named_function.rb | 13 | ||||
-rw-r--r-- | test/nodes/test_node.rb | 1 | ||||
-rw-r--r-- | test/visitors/test_depth_first.rb | 8 | ||||
-rw-r--r-- | test/visitors/test_dot.rb | 19 | ||||
-rw-r--r-- | test/visitors/test_to_sql.rb | 10 |
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) |