null+****@clear*****
null+****@clear*****
2010年 8月 13日 (金) 16:05:05 JST
Kouhei Sutou 2010-08-13 07:05:05 +0000 (Fri, 13 Aug 2010)
New Revision: 13b0f4e672695de220af2921900c2d00f8d2d22a
Log:
don't accept negative offset and limit with GRN_CURSOR_PREFIX. #377
Modified files:
groonga.h
lib/db.c
test/unit/core/test-table-patricia-trie-cursor.c
Modified: groonga.h (+7 -1)
===================================================================
--- groonga.h 2010-08-13 06:32:12 +0000 (a9a65dc)
+++ groonga.h 2010-08-13 07:05:05 +0000 (9417b29)
@@ -726,10 +726,16 @@ typedef grn_obj grn_table_cursor;
* GRN_CURSOR_BY_ID/GRN_CURSOR_BY_KEY/GRN_CURSOR_PREFIXの3フラグは、
* 同時に指定することができない。
* @offset: 該当する範囲のレコードのうち、
- (0ベースで)offset番目からレコードを取り出す。
+ * (0ベースで)offset番目からレコードを取り出す。
+ *
+ * GRN_CURSOR_PREFIXを指定したときは負の数を指定する
+ * ことはできない。
* @limit: 該当する範囲のレコードのうち、limit件のみを取り出す。
* -1が指定された場合は、全件が指定されたものとみなす。
*
+ * GRN_CURSOR_PREFIXを指定したときは-1より小さい負の
+ * 数を指定することはできない。
+ *
* tableに登録されているレコードを順番に取り出すためのカーソルを生成して返す。
**/
GRN_API grn_table_cursor *grn_table_cursor_open(grn_ctx *ctx, grn_obj *table,
Modified: lib/db.c (+25 -3)
===================================================================
--- lib/db.c 2010-08-13 06:32:12 +0000 (23638ef)
+++ lib/db.c 2010-08-13 07:05:05 +0000 (e347dd2)
@@ -1776,12 +1776,34 @@ grn_table_cursor_open(grn_ctx *ctx, grn_obj *table,
{
grn_rc rc;
grn_table_cursor *tc = NULL;
+ unsigned int table_size;
if (!table) { return tc; }
GRN_API_ENTER;
- rc = grn_normalize_offset_and_limit(ctx, grn_table_size(ctx, table), &offset, &limit);
- if (rc) {
- ERR(rc, "grn_normalize_offset_and_limit failed");
+ table_size = grn_table_size(ctx, table);
+ if (flags & GRN_CURSOR_PREFIX) {
+ if (offset < 0) {
+ ERR(GRN_TOO_SMALL_OFFSET,
+ "can't use negative offset with GRN_CURSOR_PREFIX: %d", offset);
+ } else if (offset != 0 && offset >= table_size) {
+ ERR(GRN_TOO_LARGE_OFFSET,
+ "offset is rather than table size: offset:%d, table_size:%d",
+ offset, table_size);
+ } else {
+ if (limit < -1) {
+ ERR(GRN_TOO_SMALL_LIMIT,
+ "can't use small limit rather than -1 with GRN_CURSOR_PREFIX: %d",
+ limit);
+ } else if (limit == -1) {
+ limit = table_size;
+ }
+ }
} else {
+ rc = grn_normalize_offset_and_limit(ctx, table_size, &offset, &limit);
+ if (rc) {
+ ERR(rc, "grn_normalize_offset_and_limit failed");
+ }
+ }
+ if (!ctx->rc) {
switch (table->header.type) {
case GRN_DB :
tc = (grn_table_cursor *)grn_pat_cursor_open(ctx, ((grn_db *)table)->keys,
Modified: test/unit/core/test-table-patricia-trie-cursor.c (+49 -0)
===================================================================
--- test/unit/core/test-table-patricia-trie-cursor.c 2010-08-13 06:32:12 +0000 (f5bb1a5)
+++ test/unit/core/test-table-patricia-trie-cursor.c 2010-08-13 07:05:05 +0000 (32d2562)
@@ -38,6 +38,8 @@
cut_take_string(POINT(latitude_hours, latitude_minutes, latitude_seconds, \
longitude_hours, longitude_minutes, longitude_seconds))
+void data_prefix_error(void);
+void test_prefix_error(gpointer data);
void data_prefix_short_text(void);
void test_prefix_short_text(gpointer data);
void data_prefix_geo_point(void);
@@ -179,6 +181,53 @@ create_geo_point_table(const gchar *data)
}
void
+data_prefix_error(void)
+{
+#define ADD_DATA(label, rc, message, offset, limit) \
+ gcut_add_datum(label, \
+ "rc", G_TYPE_UINT, rc, \
+ "message", G_TYPE_STRING, message, \
+ "offset", G_TYPE_INT, offset, \
+ "limit", G_TYPE_INT, limit, \
+ NULL)
+
+ ADD_DATA("negative offset",
+ GRN_TOO_SMALL_OFFSET,
+ "can't use negative offset with GRN_CURSOR_PREFIX: -1",
+ -1, -1);
+ ADD_DATA("large offset",
+ GRN_TOO_LARGE_OFFSET,
+ "offset is rather than table size: offset:100, table_size:8",
+ 100, -1);
+ ADD_DATA("negative limit",
+ GRN_TOO_SMALL_LIMIT,
+ "can't use small limit rather than -1 with GRN_CURSOR_PREFIX: -2",
+ 0, -2);
+
+#undef ADD_DATA
+}
+
+void
+test_prefix_error(gpointer data)
+{
+ const gchar *min = "ab";
+ int offset, limit;
+
+ create_short_text_table();
+
+ offset = gcut_data_get_int(data, "offset");
+ limit = gcut_data_get_int(data, "limit");
+ cursor = grn_table_cursor_open(context, table,
+ min, strlen(min),
+ NULL, 0,
+ offset, limit,
+ GRN_CURSOR_PREFIX);
+ grn_test_assert_error(gcut_data_get_uint(data, "rc"),
+ gcut_data_get_string(data, "message"),
+ context);
+}
+
+void
data_prefix_short_text(void)
{
#define ADD_DATA(label, expected, min, offset, limit, flags) \