dkubb/axiom-optimizer

View on GitHub
lib/axiom/optimizer/relation/operation/limit.rb

Summary

Maintainability
A
0 mins
Test Coverage
# encoding: utf-8

module Axiom
  class Optimizer
    module Relation
      module Operation

        # Abstract base class representing Limit optimizations
        class Limit < Unary

        private

          # Return the operation limit
          #
          # @return [Integer]
          #
          # @api private
          def limit
            operation.limit
          end

          # Optimize when the limit is zero
          class ZeroLimit < self

            # Test if the limit is zero
            #
            # @return [Boolean]
            #
            # @api private
            def optimizable?
              limit.zero?
            end

            # A Limit with a limit of zero is empty
            #
            # @return [Relation::Empty]
            #
            # @api private
            def optimize
              Axiom::Relation::Empty.new(operation.header)
            end

          end # class ZeroLimit

          # Optimize when the operand is a Limit and the limits are equal
          class EqualLimitOperand < self

            # Test if the operand is a Limit and the limits are equal
            #
            # @return [Boolean]
            #
            # @api private
            def optimizable?
              operand.kind_of?(operation.class) && equal_limit?
            end

            # Flatten equal Limit relations into a single relation
            #
            # @return [Projection]
            #
            # @api private
            def optimize
              operand
            end

          private

            # Test if the operation and operand limits are equal
            #
            # @return [Boolean]
            #
            # @api private
            def equal_limit?
              limit == operand.limit
            end

          end # class EqualLimitOperand

          # Optimize when the operand is a Limit
          class LimitOperand < self

            # Test if the operand is a Limit
            #
            # @return [Boolean]
            #
            # @api private
            def optimizable?
              operand.kind_of?(operation.class)
            end

            # Flatten Limit operations using the minimum limit
            #
            # @return [Boolean]
            #
            # @api private
            def optimize
              operand.operand.take(min_limit)
            end

          private

            # Return the minimum limit between the operation and operand
            #
            # @return [Integer]
            #
            # @api private
            def min_limit
              [limit, operand.limit].min
            end

          end # class LimitOperand

          # Optimize when operand is optimizable
          class UnoptimizedOperand < self
            include Function::Unary::UnoptimizedOperand

            # Return a Limit with an optimized operand
            #
            # @return [Limit]
            #
            # @api private
            def optimize
              operand.take(limit)
            end

          end # class UnoptimizedOperand

          Axiom::Relation::Operation::Limit.optimizer = chain(
            ZeroLimit,
            EqualLimitOperand,
            LimitOperand,
            EmptyOperand,
            MaterializedOperand,
            UnoptimizedOperand
          )

        end # class Limit
      end # module Operation
    end # module Relation
  end # class Optimizer
end # module Axiom