lib/bmg/operator/join.rb in bmg-0.17.2 vs lib/bmg/operator/join.rb in bmg-0.17.3
- old
+ new
@@ -6,20 +6,23 @@
# Natural join, following relational algebra
#
class Join
include Operator::Binary
- def initialize(type, left, right, on)
+ DEFAULT_OPTIONS = {}
+
+ def initialize(type, left, right, on, options = {})
@type = type
@left = left
@right = right
@on = on
+ @options = DEFAULT_OPTIONS.merge(options)
end
private
- attr_reader :on
+ attr_reader :on, :options
public
def each
index = Hash.new
@@ -32,18 +35,30 @@
key = tuple_project(tuple, on)
if to_join = index[key]
to_join.each do |right|
yield right.merge(tuple)
end
+ elsif left_join?
+ yield(tuple.merge(default_right_tuple))
end
end
end
def to_ast
- [ :join, left.to_ast, right.to_ast, on ]
+ [ :join, left.to_ast, right.to_ast, on, extra_opts ].compact
end
+ protected
+
+ def left_join?
+ options[:variant] == :left
+ end
+
+ def default_right_tuple
+ options[:default_right_tuple]
+ end
+
protected ### optimization
def _autowrap(type, options)
u_left, left_replaced = _unautowrap(left, options)
u_right, right_replaced = _unautowrap(right, options)
@@ -61,11 +76,16 @@
end
private :_unautowrap
protected ### inspect
+ def extra_opts
+ extra = options.dup.delete_if{|k,v| DEFAULT_OPTIONS[k] == v }
+ extra.empty? ? nil : extra
+ end
+
def args
- [ on ]
+ [ on, extra_opts ].compact
end
private
def tuple_project(tuple, on)