lib/axiom/algebra/product.rb
# encoding: utf-8
module Axiom
module Algebra
# The cartesian product between relations
class Product < Relation
include Relation::Operation::Combination
# Instantiate a new Product
#
# @example
# product = Product.new(left, right)
#
# @param [Relation] left
# @param [Relation] right
#
# @return [Join]
#
# @api public
def self.new(left, right)
assert_disjointed_headers(left, right)
super
end
# Assert the headers do not have common attributes
#
# @param [Relation] left
# @param [Relation] right
#
# @return [undefined]
#
# @raise [InvalidHeaderError]
# raised if there are common attributes between the headers
#
# @api private
def self.assert_disjointed_headers(left, right)
if (left.header & right.header).any?
fail InvalidHeaderError, 'the headers must be disjointed'
end
end
private_class_method :assert_disjointed_headers
# Iterate over each tuple in the set
#
# @example
# product = Product.new(left, right)
# product.each { |tuple| ... }
#
# @yield [tuple]
#
# @yieldparam [Tuple] tuple
# each tuple in the set
#
# @return [self]
#
# @api public
def each(&block)
return to_enum unless block_given?
util = Relation::Operation::Combination
left.each do |left_tuple|
util.combine_tuples(header, left_tuple, right, &block)
end
self
end
# Raise an exception when inserting into the Product
#
# @example
# product.insert(other) # => ImmutableRelationError raised
#
# @return [undefined]
#
# @raise [ImmutableRelationError]
# raised when inserting into the product
#
# @api public
def insert(*)
fail ImmutableRelationError, 'inserting into a product is impossible'
end
# Raise an exception when deleting from the Product
#
# @example
# product.delete(other) # => ImmutableRelationError raised
#
# @return [undefined]
#
# @raise [ImmutableRelationError]
# raised when deleting from the product
#
# @api public
def delete(*)
fail ImmutableRelationError, 'deleting from a product is impossible'
end
module Methods
extend Aliasable
inheritable_alias(:* => :product)
# Return a relation that is the cartesian product of two relations
#
# @example
# product = relation.product(other)
#
# @param [Relation] other
# the other relation to find the product with
#
# @return [Product]
#
# @api public
def product(other)
Product.new(self, other)
end
end # module Methods
Relation.class_eval { include Methods }
end # class Product
end # module Algebra
end # module Axiom