Skip to content

Instantly share code, notes, and snippets.

@DBA
Created August 3, 2010 20:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DBA/507110 to your computer and use it in GitHub Desktop.
Save DBA/507110 to your computer and use it in GitHub Desktop.
module Arel
module SqlCompiler
class GenericCompiler
def select_sql
projections = @relation.projections
@engine = engine
if Count === projections.first && projections.size == 1 &&
(relation.taken.present? || relation.wheres.present?) && relation.joins(self).blank?
subquery = [
"SELECT 1 FROM #{relation.send(:from_clauses)}", build_clauses
].join ' '
query = "SELECT COUNT(*) AS count_id FROM (#{subquery}) AS subquery"
else
query = [
"SELECT #{relation.send(:select_clauses).join(', ')}",
"FROM #{relation.send(:from_clauses)}",
build_clauses
].compact.join ' '
end
query
end
def build_clauses
joins = relation.joins(self)
wheres = relation.send(:where_clauses)
groups = relation.send(:group_clauses)
havings = relation.send(:having_clauses)
orders = relation.send(:order_clauses)
clauses = [ "",
joins,
("WHERE #{wheres.join(' AND ')}" unless wheres.empty?),
("GROUP BY #{groups.join(', ')}" unless groups.empty?),
("HAVING #{havings.join(' AND ')}" unless havings.empty?),
("ORDER BY #{orders.join(', ')}" unless orders.empty?)
].compact.join ' '
offset = relation.skipped
limit = relation.taken
@engine.connection.add_limit_offset!(clauses, :limit => limit,
:offset => offset) if offset || limit
clauses << " #{locked}" unless locked.blank?
clauses unless clauses.blank?
end
end
end
end
module ActiveRecord
module Calculations
def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
column = if @klass.column_names.include?(column_name.to_s)
Arel::Attribute.new(@klass.unscoped, column_name)
else
Arel::SqlLiteral.new(column_name == :all ? "*" : column_name.to_s)
end
# Postgresql doesn't like ORDER BY when there are no GROUP BY
if engine.adapter_name == 'PostgreSQL'
relation = except(:order).select(operation == 'count' ? column.count(distinct) : column.send(operation))
else
relation = select(operation == 'count' ? column.count(distinct) : column.send(operation))
end
type_cast_calculated_value(@klass.connection.select_value(relation.to_sql), column_for(column_name), operation)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment