Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add Insertion::OrderLeft

* Handles push-down of an insertion into an order operator
  • Loading branch information...
commit cb648db05ffda643584759f4acbfd37af2c689b1 1 parent 1c5b43b
@dkubb authored
View
33 lib/veritas/optimizer/relation/operation/insertion.rb
@@ -19,6 +19,15 @@ def unwrap_left
left.operand
end
+ # Unwrap the operand from the right relation
+ #
+ # @return [Relation]
+ #
+ # @api private
+ def unwrap_right
+ right.operand
+ end
+
# Optimize when the left operand is a Rename
class RenameLeft < self
@@ -179,12 +188,34 @@ def extend_right
end # class ProjectionLeft
+ # Optimize when the left operand is an Order
+ class OrderLeft < self
+
+ # Test if the left operand is an Order
+ #
+ # @return [Boolean]
+ #
+ # @api private
+ def optimizable?
+ left.kind_of?(Veritas::Relation::Operation::Order)
+ end
+
+ # An Insertion into an Order applies to its operand
+ #
+ # @return [Veritas::Relation::Operation::Order]
+ #
+ # @api private
+ def optimize
+ unwrap_left.insert(unwrap_right).sort_by { left.directions }
+ end
+
+ end # class OrderLeft
+
Veritas::Relation::Operation::Insertion.optimizer = chain(
RenameLeft,
RestrictionLeft,
ProjectionLeft,
OrderLeft,
- OrderRight,
MaterializedOperands,
UnoptimizedOperands
)
View
56 spec/integration/veritas/relation/operation/insertion/optimize_spec.rb
@@ -110,6 +110,62 @@
end
end
+ context 'left is an order relation' do
+ let(:left) { original_left.sort_by { header } }
+ let(:right) { original_right.sort_by { header } }
+
+ it 'returns an equivalent relation to the unoptimized operation' do
+ should == object
+ end
+
+ it 'does not execute left_body#each' do
+ left_body.should_not_receive(:each)
+ subject
+ end
+
+ it 'does not execute right_body#each' do
+ right_body.should_not_receive(:each)
+ subject
+ end
+
+ it { should be_instance_of(Relation::Operation::Order) }
+
+ # check to make sure the insertion is pushed-down
+ its(:operand) { should eql(original_left.insert(original_right)) }
+
+ its(:directions) { should == header }
+
+ it_should_behave_like 'an optimize method'
+ end
+
+ context 'left is a reverse relation' do
+ let(:left) { original_left.sort_by { header }.reverse }
+ let(:right) { original_right.sort_by { header }.reverse }
+
+ it 'returns an equivalent relation to the unoptimized operation' do
+ should == object
+ end
+
+ it 'does not execute left_body#each' do
+ left_body.should_not_receive(:each)
+ subject
+ end
+
+ it 'does not execute right_body#each' do
+ right_body.should_not_receive(:each)
+ subject
+ end
+
+ it { should be_instance_of(Relation::Operation::Order) }
+
+ # check to make sure the insertion is pushed-down
+ its(:operand) { should eql(original_left.insert(original_right)) }
+
+ its(:directions) { should == [ attribute.desc ] }
+
+ it_should_behave_like 'an optimize method'
+ end
+
context 'left is a limit relation' do
let(:left) { original_left.sort_by { header }.take(1) }
let(:right) { original_right.sort_by { header }.take(1) }
View
29 spec/unit/veritas/optimizer/relation/operation/insertion/order_left/optimizable_spec.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Optimizer::Relation::Operation::Insertion::OrderLeft, '#optimizable?' do
+ subject { object.optimizable? }
+
+ let(:object) { described_class.new(relation) }
+ let(:relation) { left.insert(right) }
+ let(:base_left) { Relation.new(header, [ [ 1 ] ].each) }
+ let(:right) { Relation.new(header, [ [ 2 ] ].each) }
+ let(:header) { Relation::Header.new([ [ :id, Integer ] ]) }
+
+ before do
+ object.operation.should be_kind_of(Relation::Operation::Insertion)
+ end
+
+ context 'when the left is an order' do
+ let(:left) { base_left.sort_by { header } }
+
+ it { should be(true) }
+ end
+
+ context 'when the left is not an order' do
+ let(:left) { base_left }
+
+ it { should be(false) }
+ end
+end
View
28 spec/unit/veritas/optimizer/relation/operation/insertion/order_left/optimize_spec.rb
@@ -0,0 +1,28 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Optimizer::Relation::Operation::Insertion::OrderLeft, '#optimize' do
+ subject { object.optimize }
+
+ let(:object) { described_class.new(relation) }
+ let(:relation) { left.insert(right) }
+ let(:left) { base_left.sort_by { header } }
+ let(:right) { base_right.sort_by { header } }
+ let(:base_left) { Relation.new(header, [ [ 1 ] ].each) }
+ let(:base_right) { Relation.new(header, [ [ 2 ] ].each) }
+ let(:header) { Relation::Header.new([ attribute ]) }
+ let(:attribute) { Attribute::Integer.new(:id) }
+
+ before do
+ object.should be_optimizable
+ end
+
+ it { should be_instance_of(Relation::Operation::Order) }
+
+ # the operand is unwrapped from the left and right
+ its(:operand) { should eql(base_left.insert(base_right)) }
+
+ # the directions are used from the left operand
+ its(:directions) { should == header }
+end
View
4 veritas-optimizer.gemspec
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Dan Kubb"]
- s.date = "2012-05-24"
+ s.date = "2012-05-26"
s.description = "Optimizes veritas relations"
s.email = "dan.kubb@gmail.com"
s.extra_rdoc_files = [
@@ -318,6 +318,8 @@ Gem::Specification.new do |s|
"spec/unit/veritas/optimizer/relation/operation/binary/unoptimized_operands/optimizable_spec.rb",
"spec/unit/veritas/optimizer/relation/operation/binary/unoptimized_operands/optimize_spec.rb",
"spec/unit/veritas/optimizer/relation/operation/combination/optimize_spec.rb",
+ "spec/unit/veritas/optimizer/relation/operation/insertion/order_left/optimizable_spec.rb",
+ "spec/unit/veritas/optimizer/relation/operation/insertion/order_left/optimize_spec.rb",
"spec/unit/veritas/optimizer/relation/operation/insertion/projection_left/optimizable_spec.rb",
"spec/unit/veritas/optimizer/relation/operation/insertion/projection_left/optimize_spec.rb",
"spec/unit/veritas/optimizer/relation/operation/insertion/rename_left/optimizable_spec.rb",
Please sign in to comment.
Something went wrong with that request. Please try again.