[groonga-commit:1190] ranguba/rroonga [master] support near cursor.

null+ranguba at clear-code.com null+ranguba at clear-code.com
Fri Aug 27 06:01:56 EDT 2010


Kouhei Sutou	2010-08-27 10:01:56 +0000 (Fri, 27 Aug 2010)

  New Revision: f1d7a7b5ff82fca4a02baa518f22ce1a8522f563

  Log:
    support near cursor.

  Modified files:
    ext/groonga/rb-grn-patricia-trie.c
    test/test-patricia-trie.rb

  Modified: ext/groonga/rb-grn-patricia-trie.c (+113 -0)
===================================================================
--- ext/groonga/rb-grn-patricia-trie.c    2010-08-27 07:53:53 +0000 (6c45a92)
+++ ext/groonga/rb-grn-patricia-trie.c    2010-08-27 10:01:56 +0000 (167a1e7)
@@ -19,6 +19,8 @@
 
 #include "rb-grn.h"
 
+grn_rc grn_obj_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest, int addp);
+
 #define SELF(object) ((RbGrnTableKeySupport *)DATA_PTR(object))
 
 VALUE rb_cGrnPatriciaTrie;
@@ -713,6 +715,114 @@ rb_grn_patricia_trie_open_rk_cursor (int argc, VALUE *argv, VALUE self)
 	return rb_cursor;
 }
 
+
+static grn_table_cursor *
+rb_grn_patricia_trie_open_grn_near_cursor (int argc, VALUE *argv, VALUE self,
+					     grn_ctx **context, int flags)
+{
+    grn_obj *table;
+    grn_obj *key_p = NULL, casted_key;
+    grn_table_cursor *cursor;
+    unsigned min_size = 0;
+    int offset = 0, limit = -1;
+    VALUE options, rb_key, rb_min_size;
+    VALUE rb_greater_than, rb_less_than, rb_offset, rb_limit;
+
+    flags |= GRN_CURSOR_PREFIX;
+
+    rb_grn_table_deconstruct((RbGrnTable *)SELF(self), &table, context,
+			     NULL, NULL,
+			     NULL, NULL, NULL,
+			     NULL);
+
+    rb_scan_args(argc, argv, "11", &rb_key, &options);
+
+    rb_grn_scan_options(options,
+			"size", &rb_min_size,
+                        "offset", &rb_offset,
+                        "limit", &rb_limit,
+			"greater_than", &rb_greater_than,
+			"less_than", &rb_less_than,
+			NULL);
+
+    key_p = RVAL2GRNBULK_WITH_TYPE(rb_key, *context, key_p,
+				   table->header.domain, grn_ctx_at(*context, table->header.domain));
+    GRN_OBJ_INIT(&casted_key, GRN_BULK, 0, table->header.domain);
+    if (key_p->header.domain != table->header.domain) {
+	grn_obj_cast(*context, key_p, &casted_key, 0);
+	key_p = &casted_key;
+    }
+
+    if (!NIL_P(rb_min_size))
+	min_size = NUM2UINT(rb_min_size);
+    if (!NIL_P(rb_offset))
+	offset = NUM2INT(rb_offset);
+    if (!NIL_P(rb_limit))
+	limit = NUM2INT(rb_limit);
+
+    if (RVAL2CBOOL(rb_greater_than))
+	flags |= GRN_CURSOR_GT;
+    if (RVAL2CBOOL(rb_less_than))
+	flags |= GRN_CURSOR_LT;
+
+    cursor = grn_table_cursor_open(*context, table,
+				   NULL, min_size,
+				   GRN_BULK_HEAD(key_p), GRN_BULK_VSIZE(key_p),
+				   offset, limit, flags);
+    GRN_OBJ_FIN(*context, &casted_key);
+    rb_grn_context_check(*context, self);
+
+    return cursor;
+}
+
+/*
+ * call-seq:
+ *   table.open_near_cursor(key, options={}) -> Groonga::PatriciaTrieCursor
+ *   table.open_near_cursor(key, options={}) {|cursor| ... }
+ *
+ * _key_に近い順にレコードを取り出すカーソルを生成して返す。
+ * ブロックを指定すると、そのブロックに生成したカーソルが渡さ
+ * れ、ブロックを抜けると自動的にカーソルが破棄される。
+ *
+ * _options_に指定可能な値は以下の通り。
+ *
+ * [+:size+]
+ *   _size_バイト以降のデータが同じキーのレコードに限定する。
+ *
+ * [+:offset+]
+ *   該当する範囲のレコードのうち、(0ベースで)_:offset_番目
+ *   からレコードを取り出す。
+ *
+ * [+:limit+]
+ *   該当する範囲のレコードのうち、_:limit_件のみを取り出す。
+ *   省略された場合または-1が指定された場合は、全件が指定され
+ *   たものとみなす。
+ *
+ * [+:greater_than+]
+ *   +true+を指定すると_key_で指定した値に一致した[+key+]を
+ *   範囲に含まない。
+ *
+ * [+:less_than+]
+ *   +true+を指定すると_key_で指定した値に一致した[+key+]を
+ *   範囲に含まない。
+ */
+static VALUE
+rb_grn_patricia_trie_open_near_cursor (int argc, VALUE *argv, VALUE self)
+{
+    grn_ctx *context = NULL;
+    grn_table_cursor *cursor;
+    VALUE rb_cursor;
+
+    cursor = rb_grn_patricia_trie_open_grn_near_cursor(argc, argv,
+								self, &context, GRN_CURSOR_RK);
+    rb_cursor = GRNTABLECURSOR2RVAL(Qnil, context, cursor);
+    rb_iv_set(rb_cursor, "@table", self); /* FIXME: cursor should mark table */
+    if (rb_block_given_p())
+	return rb_ensure(rb_yield, rb_cursor, rb_grn_object_close, rb_cursor);
+    else
+	return rb_cursor;
+}
+
 void
 rb_grn_init_patricia_trie (VALUE mGrn)
 {
@@ -739,4 +849,7 @@ rb_grn_init_patricia_trie (VALUE mGrn)
     rb_define_method(rb_cGrnPatriciaTrie, "open_rk_cursor",
 		     rb_grn_patricia_trie_open_rk_cursor,
 		     -1);
+    rb_define_method(rb_cGrnPatriciaTrie, "open_near_cursor",
+		     rb_grn_patricia_trie_open_near_cursor,
+		     -1);
 }

  Modified: test/test-patricia-trie.rb (+67 -0)
===================================================================
--- test/test-patricia-trie.rb    2010-08-27 07:53:53 +0000 (4629159)
+++ test/test-patricia-trie.rb    2010-08-27 10:01:56 +0000 (0f38a7e)
@@ -296,4 +296,71 @@ class PatriciaTrieTest < Test::Unit::TestCase
     end
     assert_equal(expected, actual.sort)
   end
+
+  def test_near_cursor
+    points = Groonga::PatriciaTrie.create(:name => "Points",
+                                          :key_type => 'WGS84GeoPoint')
+    ["130322053x504985073",
+     "130285021x504715091",
+     "130117012x504390088",
+     "130335016x504662007",
+     "130308044x504536008",
+     "130306053x504530043",
+     "130205016x505331054",
+     "130222054x505270050",
+     "130255017x504266011",
+     "130239038x504251015",
+     "129885039x503653023",
+     "129809022x504597055",
+     "130015001x504266057",
+     "130089012x505045070",
+     "130208017x504315098",
+     "130347036x504325073",
+     "130380061x505202034",
+     "129903045x504648034",
+     "130094061x505025099",
+     "130133052x505120058",
+     "130329069x505188046",
+     "130226001x503769013",
+     "129866001x504328017",
+     "129786048x504792049",
+     "129845056x504853081",
+     "130055008x504968095",
+     "130086003x504480071",
+     "129680021x504441006",
+     "129855010x504452003",
+     "130280013x505208029",
+     "129721099x504685024",
+     "129690039x504418033",
+     "130019020x505027021",
+     "130046026x505082073",
+     "130038025x505066028",
+     "129917001x504675017"].each do |point|
+      points.add(point)
+    end
+
+    assert_near_cursor(["129680021x504441006",
+                        "129690039x504418033",
+                        "129721099x504685024",
+                        "129786048x504792049",
+                        "129809022x504597055",
+                        "129845056x504853081",
+                        "129855010x504452003",
+                        "129866001x504328017",
+                        "129885039x503653023",
+                        "129903045x504648034"],
+                       points,
+                       "129786048x504792049",
+                       {:limit => 10})
+  end
+
+  def assert_near_cursor(expected, tables, prefix, options={})
+    actual = []
+    tables.open_near_cursor(prefix, options) do |cursor|
+      cursor.each do |record|
+        actual << record.key
+      end
+    end
+    assert_equal(expected, actual)
+  end
 end



More information about the groonga-commit mailing list