diff options
-rw-r--r-- | lib/arel/nodes.rb | 1 | ||||
-rw-r--r-- | lib/arel/nodes/having.rb | 11 | ||||
-rw-r--r-- | lib/arel/nodes/select_core.rb | 3 | ||||
-rw-r--r-- | lib/arel/select_manager.rb | 5 | ||||
-rw-r--r-- | lib/arel/table.rb | 4 | ||||
-rw-r--r-- | lib/arel/visitors/to_sql.rb | 7 | ||||
-rw-r--r-- | spec/arel/table_spec.rb | 9 |
7 files changed, 39 insertions, 1 deletions
diff --git a/lib/arel/nodes.rb b/lib/arel/nodes.rb index 28b9e61fb6..4c24acb16a 100644 --- a/lib/arel/nodes.rb +++ b/lib/arel/nodes.rb @@ -7,6 +7,7 @@ require 'arel/nodes/in' require 'arel/nodes/count' require 'arel/nodes/sum' require 'arel/nodes/max' +require 'arel/nodes/having' require 'arel/nodes/sql_literal' require 'arel/nodes/select_core' require 'arel/nodes/select_statement' diff --git a/lib/arel/nodes/having.rb b/lib/arel/nodes/having.rb new file mode 100644 index 0000000000..1944a84391 --- /dev/null +++ b/lib/arel/nodes/having.rb @@ -0,0 +1,11 @@ +module Arel + module Nodes + class Having + attr_accessor :expr + + def initialize expr + @expr = expr + end + end + end +end diff --git a/lib/arel/nodes/select_core.rb b/lib/arel/nodes/select_core.rb index 6e85968b31..e52db6eb77 100644 --- a/lib/arel/nodes/select_core.rb +++ b/lib/arel/nodes/select_core.rb @@ -2,12 +2,14 @@ module Arel module Nodes class SelectCore attr_reader :froms, :projections, :wheres, :groups + attr_accessor :having def initialize @froms = [] @projections = [] @wheres = [] @groups = [] + @having = nil end def initialize_copy other @@ -16,6 +18,7 @@ module Arel @projections = @projections.clone @wheres = @wheres.clone @group = @groups.clone + @having = @having.clone if @having end end end diff --git a/lib/arel/select_manager.rb b/lib/arel/select_manager.rb index d8e113d5ee..4ddae13aa4 100644 --- a/lib/arel/select_manager.rb +++ b/lib/arel/select_manager.rb @@ -40,6 +40,11 @@ module Arel end end + def having expr + @ctx.having = Nodes::Having.new(expr) + self + end + def project *projections # FIXME: converting these to SQLLiterals is probably not good, but # rails tests require it. diff --git a/lib/arel/table.rb b/lib/arel/table.rb index 5d8f7c1ae5..ce21457e60 100644 --- a/lib/arel/table.rb +++ b/lib/arel/table.rb @@ -61,6 +61,10 @@ module Arel tm.take amount end + def having expr + tm.having expr + end + def columns @columns ||= @engine.connection.columns(@name, "#{@name} Columns").map do |column| Attributes.for(column).new self, column.name, column diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb index e1cf0f3778..48c8c492e0 100644 --- a/lib/arel/visitors/to_sql.rb +++ b/lib/arel/visitors/to_sql.rb @@ -57,10 +57,15 @@ module Arel "SELECT #{o.projections.map { |x| visit x }.join ', '}", ("FROM #{o.froms.map { |x| visit x }.join ', ' }" unless o.froms.empty?), ("WHERE #{o.wheres.map { |x| visit x }.join ' AND ' }" unless o.wheres.empty?), - ("GROUP BY #{o.groups.map { |x| visit x }.join ', ' }" unless o.groups.empty?) + ("GROUP BY #{o.groups.map { |x| visit x }.join ', ' }" unless o.groups.empty?), + (visit(o.having) if o.having), ].compact.join ' ' end + def visit_Arel_Nodes_Having o + "HAVING #{visit o.expr}" + end + def visit_Arel_Nodes_Group o visit o.expr end diff --git a/spec/arel/table_spec.rb b/spec/arel/table_spec.rb index e67c371577..46d9dbddf4 100644 --- a/spec/arel/table_spec.rb +++ b/spec/arel/table_spec.rb @@ -6,6 +6,15 @@ module Arel @relation = Table.new(:users) end + describe 'having' do + it 'adds a having clause' do + mgr = @relation.having @relation[:id].eq(10) + mgr.to_sql.should be_like %{ + SELECT FROM "users" HAVING "users"."id" = 10 + } + end + end + describe 'backwards compat' do describe 'joins' do it 'returns nil' do |