Skip to content

Commit

Permalink
Add #extract, which produces ANSI SQL function EXTRACT(<field> from <…
Browse files Browse the repository at this point in the history
…expr>).
  • Loading branch information
Alexander Staubo committed Feb 23, 2012
1 parent a1a6fbc commit 2db4ec6
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 0 deletions.
4 changes: 4 additions & 0 deletions lib/arel/expressions.rb
Expand Up @@ -19,5 +19,9 @@ def minimum
def average def average
Nodes::Avg.new [self], Nodes::SqlLiteral.new('avg_id') Nodes::Avg.new [self], Nodes::SqlLiteral.new('avg_id')
end end

def extract field
Nodes::Extract.new [self], field
end
end end
end end
1 change: 1 addition & 0 deletions lib/arel/nodes.rb
Expand Up @@ -36,6 +36,7 @@
# We should make Function a Unary node and deprecate the use of "aliaz" # We should make Function a Unary node and deprecate the use of "aliaz"
require 'arel/nodes/function' require 'arel/nodes/function'
require 'arel/nodes/count' require 'arel/nodes/count'
require 'arel/nodes/extract'
require 'arel/nodes/values' require 'arel/nodes/values'
require 'arel/nodes/named_function' require 'arel/nodes/named_function'


Expand Down
23 changes: 23 additions & 0 deletions lib/arel/nodes/extract.rb
@@ -0,0 +1,23 @@
module Arel
module Nodes

class Extract < Arel::Nodes::Unary
include Arel::Expression
include Arel::Predications

attr_accessor :field
attr_accessor :alias

def initialize expr, field, aliaz = nil
super(expr)
@field = field
@alias = aliaz && SqlLiteral.new(aliaz)
end

def as aliaz
self.alias = SqlLiteral.new(aliaz)
self
end
end
end
end
6 changes: 6 additions & 0 deletions lib/arel/visitors/dot.rb
Expand Up @@ -103,6 +103,12 @@ def function o
alias :visit_Arel_Nodes_Avg :function alias :visit_Arel_Nodes_Avg :function
alias :visit_Arel_Nodes_Sum :function alias :visit_Arel_Nodes_Sum :function


def extract o
visit_edge o, "expressions"
visit_edge o, "alias"
end
alias :visit_Arel_Nodes_Extract :extract

def visit_Arel_Nodes_NamedFunction o def visit_Arel_Nodes_NamedFunction o
visit_edge o, "name" visit_edge o, "name"
visit_edge o, "expressions" visit_edge o, "expressions"
Expand Down
4 changes: 4 additions & 0 deletions lib/arel/visitors/to_sql.rb
Expand Up @@ -272,6 +272,10 @@ def visit_Arel_Nodes_NamedFunction o
}.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}" }.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
end end


def visit_Arel_Nodes_Extract o
"EXTRACT(#{o.field.to_s.upcase} FROM #{visit o.expr})#{o.alias ? " AS #{visit o.alias}" : ''}"
end

def visit_Arel_Nodes_Count o def visit_Arel_Nodes_Count o
"COUNT(#{o.distinct ? 'DISTINCT ' : ''}#{o.expressions.map { |x| "COUNT(#{o.distinct ? 'DISTINCT ' : ''}#{o.expressions.map { |x|
visit x visit x
Expand Down
19 changes: 19 additions & 0 deletions test/nodes/test_extract.rb
@@ -0,0 +1,19 @@
require 'helper'

describe Arel::Nodes::Extract do
it "should extract field" do
table = Arel::Table.new :users
table[:timestamp].extract('date').to_sql.must_be_like %{
EXTRACT(DATE FROM "users"."timestamp")
}
end

describe "as" do
it 'should alias the extract' do
table = Arel::Table.new :users
table[:timestamp].extract('date').as('foo').to_sql.must_be_like %{
EXTRACT(DATE FROM "users"."timestamp") AS foo
}
end
end
end

0 comments on commit 2db4ec6

Please sign in to comment.