summaryrefslogtreecommitdiff
path: root/storage/mroonga/vendor/groonga/lib/mrb/scripts/table.rb
blob: 75c918949f0d6d6d383c88289c81d72339dc3b1d (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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
module Groonga
  class Table
    include Enumerable
    include Indexable

    def columns
      context = Context.instance
      column_ids.collect do |id|
        context[id]
      end
    end

    def each
      flags =
        TableCursorFlags::ASCENDING |
        TableCursorFlags::BY_ID
      TableCursor.open(self, :flags => flags) do |cursor|
        cursor.each do |id|
          yield(id)
        end
      end
    end

    def sort(keys, options={})
      offset = options[:offset] || 0
      limit = options[:limit] || -1
      ensure_sort_keys(keys) do |sort_keys|
        sorted = Array.create("", self)
        begin
          sort_raw(sort_keys, offset, limit, sorted)
        rescue Exception
          sorted.close
          raise
        end
        sorted
      end
    end

    def group(keys, result)
      ensure_sort_keys(keys) do |sort_keys|
        group_raw(sort_keys, result)
      end
    end

    def apply_window_function(output_column,
                              window_function_call,
                              options={})
      ensure_sort_keys_accept_nil(options[:sort_keys]) do |sort_keys|
        ensure_sort_keys_accept_nil(options[:group_keys]) do |group_keys|
          window_definition = WindowDefinition.new
          begin
            window_definition.sort_keys = sort_keys
            window_definition.group_keys = group_keys
            apply_window_function_raw(output_column,
                                      window_definition,
                                      window_function_call)
          ensure
            window_definition.close
          end
        end
      end
    end

    private
    def ensure_sort_keys_accept_nil(keys, &block)
      return yield(nil) if keys.nil?

      ensure_sort_keys(keys, &block)
    end

    def ensure_sort_keys(keys)
      if keys.is_a?(::Array) and keys.all? {|key| key.is_a?(TableSortKey)}
        return yield(keys)
      end

      converted_keys = []

      begin
        keys = [keys] unless keys.is_a?(::Array)
        sort_keys = keys.collect do |key|
          ensure_sort_key(key, converted_keys)
        end
        yield(sort_keys)
      ensure
        converted_keys.each do |converted_key|
          converted_key.close
        end
      end
    end

    def ensure_sort_key(key, converted_keys)
      return key if key.is_a?(TableSortKey)

      sort_key = TableSortKey.new
      converted_keys << sort_key

      key_name = nil
      order = :ascending
      offset = 0
      if key.is_a?(::Hash)
        key_name = key[:key]
        order    = key[:order] || order
        offset   = key[:offset] || offset
      else
        key_name = key
      end

      case key_name
      when String
        # Do nothing
      when Symbol
        key_name = key_name.to_s
      else
        message = "sort key name must be String or Symbol: " +
                  "#{key_name.inspect}: #{key.inspect}"
        raise ArgumentError, message
      end

      if key_name.start_with?("-")
        key_name[0] = ""
        order = :descending
      elsif key_name.start_with?("+")
        key_name[0] = ""
      end

      key = find_column(key_name)
      if key.nil?
        table_name = name || "(temporary)"
        message = "unknown key: #{key_name.inspect}: "
        message << "#{table_name}(#{size})"
        raise ArgumentError, message
      end

      sort_key.key = key
      if order == :ascending
        sort_key.flags = Groonga::TableSortFlags::ASCENDING
      else
        sort_key.flags = Groonga::TableSortFlags::DESCENDING
      end
      sort_key.offset = offset
      sort_key
    end
  end
end