Skip to content

Commit

Permalink
Add support for counting rows with conditions or limit using a subquery.
Browse files Browse the repository at this point in the history
  • Loading branch information
miloops committed Jun 23, 2010
1 parent f681150 commit 71e9299
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 6 deletions.
23 changes: 17 additions & 6 deletions lib/arel/engines/sql/relations/compiler.rb
Expand Up @@ -8,17 +8,28 @@ def initialize(relation)
end

def select_sql
query = build_query \
"SELECT #{select_clauses.join(', ')}",
"FROM #{from_clauses}",
if relation.projections.first.is_a?(Count) && relation.projections.size == 1 && (taken.present? || wheres.present?)
subquery = build_query("SELECT 1 FROM #{from_clauses}", build_clauses)
query = "SELECT #{select_clauses.join(', ')} FROM (#{subquery})"
else
query = build_query \
"SELECT #{select_clauses.join(', ')}",
"FROM #{from_clauses}",
build_clauses
end
query
end

def build_clauses
clauses = build_query "",
(joins(self) unless joins(self).blank? ),
("WHERE #{where_clauses.join(' AND ')}" unless wheres.blank? ),
("GROUP BY #{group_clauses.join(', ')}" unless groupings.blank? ),
("HAVING #{having_clauses.join(' AND ')}" unless havings.blank? ),
("ORDER BY #{order_clauses.join(', ')}" unless orders.blank? )
engine.add_limit_offset!(query,{ :limit => taken, :offset => skipped }) if taken || skipped
query << " #{locked}" unless locked.blank?
query
clauses << " #{locked}" unless locked.blank?
engine.add_limit_offset!(clauses,{ :limit => taken, :offset => skipped }) if taken || skipped
clauses unless clauses.blank?
end

def delete_sql
Expand Down
18 changes: 18 additions & 0 deletions spec/engines/sql/unit/relations/take_spec.rb
Expand Up @@ -52,6 +52,24 @@ module Arel
})
end
end

it "manufactures count sql with limit" do
sql = Take.new(@relation.project(@relation[:id].count), @taken).to_sql

adapter_is :mysql do
sql.should be_like(%Q{
SELECT COUNT(`users`.`id`) AS count_id
FROM (SELECT 1 FROM `users` LIMIT 4)
})
end

adapter_is_not :mysql, :oracle do
sql.should be_like(%Q{
SELECT COUNT("users"."id") AS count_id
FROM (SELECT 1 FROM "users" LIMIT 4)
})
end
end
end
end
end

0 comments on commit 71e9299

Please sign in to comment.