summaryrefslogtreecommitdiffstats
path: root/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/binary_operation.rb
blob: d59c65c786184bd2ef5047b5376e9990a03f6828 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
module Groonga
  module ExpressionTree
    class BinaryOperation
      attr_reader :operator
      attr_reader :left
      attr_reader :right
      def initialize(operator, left, right)
        @operator = operator
        @left = left
        @right = right
      end

      def build(expression)
        @left.build(expression)
        @right.build(expression)
        expression.append_operator(@operator, 2)
      end

      RANGE_OPERATORS = [
        Operator::LESS,
        Operator::GREATER,
        Operator::LESS_EQUAL,
        Operator::GREATER_EQUAL,
      ]
      def estimate_size(table)
        case @operator
        when *RANGE_OPERATORS
          estimate_size_range(table)
        else
          table.size
        end
      end

      private
      def estimate_size_range(table)
        return table.size unless @left.is_a?(Variable)
        return table.size unless @right.is_a?(Constant)

        column = @left.column
        value = @right.value
        index_info = column.find_index(@operator)
        return table.size if index_info.nil?

        index_column = index_info.index
        lexicon = index_column.lexicon
        options = {}
        case @operator
        when Operator::LESS
          options[:max] = value
          options[:flags] = TableCursorFlags::LT
        when Operator::LESS_EQUAL
          options[:max] = value
          options[:flags] = TableCursorFlags::LE
        when Operator::GREATER
          options[:min] = value
          options[:flags] = TableCursorFlags::GT
        when Operator::GREATER_EQUAL
          options[:min] = value
          options[:flags] = TableCursorFlags::GE
        end
        TableCursor.open(lexicon, options) do |cursor|
          index_column.estimate_size(:lexicon_cursor => cursor)
        end
      end
    end
  end
end