Use Arel to build subquery. Adapt tests to changed fixtures.

This commit is contained in:
John Mileham 2011-03-24 15:09:24 -04:00
parent b44a0ec153
commit 28c73f0123
2 changed files with 14 additions and 15 deletions

@ -183,13 +183,10 @@ def perform_calculation(operation, column_name, options = {})
end
end
def aggregate_column(column_name, subquery_alias = nil)
def aggregate_column(column_name)
if @klass.column_names.include?(column_name.to_s)
Arel::Attribute.new(subquery_alias || @klass.unscoped.table, column_name)
Arel::Attribute.new(@klass.unscoped.table, column_name)
else
if subquery_alias && (split_name = column_name.to_s.split(".")).length > 1
column_name = split_name.last
end
Arel.sql(column_name == :all ? "*" : column_name.to_s)
end
end
@ -315,14 +312,16 @@ def select_for_count
end
def build_count_subquery(relation, column_name, distinct)
# Arel doesn't do subqueries
subquery_alias = arel_table.alias("subquery_for_count")
aliased_column = aggregate_column(column_name, subquery_alias)
select_value = operation_over_aggregate_column(aliased_column, 'count', distinct)
column_alias = Arel.sql('count_column')
subquery_alias = Arel.sql('subquery_for_count')
relation.select_values = [(column_name == :all ? 1 : aggregate_column(column_name))]
subquery_sql = "(#{relation.arel.to_sql}) #{subquery_alias.name}"
subquery_alias.relation.select_manager.project(select_value).from(subquery_sql)
aliased_column = aggregate_column(column_name == :all ? 1 : column_name).as(column_alias)
relation.select_values = [aliased_column]
subquery = relation.arel.as(subquery_alias)
sm = Arel::SelectManager.new relation.engine
select_value = operation_over_aggregate_column(column_alias, 'count', distinct)
sm.project(select_value).from(subquery)
end
end
end

@ -667,14 +667,14 @@ def test_size
end
def test_size_with_limit
posts = Post.limit(6)
posts = Post.limit(10)
assert_queries(1) { assert_equal 6, posts.size }
assert_queries(1) { assert_equal 10, posts.size }
assert ! posts.loaded?
best_posts = posts.where(:comments_count => 0)
best_posts.to_a # force load
assert_no_queries { assert_equal 5, best_posts.size }
assert_no_queries { assert_equal 9, best_posts.size }
end
def test_size_with_zero_limit