Kouhei Sutou
null+****@clear*****
Mon Jun 29 00:25:08 JST 2015
Kouhei Sutou 2015-06-29 00:25:08 +0900 (Mon, 29 Jun 2015) New Revision: 6629adb6c03fe1b83588d339828cc0c4952065f5 https://github.com/groonga/groonga/commit/6629adb6c03fe1b83588d339828cc0c4952065f5 Message: mrb: define Groonga::Table#sort in mruby Added files: lib/mrb/scripts/table.rb Modified files: lib/mrb/mrb_table.c lib/mrb/scripts/initialize/post.rb lib/mrb/scripts/sources.am Modified: lib/mrb/mrb_table.c (+14 -68) =================================================================== --- lib/mrb/mrb_table.c 2015-06-29 00:24:10 +0900 (9dc4ee8) +++ lib/mrb/mrb_table.c 2015-06-29 00:25:08 +0900 (7d245cf) @@ -157,22 +157,21 @@ mrb_grn_table_select(mrb_state *mrb, mrb_value self) return grn_mrb_value_from_grn_obj(mrb, result); } -/* TODO: Fix memory leak on error */ static mrb_value -mrb_grn_table_sort(mrb_state *mrb, mrb_value self) +mrb_grn_table_sort_raw(mrb_state *mrb, mrb_value self) { grn_ctx *ctx = (grn_ctx *)mrb->ud; grn_obj *table; - grn_obj *result = NULL; + mrb_value mrb_keys; grn_table_sort_key *keys; int i, n_keys; - int offset = 0; - int limit = -1; - mrb_value mrb_keys; - mrb_value mrb_options = mrb_nil_value(); + mrb_int offset; + mrb_int limit; + mrb_value mrb_result; + grn_obj *result; table = DATA_PTR(self); - mrb_get_args(mrb, "o|H", &mrb_keys, &mrb_options); + mrb_get_args(mrb, "oiio", &mrb_keys, &offset, &limit, &mrb_result); mrb_keys = mrb_convert_type(mrb, mrb_keys, MRB_TT_ARRAY, "Array", "to_ary"); @@ -180,69 +179,16 @@ mrb_grn_table_sort(mrb_state *mrb, mrb_value self) n_keys = RARRAY_LEN(mrb_keys); keys = GRN_MALLOCN(grn_table_sort_key, n_keys); for (i = 0; i < n_keys; i++) { - mrb_value mrb_sort_options; - mrb_value mrb_sort_key; - mrb_value mrb_sort_order; - - mrb_sort_options = RARRAY_PTR(mrb_keys)[i]; - mrb_sort_key = grn_mrb_options_get_lit(mrb, mrb_sort_options, "key"); - switch (mrb_type(mrb_sort_key)) { - case MRB_TT_STRING : - keys[i].key = grn_obj_column(ctx, table, - RSTRING_PTR(mrb_sort_key), - RSTRING_LEN(mrb_sort_key)); - break; - case MRB_TT_SYMBOL : - { - const char *name; - mrb_int name_length; - name = mrb_sym2name_len(mrb, mrb_symbol(mrb_sort_key), &name_length); - keys[i].key = grn_obj_column(ctx, table, name, name_length); - } - break; - default : - /* TODO: free */ - mrb_raisef(mrb, E_ARGUMENT_ERROR, - "sort key must be string or symbol: %S", - mrb_sort_key); - break; - } - - keys[i].flags = 0; - mrb_sort_order = grn_mrb_options_get_lit(mrb, mrb_sort_options, "order"); - if (mrb_nil_p(mrb_sort_order) || - (mrb_symbol(mrb_sort_order) == mrb_intern_lit(mrb, "ascending"))) { - keys[i].flags |= GRN_TABLE_SORT_ASC; - } else { - keys[i].flags |= GRN_TABLE_SORT_DESC; - } + memcpy(&(keys[i]), + DATA_PTR(RARRAY_PTR(mrb_keys)[i]), + sizeof(grn_table_sort_key)); } - - if (!mrb_nil_p(mrb_options)) { - mrb_value mrb_offset; - mrb_value mrb_limit; - - mrb_offset = grn_mrb_options_get_lit(mrb, mrb_options, "offset"); - if (!mrb_nil_p(mrb_offset)) { - offset = mrb_fixnum(mrb_offset); - } - - mrb_limit = grn_mrb_options_get_lit(mrb, mrb_options, "limit"); - if (!mrb_nil_p(mrb_limit)) { - limit = mrb_fixnum(mrb_limit); - } - } - - result = grn_table_create(ctx, NULL, 0, NULL, GRN_TABLE_NO_KEY, - NULL, table); + result = DATA_PTR(mrb_result); grn_table_sort(ctx, table, offset, limit, result, keys, n_keys); - for (i = 0; i < n_keys; i++) { - grn_obj_unlink(ctx, keys[i].key); - } GRN_FREE(keys); grn_mrb_ctx_check(mrb); - return grn_mrb_value_from_grn_obj(mrb, result); + return mrb_result; } static mrb_value @@ -343,8 +289,8 @@ grn_mrb_table_init(grn_ctx *ctx) mrb_define_method(mrb, klass, "select", mrb_grn_table_select, MRB_ARGS_ARG(1, 1)); - mrb_define_method(mrb, klass, "sort", - mrb_grn_table_sort, MRB_ARGS_ARG(1, 1)); + mrb_define_method(mrb, klass, "sort_raw", + mrb_grn_table_sort_raw, MRB_ARGS_REQ(4)); mrb_define_method(mrb, klass, "delete", mrb_grn_table_delete, MRB_ARGS_REQ(1)); Modified: lib/mrb/scripts/initialize/post.rb (+1 -0) =================================================================== --- lib/mrb/scripts/initialize/post.rb 2015-06-29 00:24:10 +0900 (ea26a03) +++ lib/mrb/scripts/initialize/post.rb 2015-06-29 00:25:08 +0900 (ccd4475) @@ -6,6 +6,7 @@ require "writer" require "object" require "database" +require "table" require "index_column" require "command" require "table_cursor" Modified: lib/mrb/scripts/sources.am (+1 -0) =================================================================== --- lib/mrb/scripts/sources.am 2015-06-29 00:24:10 +0900 (5ddcba1) +++ lib/mrb/scripts/sources.am 2015-06-29 00:25:08 +0900 (6fda018) @@ -19,5 +19,6 @@ RUBY_SCRIPT_FILES = \ scan_info_builder.rb \ scan_info_data.rb \ scan_info_search_index.rb \ + table.rb \ table_cursor.rb \ writer.rb Added: lib/mrb/scripts/table.rb (+77 -0) 100644 =================================================================== --- /dev/null +++ lib/mrb/scripts/table.rb 2015-06-29 00:25:08 +0900 (0c81404) @@ -0,0 +1,77 @@ +module Groonga + class Table + 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 + + private + 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 + + sort_key.key = find_column(key_name) + 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 -------------- next part -------------- HTML����������������������������... Download