class Bmg::Sql::Processor::Join

Attributes

on[R]
options[R]
right[R]

Public Class Methods

new(right, on, options, builder) click to toggle source
Calls superclass method Bmg::Sql::Processor::new
# File lib/bmg/sql/processor/join.rb, line 7
def initialize(right, on, options, builder)
  super(builder)
  @right = right
  @on = on
  @options = options
end

Public Instance Methods

call(sexpr) click to toggle source
Calls superclass method
# File lib/bmg/sql/processor/join.rb, line 15
def call(sexpr)
  if unjoinable?(sexpr)
    call(builder.from_self(sexpr))
  elsif unjoinable?(right)
    Join.new(builder.from_self(right), on, options, builder).call(sexpr)
  else
    super(sexpr)
  end
end

Private Instance Methods

apply_join_strategy(left, right) click to toggle source
# File lib/bmg/sql/processor/join.rb, line 27
def apply_join_strategy(left, right)
  [ :select_exp,
    join_set_quantifiers(left, right),
    join_select_lists(left, right),
    join_from_clauses(left, right),
    join_where_clauses(left, right),
    join_order_by_clauses(left, right) ].compact
end
coalesced(child) click to toggle source
# File lib/bmg/sql/processor/join.rb, line 92
def coalesced(child)
  drt, as_name = options[:default_right_tuple], child.as_name.to_sym
  if drt && drt.has_key?(as_name)
    child.with_update(1, [
      :func_call,
      :coalesce,
      child.left,
      [:literal, drt[as_name]]
    ])
  else
    child
  end
end
join_from_clauses(left, right) click to toggle source
# File lib/bmg/sql/processor/join.rb, line 59
def join_from_clauses(left, right)
  joincon = join_predicate(left, right, on)
  join = if left_join?
    [:left_join, left.table_spec, right.table_spec, joincon]
  elsif joincon.tautology?
    [:cross_join, left.table_spec, right.table_spec]
  else
    [:inner_join, left.table_spec, right.table_spec, joincon]
  end
  left.from_clause.with_update(-1, join)
end
join_order_by_clauses(left, right) click to toggle source
# File lib/bmg/sql/processor/join.rb, line 80
def join_order_by_clauses(left, right)
  order_by = [ left.order_by_clause, right.order_by_clause ].compact
  return order_by.first if order_by.size <= 1
  order_by.first + order_by.last.sexpr_body
end
join_select_lists(left, right) click to toggle source
# File lib/bmg/sql/processor/join.rb, line 45
def join_select_lists(left, right)
  left_list, right_list = left.select_list, right.select_list
  list = left_list.dup
  right_list.each_child do |child, index|
    next if left_list.knows?(child.as_name)
    if left_join?
      list << coalesced(child)
    else
      list << child
    end
  end
  list
end
join_set_quantifiers(left, right) click to toggle source
# File lib/bmg/sql/processor/join.rb, line 40
def join_set_quantifiers(left, right)
  left_q, right_q = left.set_quantifier, right.set_quantifier
  left_q == right_q ? left_q : builder.distinct
end
join_where_clauses(left, right) click to toggle source
# File lib/bmg/sql/processor/join.rb, line 71
def join_where_clauses(left, right)
  predicate = [ tautology, left.predicate, right.predicate ].compact
  case predicate.size
  when 1 then nil
  when 2 then [ :where_clause, predicate.last ]
  else [ :where_clause, predicate.reduce(:&) ]
  end
end
left_join?() click to toggle source
# File lib/bmg/sql/processor/join.rb, line 88
def left_join?
  options[:kind] == :left
end
unjoinable?(sexpr) click to toggle source
# File lib/bmg/sql/processor/join.rb, line 36
def unjoinable?(sexpr)
  sexpr.set_operator? or sexpr.limit_or_offset? or sexpr.group_by?
end