class Qdsl::Select

Attributes

source[R]

Public Class Methods

new(column_set) click to toggle source
# File lib/select.rb, line 5
def initialize(column_set)
  @column_set = column_set
  @inner_joins = []
end

Public Instance Methods

add_inner_join(source, predicate_block) click to toggle source
# File lib/select.rb, line 38
def add_inner_join(source, predicate_block)
  @inner_joins << InnerJoin.new(source, predicate_block)
  self
end
create_query() click to toggle source
# File lib/select.rb, line 34
def create_query
  SelectQuery.new(self, @column_set)
end
from(source) click to toggle source
# File lib/select.rb, line 10
def from(source)
  @source = source
  self
end
inner_join(source) click to toggle source
# File lib/select.rb, line 30
def inner_join(source)
  InnerJoinBuilder.new(self, source)
end
limit(count) click to toggle source
# File lib/select.rb, line 25
def limit(count)
  @count = count
  self
end
order_by(*columns, &block) click to toggle source
# File lib/select.rb, line 20
def order_by(*columns, &block)
  @order_by_column_set = ColumnSet.new(columns, block)
  self
end
render(context = nil, depth = 0, id = nil) click to toggle source
# File lib/select.rb, line 43
def render(context = nil, depth = 0, id = nil)
  raise 'No FROM clause was specified' unless @source

  indent = '  ' * depth

  context ||= Context.new

  parameters = {}

  source_query = @source.create_query
  source_query_id = context.create_id
  source_result = source_query.render(context, depth + 1, source_query_id)

  inner_join_fragments = []
  inner_join_results = []
  @inner_joins.each do |inner_join|
    inner_join_query = inner_join.source.create_query
    inner_join_query_id = context.create_id
    inner_join_result = inner_join_query.render(context, depth + 1, inner_join_query_id)
    inner_join_results << inner_join_result
    x = ColumnProxy.new(source_result)
    y = ColumnProxy.new(inner_join_result)
    predicate = inner_join.predicate_block.call(x, y)

    # Should just use id attribute instead of passing dictionary!
    bah = {
      source_result => source_result.id,
      inner_join_result => inner_join_result.id,
    }

    predicate_result = predicate.render_sql(context, bah)

    inner_join_fragments << "#{indent}INNER JOIN #{inner_join_result.sql}"
    inner_join_fragments << "#{indent}ON #{predicate_result.sql}\n"
  end

  columns = @column_set.capture(source_result, inner_join_results)

  column_results = columns.collect { |x| x.render_sql(context, x.source.id) }

  fragments = []

  fragments << "#{indent}SELECT\n"
  column_results.each_with_index do |column_result, index|
    fragments << "#{indent}  #{column_result.sql}#{index < column_results.size - 1 ? ',' : ''}\n"
  end

  fragments << "#{indent}FROM #{source_result.sql}"

  fragments += inner_join_fragments

  if @where_predicate_block
    blah = [source_result] + inner_join_results
    proxies = blah.collect { |x| ColumnProxy.new(x) }
    where_predicate = @where_predicate_block.call(Util::fix_block_params(proxies))

    # Should just use id attribute instead of passing dictionary!
    bah = blah.inject({}) { |acc, x| acc[x] = x.id; acc }

    where_predicate_result = where_predicate.render_sql(context, bah)
    parameters.merge!(where_predicate_result.parameters)

    fragments << "#{indent}WHERE #{where_predicate_result.sql}\n"
  end

  if @order_by_column_set
    order_by_columns = @order_by_column_set.capture(source_result, inner_join_results)
    order_by_column_results = order_by_columns.collect { |x| x.render_sql(context, x.source.id) }
    fragments << "#{indent}ORDER BY #{order_by_column_results.collect(&:sql).join(', ')}\n"
  end

  if @count
    fragments << "LIMIT #{@count}"
  end

  sql = fragments.join
  RenderResult.new(
    id,
    sql,
    columns.collect(&:name),
    parameters
  )
end
where(&predicate_block) click to toggle source
# File lib/select.rb, line 15
def where(&predicate_block)
  @where_predicate_block = predicate_block
  self
end