DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Query Class

08.01.2009
| 1709 views |
  • submit to reddit
        
class Query
  attr_accessor :select, :from, :where, :vars, :group, :having, :order, :limit, :group_with_rollup
  
  def initialize(options = {})
    @select            = Array(options[:select]) || []
    @from              = Array(options[:from])   || []
    @where             = Array(options[:where])  || []
    @vars              = options[:vars]          || {}
    @group             = options[:group]         || []
    @having            = options[:having]        || []
    @order             = options[:order]         || []
    @limit             = options[:limit]
    @group_with_rollup = options[:group_with_rollup]
  end
  
  def build(clause=nil)
    return build_clause(clause) if clause
    
    stmt = []
    [:select, :from, :where, :group, :having, :order, :limit].each do |key|
      clause = build_clause(key)
      stmt << clause if clause
    end
    stmt.join("\n")
  end
  
private
  def build_clause(key)
    value = instance_variable_get("@#{key}")
    
    if value.empty?
      raise "You have not specified a 'select' clause!" if key == :select
      raise "You have not specified a 'from' clause!"   if key == :from
    end
    
    unless key == :limit
      value = Array(value).flatten.map {|v|
        v = v.strip.gsub(/([\r\n])[ ]*/m) { $1 } if v
        v.blank? ? nil : v
      }.compact
    end
    
    clause = nil
    unless value.blank?
      word = (key == :group) ? "GROUP BY" : key.to_s.upcase
      rest = case key
        when :select, :group, :having, :order
          value.join(",\n")
        when :where
          value.map {|v| "(#{v})" }.join(" AND\n")
        when :from
          value.join("\n")
        else
          value
      end
      rest = ActiveRecord::Base.send(:sanitize_sql, [rest, @vars]) if key == :where
      arr = [word, rest]
      arr << "WITH ROLLUP" if key == :group && @group_with_rollup
      clause = arr.join("\n")
    end
    clause
  end
end