Skip to content

Commit

Permalink
Subqueries in select clause (fixes activerecord-hackery#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ernie Miller committed Jun 16, 2011
1 parent 512493b commit 0c57f06
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 2 deletions.
2 changes: 2 additions & 0 deletions lib/squeel/adapters/active_record.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
ActiveRecord::Relation.send :include, Squeel::Nodes::Aliasing

case ActiveRecord::VERSION::MAJOR
when 3
case ActiveRecord::VERSION::MINOR
Expand Down
11 changes: 11 additions & 0 deletions lib/squeel/adapters/active_record/3.0/compat.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
module Arel

class SelectManager
def as other
Nodes::TableAlias.new Nodes::SqlLiteral.new(other), Nodes::Grouping.new(@ast)
end
end

class Table
alias :table_name :name

Expand Down Expand Up @@ -130,6 +136,11 @@ def visit_Arel_Nodes_Values o
end
}.join ', '})"
end

def quote_table_name name
return name if Arel::Nodes::SqlLiteral === name
@quoted_tables[name] ||= @connection.quote_table_name(name)
end
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/squeel/adapters/active_record/relation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def build_arel
end

# reverse_sql_order doesn't understand ARel ordering nodes, so we
# need to convert them to their corresponding SQL
# need to convert them to their corresponding SQL (for now)
def sqlify_order(order)
order.map do |o|
o.respond_to?(:to_sql) ? o.to_sql : o
Expand Down
3 changes: 3 additions & 0 deletions lib/squeel/nodes/as.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ module Squeel
module Nodes
# A node representing an SQL alias, which will result in same when visited.
class As < Binary
alias :expr :left
alias :alias :right

# @param left The node to be aliased
# @param right The alias name
def initialize(left, right)
Expand Down
2 changes: 1 addition & 1 deletion lib/squeel/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Squeel
VERSION = "0.8.0"
VERSION = "0.8.1"
end
9 changes: 9 additions & 0 deletions lib/squeel/visitors/attribute_visitor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ def visit_Squeel_Nodes_As(o, parent)
accept(o.left, parent).as(o.right)
end

# Visit an ActiveRecord Relation, returning an Arel::SelectManager
# @param [ActiveRecord::Relation] o The Relation to visit
# @param parent The parent object in the context
# @return [Arel::SelectManager] The ARel select manager that represents
# the relation's query
def visit_ActiveRecord_Relation(o, parent)
o.arel
end

# @return [Boolean] Whether the given value implies a context change
# @param v The value to consider
def implies_context_change?(v)
Expand Down
19 changes: 19 additions & 0 deletions spec/squeel/adapters/active_record/relation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,13 @@ module ActiveRecord
relation.first.flanderized_name.should eq 'Aric Smith-diddly'
end

it 'allows a subquery in the select values' do
subquery = Article.where(:person_id => 1).select(:id).order{id.desc}.limit(1)
relation = Person.where(:id => 1).select{[id, name, subquery.as('last_article_id')]}
aric = relation.first
aric.last_article_id.should eq Article.where(:person_id => 1).last.id
end

end

describe '#group' do
Expand Down Expand Up @@ -583,6 +590,18 @@ module ActiveRecord

end

describe '#as' do

it 'aliases the relation in an As node' do
relation = Person.where{name == 'ernie'}
node = relation.as('ernie')
node.should be_a Squeel::Nodes::As
node.expr.should eq relation
node.alias.should eq 'ernie'
end

end

describe '#merge' do

it 'merges relations with the same base' do
Expand Down
6 changes: 6 additions & 0 deletions spec/squeel/visitors/attribute_visitor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ module Visitors
ordering.direction.should eq :asc
end

it 'allows a subquery as a selection' do
relation = Person.where(:name => 'Aric Smith').select(:id)
node = @v.accept(relation.as('aric'))
node.to_sql.should be_like "(SELECT \"people\".\"id\" FROM \"people\" WHERE \"people\".\"name\" = 'Aric Smith') aric"
end

it 'creates an ARel NamedFunction node for a Function node' do
function = @v.accept(:find_in_set.func())
function.should be_a Arel::Nodes::NamedFunction
Expand Down

0 comments on commit 0c57f06

Please sign in to comment.