Kouhei Sutou
null+****@clear*****
Tue Feb 7 19:54:49 JST 2017
Kouhei Sutou 2017-02-07 19:54:49 +0900 (Tue, 07 Feb 2017) New Revision: 9a7b309c7beaddfb41a369a5d9c90ab64134cfe9 https://github.com/ranguba/rroonga/commit/9a7b309c7beaddfb41a369a5d9c90ab64134cfe9 Message: Support opening index cursor by term ID Modified files: ext/groonga/rb-grn-index-column.c ext/groonga/rb-grn-inverted-index-cursor.c ext/groonga/rb-grn.h ext/groonga/rb-groonga.c test/test-index-cursor.rb Modified: ext/groonga/rb-grn-index-column.c (+47 -12) =================================================================== --- ext/groonga/rb-grn-index-column.c 2017-02-07 17:52:47 +0900 (41e1d3b) +++ ext/groonga/rb-grn-index-column.c 2017-02-07 19:54:49 +0900 (de9600f) @@ -933,6 +933,12 @@ rb_grn_index_column_medium_p (VALUE self) return CBOOL2RVAL(flags & GRN_OBJ_INDEX_MEDIUM); } +static VALUE +call_close (VALUE object) +{ + return rb_funcall(object, rb_intern("close"), 0); +} + /* * Opens cursor to iterate posting in the index column. * @@ -959,12 +965,12 @@ rb_grn_index_column_open_cursor (int argc, VALUE *argv, VALUE self) grn_obj *column; grn_column_flags column_flags; grn_obj *range_object; - grn_table_cursor *table_cursor; + grn_table_cursor *table_cursor = NULL; + grn_id term_id = GRN_ID_NIL; grn_id rid_min = GRN_ID_NIL; grn_id rid_max = GRN_ID_MAX; int flags = 0; - grn_obj *index_cursor; - VALUE rb_table_cursor; + VALUE rb_table_cursor_or_term_id; VALUE options; VALUE rb_with_section, rb_with_weight, rb_with_position; VALUE rb_table; @@ -977,16 +983,20 @@ rb_grn_index_column_open_cursor (int argc, VALUE *argv, VALUE self) NULL, &range_object, NULL, NULL); - rb_scan_args(argc, argv, "11", &rb_table_cursor, &options); + rb_scan_args(argc, argv, "11", &rb_table_cursor_or_term_id, &options); rb_grn_scan_options(options, "with_section", &rb_with_section, "with_weight", &rb_with_weight, "with_position", &rb_with_position, NULL); - table_cursor = RVAL2GRNTABLECURSOR(rb_table_cursor, NULL); + if (CBOOL2RVAL(rb_obj_is_kind_of(rb_table_cursor_or_term_id, rb_cInteger))) { + term_id = NUM2UINT(rb_table_cursor_or_term_id); + } else { + table_cursor = RVAL2GRNTABLECURSOR(rb_table_cursor_or_term_id, NULL); + } rb_table = GRNOBJECT2RVAL(Qnil, context, range_object, GRN_FALSE); - rb_lexicon = rb_iv_get(rb_table_cursor, "@table"); + rb_lexicon = rb_funcall(self, rb_intern("table"), 0); column_flags = grn_column_get_flags(context, column); @@ -1003,18 +1013,43 @@ rb_grn_index_column_open_cursor (int argc, VALUE *argv, VALUE self) } if (NIL_P(rb_with_position)) { - flags |= column_flags & GRN_OBJ_WITH_POSITION; + /* TODO: Remove this check. Require Groonga 7.0.1. */ + if (table_cursor) { + flags |= column_flags & GRN_OBJ_WITH_POSITION; + } } else if (RVAL2CBOOL(rb_with_position)) { flags |= GRN_OBJ_WITH_POSITION; } - index_cursor = grn_index_cursor_open(context, table_cursor, - column, rid_min, rid_max, flags); - - rb_cursor = GRNINDEXCURSOR2RVAL(context, index_cursor, rb_table, rb_lexicon); + if (table_cursor) { + grn_obj *index_cursor; + index_cursor = grn_index_cursor_open(context, table_cursor, + column, rid_min, rid_max, flags); + rb_cursor = GRNINDEXCURSOR2RVAL(context, + index_cursor, + rb_table, + rb_lexicon); + } else { + grn_ii *ii = (grn_ii *)column; + grn_ii_cursor *ii_cursor; + ii_cursor = grn_ii_cursor_open(context, + ii, + term_id, + rid_min, + rid_max, + /* TODO: Require Groonga 7.0.1. */ + 0, /* grn_ii_get_n_elements(context, ii), */ + flags); + rb_cursor = rb_grn_inverted_index_cursor_to_ruby_object(context, + ii_cursor, + term_id, + flags, + rb_table, + rb_lexicon); + } if (rb_block_given_p()) - return rb_ensure(rb_yield, rb_cursor, rb_grn_object_close, rb_cursor); + return rb_ensure(rb_yield, rb_cursor, call_close, rb_cursor); else return rb_cursor; } Modified: ext/groonga/rb-grn-inverted-index-cursor.c (+62 -7) =================================================================== --- ext/groonga/rb-grn-inverted-index-cursor.c 2017-02-07 17:52:47 +0900 (1dac53c) +++ ext/groonga/rb-grn-inverted-index-cursor.c 2017-02-07 19:54:49 +0900 (e43ba30) @@ -27,6 +27,7 @@ struct _RbGrnInvertedIndexCursor grn_ctx *context; grn_ii_cursor *cursor; grn_id term_id; + int flags; }; static VALUE rb_cGrnInvertedIndexCursor; @@ -36,7 +37,7 @@ rb_grn_inverted_index_cursor_free(void *data) { RbGrnInvertedIndexCursor *rb_grn_cursor = data; - if (rb_grn_cursor->context) { + if (rb_grn_cursor->context && rb_grn_cursor->cursor) { grn_ii_cursor_close(rb_grn_cursor->context, rb_grn_cursor->cursor); } @@ -58,6 +59,8 @@ static const rb_data_type_t rb_grn_inverted_index_cursor_type = { VALUE rb_grn_inverted_index_cursor_to_ruby_object (grn_ctx *context, grn_ii_cursor *cursor, + grn_id term_id, + int flags, VALUE rb_table, VALUE rb_lexicon) { @@ -72,9 +75,18 @@ rb_grn_inverted_index_cursor_to_ruby_object (grn_ctx *context, rb_grn_cursor->self = rb_cursor; rb_grn_cursor->context = context; rb_grn_cursor->cursor = cursor; + rb_grn_cursor->term_id = term_id; + rb_grn_cursor->flags = flags; rb_iv_set(rb_cursor, "@table", rb_table); rb_iv_set(rb_cursor, "@lexicon", rb_lexicon); + /* TODO: Require Groonga 7.0.1. + if (rb_grn_cursor->cursor && + (rb_grn_cursor->flags & GRN_OBJ_WITH_POSITION)) { + grn_ii_cursor_next(context, cursor); + } + */ + return rb_cursor; } @@ -84,10 +96,24 @@ next_value (VALUE rb_posting, VALUE rb_table, VALUE rb_lexicon) { - grn_posting *posting; - - posting = grn_ii_cursor_next(rb_grn_cursor->context, - rb_grn_cursor->cursor); + grn_ctx *context = rb_grn_cursor->context; + grn_ii_cursor *cursor = rb_grn_cursor->cursor; + grn_posting *posting = NULL; + + /* TODO: Require Groonga 7.0.1. */ + /* + if (rb_grn_cursor->flags & GRN_OBJ_WITH_POSITION) { + posting = grn_ii_cursor_next_pos(context, cursor); + while (!posting && grn_ii_cursor_next(context, cursor)) { + posting = grn_ii_cursor_next_pos(context, cursor); + break; + } + } else { + */ + posting = grn_ii_cursor_next(context, cursor); + /* + } + */ if (!posting) { return Qnil; } @@ -123,6 +149,10 @@ rb_grn_inverted_index_cursor_next (VALUE self) self); } + if (!rb_grn_cursor->cursor) { + return Qnil; + } + rb_table = rb_iv_get(self, "@table"); rb_lexicon = rb_iv_get(self, "@lexicon"); rb_posting = next_value(Qnil, rb_grn_cursor, rb_table, rb_lexicon); @@ -160,6 +190,10 @@ rb_grn_inverted_index_cursor_each (int argc, VALUE *argv, VALUE self) self); } + if (!rb_grn_cursor->cursor) { + return Qnil; + } + rb_table = rb_iv_get(self, "@table"); rb_lexicon = rb_iv_get(self, "@lexicon"); reuse_posting_object = RVAL2CBOOL(rb_reuse_posting_object); @@ -196,8 +230,10 @@ rb_grn_inverted_index_cursor_close (VALUE self) self); } - grn_ii_cursor_close(rb_grn_cursor->context, - rb_grn_cursor->cursor); + if (rb_grn_cursor->cursor) { + grn_ii_cursor_close(rb_grn_cursor->context, + rb_grn_cursor->cursor); + } rb_grn_cursor->context = NULL; rb_grn_cursor->cursor = NULL; @@ -205,6 +241,23 @@ rb_grn_inverted_index_cursor_close (VALUE self) } +static VALUE +rb_grn_inverted_index_cursor_is_closed (VALUE self) +{ + RbGrnInvertedIndexCursor *rb_grn_cursor; + + TypedData_Get_Struct(self, + RbGrnInvertedIndexCursor, + &rb_grn_inverted_index_cursor_type, + rb_grn_cursor); + if (rb_grn_cursor->context) { + return Qfalse; + } else { + return Qtrue; + } + +} + void rb_grn_init_inverted_index_cursor (VALUE mGrn) { @@ -218,4 +271,6 @@ rb_grn_init_inverted_index_cursor (VALUE mGrn) rb_grn_inverted_index_cursor_each, -1); rb_define_method(rb_cGrnInvertedIndexCursor, "close", rb_grn_inverted_index_cursor_close, 0); + rb_define_method(rb_cGrnInvertedIndexCursor, "closed?", + rb_grn_inverted_index_cursor_is_closed, 0); } Modified: ext/groonga/rb-grn.h (+2 -0) =================================================================== --- ext/groonga/rb-grn.h 2017-02-07 17:52:47 +0900 (adcde73) +++ ext/groonga/rb-grn.h 2017-02-07 19:54:49 +0900 (9be30b3) @@ -829,6 +829,8 @@ VALUE rb_grn_index_cursor_to_ruby_object (grn_ctx *context, VALUE rb_grn_inverted_index_cursor_to_ruby_object (grn_ctx *context, grn_ii_cursor *cursor, + grn_id term_id, + int flags, VALUE rb_table, VALUE rb_lexicon); Modified: ext/groonga/rb-groonga.c (+1 -0) =================================================================== --- ext/groonga/rb-groonga.c 2017-02-07 17:52:47 +0900 (430c25d) +++ ext/groonga/rb-groonga.c 2017-02-07 19:54:49 +0900 (1601c86) @@ -229,6 +229,7 @@ Init_groonga (void) rb_grn_init_table(mGrn); rb_grn_init_table_cursor(mGrn); rb_grn_init_index_cursor(mGrn); + rb_grn_init_inverted_index_cursor(mGrn); rb_grn_init_posting(mGrn); rb_grn_init_type(mGrn); rb_grn_init_procedure(mGrn); Modified: test/test-index-cursor.rb (+55 -15) =================================================================== --- test/test-index-cursor.rb 2017-02-07 17:52:47 +0900 (97e3229) +++ test/test-index-cursor.rb 2017-02-07 19:54:49 +0900 (55e67b6) @@ -36,7 +36,27 @@ class IndexCursorTest < Test::Unit::TestCase assert_predicate(index_cursor, :closed?) end - assert_equal(expected_postings, postings) + assert_equal(expected_postings(:with_position => true), + postings) + end + + def test_term_id + postings = [] + @terms.open_cursor do |table_cursor| + table_cursor.each do |term| + index_cursor = nil + @content_index.open_cursor(term.id) do |cursor| + cursor.each do |posting| + postings << posting.to_hash + end + index_cursor = cursor + end + assert_predicate(index_cursor, :closed?) + end + end + + assert_equal(expected_postings(:with_position => false), + postings) end end @@ -151,20 +171,40 @@ class IndexCursorTest < Test::Unit::TestCase @articles.add("3", :content => "hello") end - def expected_postings - parameters = [:record_id, :section_id, :term_id, :position, - :term_frequency, :weight, :n_rest_postings] - - expected = [ - [1, 1, 1, 0, 1, 0, 0], - [2, 1, 1, 1, 1, 0, 0], - [2, 1, 2, 0, 1, 0, 0], - [3, 1, 2, 2, 1, 0, 0], - [3, 1, 3, 0, 1, 0, 0], - [3, 1, 4, 1, 1, 0, 0], - [3, 1, 5, 3, 1, 0, 0], - [3, 1, 6, 4, 1, 0, 0] - ] + def expected_postings(options={}) + parameters = [ + :record_id, + :section_id, + :term_id, + :position, + :term_frequency, + :weight, + :n_rest_postings, + ] + + if options[:with_position] + expected = [ + [1, 1, 1, 0, 1, 0, 0], + [2, 1, 1, 1, 1, 0, 0], + [2, 1, 2, 0, 1, 0, 0], + [3, 1, 2, 2, 1, 0, 0], + [3, 1, 3, 0, 1, 0, 0], + [3, 1, 4, 1, 1, 0, 0], + [3, 1, 5, 3, 1, 0, 0], + [3, 1, 6, 4, 1, 0, 0] + ] + else + expected = [ + [1, 1, 1, 0, 1, 0, 1], + [2, 1, 1, 0, 1, 0, 1], + [2, 1, 2, 0, 1, 0, 1], + [3, 1, 2, 0, 1, 0, 1], + [3, 1, 3, 0, 1, 0, 0], + [3, 1, 4, 1, 1, 0, 0], + [3, 1, 5, 3, 1, 0, 0], + [3, 1, 6, 4, 1, 0, 0] + ] + end create_hashes(parameters, expected) end -------------- next part -------------- HTML����������������������������...Download