[Groonga-commit] groonga/grnxx at c6863bd [master] Enable tests for Index. (#121)

Back to archive index

susumu.yata null+****@clear*****
Tue Dec 16 10:46:34 JST 2014


susumu.yata	2014-11-28 16:00:19 +0900 (Fri, 28 Nov 2014)

  New Revision: c6863bd0e2871c1c5b98dc5201199fb27dd4f223
  https://github.com/groonga/grnxx/commit/c6863bd0e2871c1c5b98dc5201199fb27dd4f223

  Message:
    Enable tests for Index. (#121)

  Modified files:
    test/Makefile.am
    test/test_index.cpp

  Modified: test/Makefile.am (+3 -4)
===================================================================
--- test/Makefile.am    2014-11-28 15:59:44 +0900 (9694e48)
+++ test/Makefile.am    2014-11-28 16:00:19 +0900 (94ce4bb)
@@ -5,14 +5,13 @@ TESTS =				\
 	test_db			\
 	test_table		\
 	test_column		\
+	test_index		\
 	test_expression		\
 	test_sorter		\
 	test_merger		\
 	test_pipeline		\
 	test_issue_62
 
-#	test_index
-
 check_PROGRAMS = $(TESTS)
 
 test_string_SOURCES = test_string.cpp
@@ -33,8 +32,8 @@ test_table_LDADD = $(top_srcdir)/lib/grnxx/libgrnxx.la
 test_column_SOURCES = test_column.cpp
 test_column_LDADD = $(top_srcdir)/lib/grnxx/libgrnxx.la
 
-#test_index_SOURCES = test_index.cpp
-#test_index_LDADD = $(top_srcdir)/lib/grnxx/libgrnxx.la
+test_index_SOURCES = test_index.cpp
+test_index_LDADD = $(top_srcdir)/lib/grnxx/libgrnxx.la
 
 test_expression_SOURCES = test_expression.cpp
 test_expression_LDADD = $(top_srcdir)/lib/grnxx/libgrnxx.la

  Modified: test/test_index.cpp (+863 -796)
===================================================================
--- test/test_index.cpp    2014-11-28 15:59:44 +0900 (3049942)
+++ test/test_index.cpp    2014-11-28 16:00:19 +0900 (81bd758)
@@ -28,308 +28,319 @@
 std::mt19937_64 mersenne_twister;
 
 void test_index() {
-  grnxx::Error error;
-
   // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
+  auto db = grnxx::open_db("");
 
   // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
+  auto table = db->create_table("Table");
 
   // Append the first row.
-  grnxx::Int row_id;
-  assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                           grnxx::Datum(), &row_id));
+  grnxx::Int row_id = table->insert_row();
 
   // Create a column named "Column".
-  auto column = table->create_column(&error, "Column", grnxx::INT_DATA);
-  assert(column);
+  auto column = table->create_column("Column", grnxx::INT_DATA);
 
   // Create an index named "Index".
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
+  auto index = column->create_index("Index", grnxx::TREE_INDEX);
   assert(index->column() == column);
   assert(index->name() == "Index");
   assert(index->type() == grnxx::TREE_INDEX);
 }
 
 void test_set_and_index() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
+  constexpr size_t NUM_ROWS = 1 << 16;
 
   // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
+  auto db = grnxx::open_db("");
 
   // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
+  auto table = db->create_table("Table");
 
   // Create a column.
-  auto column = table->create_column(&error, "Int", grnxx::INT_DATA);
-  assert(column);
+  auto column = table->create_column("Int", grnxx::INT_DATA);
 
   // Generate random values.
-  // Int: [0, 100).
+  // Int: [0, 100) or N/A.
   grnxx::Array<grnxx::Int> values;
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, mersenne_twister() % 100);
+  values.resize(NUM_ROWS);
+  size_t total_count = 0;
+  for (size_t i = 0; i < NUM_ROWS; ++i) {
+    if ((mersenne_twister() % 128) != 0) {
+      values[i] = grnxx::Int(mersenne_twister() % 100);
+      ++total_count;
+    } else {
+      values[i] = grnxx::Int::na();
+    }
   }
 
   // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
+  for (size_t i = 0; i < NUM_ROWS; ++i) {
+    grnxx::Int row_id = table->insert_row();
+    assert(row_id.match(grnxx::Int(i)));
+    column->set(row_id, values[i]);
   }
 
   // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
-
-  // Create a cursor.
-  auto cursor = index->find_in_range(&error);
-  assert(cursor);
-
-  grnxx::Array<grnxx::Record> records;
-  auto result = cursor->read_all(&error, &records);
-  assert(result.is_ok);
-  assert(result.count == NUM_ROWS);
-  for (grnxx::Int i = 1; i < NUM_ROWS; ++i) {
-    assert(values[records.get_row_id(i - 1)] <= values[records.get_row_id(i)]);
-  }
+  auto index = column->create_index("Index", grnxx::TREE_INDEX);
+
+//  // Create a cursor.
+//  auto cursor = index->find_in_range();
+
+//  grnxx::Array<grnxx::Record> records;
+//  size_t count = cursor->read_all(&records);
+//  assert(count == total_count);
+//  for (size_t i = 1; i < NUM_ROWS; ++i) {
+//    size_t lhs_row_id = records[i - 1].row_id.raw();
+//    size_t rhs_row_id = records[i].row_id.raw();
+//    grnxx::Int lhs_value = values[lhs_row_id];
+//    grnxx::Int rhs_value = values[rhs_row_id];
+//    assert(!lhs_value.is_na());
+//    assert(!rhs_value.is_na());
+//    assert(lhs_value.raw() <= rhs_value.raw());
+//    if (lhs_value.match(rhs_value)) {
+//      assert(lhs_row_id < rhs_row_id);
+//    }
+//  }
 }
 
 void test_index_and_set() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
+  constexpr size_t NUM_ROWS = 1 << 16;
 
   // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
+  auto db = grnxx::open_db("");
 
   // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
+  auto table = db->create_table("Table");
 
   // Create a column.
-  auto column = table->create_column(&error, "Int", grnxx::INT_DATA);
-  assert(column);
+  auto column = table->create_column("Int", grnxx::INT_DATA);
 
   // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
+  auto index = column->create_index("Index", grnxx::TREE_INDEX);
 
   // Generate random values.
-  // Int: [0, 100).
+  // Int: [0, 100) or N/A.
   grnxx::Array<grnxx::Int> values;
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, mersenne_twister() % 100);
+  values.resize(NUM_ROWS);
+  size_t total_count = 0;
+  for (size_t i = 0; i < NUM_ROWS; ++i) {
+    if ((mersenne_twister() % 128) != 0) {
+      values[i] = grnxx::Int(mersenne_twister() % 100);
+      ++total_count;
+    } else {
+      values[i] = grnxx::Int::na();
+    }
   }
 
   // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
+  for (size_t i = 0; i < NUM_ROWS; ++i) {
+    grnxx::Int row_id = table->insert_row();
+    assert(row_id.match(grnxx::Int(i)));
+    column->set(row_id, values[i]);
   }
 
-  // Create a cursor.
-  auto cursor = index->find_in_range(&error);
-  assert(cursor);
-
-  grnxx::Array<grnxx::Record> records;
-  auto result = cursor->read_all(&error, &records);
-  assert(result.is_ok);
-  assert(result.count == NUM_ROWS);
-  for (grnxx::Int i = 1; i < NUM_ROWS; ++i) {
-    assert(values[records.get_row_id(i - 1)] <= values[records.get_row_id(i)]);
-  }
+//  // Create a cursor.
+//  auto cursor = index->find_in_range();
+
+//  grnxx::Array<grnxx::Record> records;
+//  size_t count = cursor->read_all(&records);
+//  assert(count == NUM_ROWS);
+//  for (size_t i = 1; i < NUM_ROWS; ++i) {
+//    size_t lhs_row_id = records[i - 1].row_id.raw();
+//    size_t rhs_row_id = records[i].row_id.raw();
+//    grnxx::Int lhs_value = values[lhs_row_id];
+//    grnxx::Int rhs_value = values[rhs_row_id];
+//    assert(!lhs_value.is_na());
+//    assert(!rhs_value.is_na());
+//    assert(lhs_value.raw() <= rhs_value.raw());
+//    if (lhs_value.match(rhs_value)) {
+//      assert(lhs_row_id < rhs_row_id);
+//    }
+//  }
 }
 
 void test_remove() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
+  constexpr size_t NUM_ROWS = 1 << 16;
 
   // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
+  auto db = grnxx::open_db("");
 
   // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
+  auto table = db->create_table("Table");
 
   // Create a column.
-  auto column = table->create_column(&error, "Int", grnxx::INT_DATA);
-  assert(column);
+  auto column = table->create_column("Int", grnxx::INT_DATA);
 
   // Generate random values.
-  // Int: [0, 100).
+  // Int: [0, 100) or N/A.
   grnxx::Array<grnxx::Int> values;
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, mersenne_twister() % 100);
+  values.resize(NUM_ROWS);
+  size_t total_count = 0;
+  for (size_t i = 0; i < NUM_ROWS; ++i) {
+    if ((mersenne_twister() % 128) != 0) {
+      values[i] = grnxx::Int(mersenne_twister() % 100);
+      ++total_count;
+    } else {
+      values[i] = grnxx::Int::na();
+    }
   }
 
   // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
+  for (size_t i = 0; i < NUM_ROWS; ++i) {
+    grnxx::Int row_id = table->insert_row();
+    assert(row_id.match(grnxx::Int(i)));
+    column->set(row_id, values[i]);
   }
 
   // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
-
-  // Remove odd rows.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; i += 2) {
-    assert(table->remove_row(&error, i));
-    assert(!table->test_row(&error, i));
+  auto index = column->create_index("Index", grnxx::TREE_INDEX);
+
+  // Remove even rows.
+  size_t odd_count = total_count;
+  for (size_t i = 0; i < NUM_ROWS; i += 2) {
+    grnxx::Int row_id(i);
+    grnxx::Datum datum;
+    column->get(row_id, &datum);
+    if (datum.as_int().is_na()) {
+      --odd_count;
+    }
+    table->remove_row(row_id);
+    assert(!table->test_row(row_id));
   }
 
   // Create a cursor.
-  auto cursor = index->find_in_range(&error);
-  assert(cursor);
-
-  grnxx::Array<grnxx::Record> records;
-  auto result = cursor->read_all(&error, &records);
-  assert(result.is_ok);
-  assert(result.count == NUM_ROWS / 2);
-  for (grnxx::Int i = 1; i < (NUM_ROWS / 2); ++i) {
-    assert(values[records.get_row_id(i - 1)] <= values[records.get_row_id(i)]);
-  }
+//  auto cursor = index->find_in_range();
+
+//  grnxx::Array<grnxx::Record> records;
+//  size_t count = cursor->read_all(&records);
+//  assert(count == odd_count);
+//  for (size_t i = 0; i < count; ++i) {
+//    size_t lhs_row_id = records[i - 1].row_id.raw();
+//    size_t rhs_row_id = records[i].row_id.raw();
+//    grnxx::Int lhs_value = values[lhs_row_id];
+//    grnxx::Int rhs_value = values[rhs_row_id];
+//    assert(!lhs_value.is_na());
+//    assert(!rhs_value.is_na());
+//    assert(lhs_value.raw() <= rhs_value.raw());
+//    if (lhs_value.match(rhs_value)) {
+//      assert(lhs_row_id < rhs_row_id);
+//    }
+//  }
 }
 
-void test_bool_exact_match() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
-
-  // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
-
-  // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
-
-  // Create a column.
-  auto column = table->create_column(&error, "Bool", grnxx::BOOL_DATA);
-  assert(column);
-
-  // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
-
-  // Generate random values.
-  // Bool: [false, true].
-  grnxx::Array<grnxx::Bool> values;
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, (mersenne_twister() & 1) == 1);
-  }
-
-  // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
-  }
-
-  // Test cursors for each value.
-  grnxx::Bool possible_values[2] = { false, true };
-  for (int possible_value_id = 0; possible_value_id < 2; ++possible_value_id) {
-    grnxx::Bool value = possible_values[possible_value_id];
-
-    auto cursor = index->find(&error, value);
-    assert(cursor);
-
-    grnxx::Array<grnxx::Record> records;
-    auto result = cursor->read_all(&error, &records);
-    assert(result.is_ok);
-    for (grnxx::Int i = 1; i < records.size(); ++i) {
-      assert(values[records.get_row_id(i)] == value);
-    }
-
-    grnxx::Int count = 0;
-    for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-      if (values[i] == value) {
-        ++count;
-      }
-    }
-    assert(count == records.size());
-  }
-}
+//void test_bool_exact_match() {
+//  constexpr grnxx::Int NUM_ROWS = 1 << 16;
+
+//  grnxx::Error error;
+
+//  // Create a database with the default options.
+//  auto db = grnxx::open_db(&error, "");
+//  assert(db);
+
+//  // Create a table with the default options.
+//  auto table = db->create_table(&error, "Table");
+//  assert(table);
+
+//  // Create a column.
+//  auto column = table->create_column(&error, "Bool", grnxx::BOOL_DATA);
+//  assert(column);
+
+//  // Create an index.
+//  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
+//  assert(index);
+
+//  // Generate random values.
+//  // Bool: [false, true].
+//  grnxx::Array<grnxx::Bool> values;
+//  assert(values.resize(&error, NUM_ROWS + 1));
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    values.set(i, (mersenne_twister() & 1) == 1);
+//  }
+
+//  // Store generated values into columns.
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    grnxx::Int row_id;
+//    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
+//                             grnxx::Datum(), &row_id));
+//    assert(row_id == i);
+//    assert(column->set(&error, row_id, values[i]));
+//  }
+
+//  // Test cursors for each value.
+//  grnxx::Bool possible_values[2] = { false, true };
+//  for (int possible_value_id = 0; possible_value_id < 2; ++possible_value_id) {
+//    grnxx::Bool value = possible_values[possible_value_id];
+
+//    auto cursor = index->find(&error, value);
+//    assert(cursor);
+
+//    grnxx::Array<grnxx::Record> records;
+//    auto result = cursor->read_all(&error, &records);
+//    assert(result.is_ok);
+//    for (grnxx::Int i = 1; i < records.size(); ++i) {
+//      assert(values[records.get_row_id(i)] == value);
+//    }
+
+//    grnxx::Int count = 0;
+//    for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//      if (values[i] == value) {
+//        ++count;
+//      }
+//    }
+//    assert(count == records.size());
+//  }
+//}
 
 void test_int_exact_match() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
+  constexpr size_t NUM_ROWS = 1 << 16;
 
   // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
+  auto db = grnxx::open_db("");
 
   // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
+  auto table = db->create_table("Table");
 
   // Create a column.
-  auto column = table->create_column(&error, "Int", grnxx::INT_DATA);
-  assert(column);
+  auto column = table->create_column("Int", grnxx::INT_DATA);
 
   // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
+  auto index = column->create_index("Index", grnxx::TREE_INDEX);
 
   // Generate random values.
-  // Int: [0, 100).
+  // Int: [0, 100) or N/A.
   grnxx::Array<grnxx::Int> values;
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, mersenne_twister() % 100);
+  values.resize(NUM_ROWS);
+  size_t total_count = 0;
+  for (size_t i = 0; i < NUM_ROWS; ++i) {
+    if ((mersenne_twister() % 128) != 0) {
+      values[i] = grnxx::Int(mersenne_twister() % 100);
+      ++total_count;
+    } else {
+      values[i] = grnxx::Int::na();
+    }
   }
 
   // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
+  for (size_t i = 0; i < NUM_ROWS; ++i) {
+    grnxx::Int row_id = table->insert_row();
+    assert(row_id.match(grnxx::Int(i)));
+    column->set(row_id, values[i]);
   }
 
   // Test cursors for each value.
-  for (grnxx::Int value = 0; value < 100; ++value) {
-    auto cursor = index->find(&error, value);
-    assert(cursor);
+  for (int raw = 0; raw < 100; ++raw) {
+    grnxx::Int value(raw);
+    auto cursor = index->find(value);
 
     grnxx::Array<grnxx::Record> records;
-    auto result = cursor->read_all(&error, &records);
-    assert(result.is_ok);
-    for (grnxx::Int i = 1; i < records.size(); ++i) {
-      assert(values[records.get_row_id(i)] == value);
+    size_t count = cursor->read_all(&records);
+    for (size_t i = 0; i < records.size(); ++i) {
+      assert(values[records[i].row_id.raw()].match(value));
     }
 
-    grnxx::Int count = 0;
-    for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-      if (values[i] == value) {
+    count = 0;
+    for (size_t i = 0; i < NUM_ROWS; ++i) {
+      if (values[i].match(value)) {
         ++count;
       }
     }
@@ -338,126 +349,55 @@ void test_int_exact_match() {
 }
 
 void test_float_exact_match() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
+  constexpr size_t NUM_ROWS = 1 << 16;
 
   // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
+  auto db = grnxx::open_db("");
 
   // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
+  auto table = db->create_table("Table");
 
   // Create a column.
-  auto column = table->create_column(&error, "Float", grnxx::FLOAT_DATA);
-  assert(column);
+  auto column = table->create_column("Float", grnxx::FLOAT_DATA);
 
   // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
+  auto index = column->create_index("Index", grnxx::TREE_INDEX);
 
   // Generate random values.
-  // Float: [0.0, 1.0).
+  // Float: [0, 1.0) or N/A.
   grnxx::Array<grnxx::Float> values;
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, (mersenne_twister() % 256) / 256.0);
-  }
-
-  // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
-  }
-
-  // Test cursors for each value.
-  for (grnxx::Int int_value = 0; int_value < 256; ++int_value) {
-    grnxx::Float value = int_value / 256.0;
-
-    auto cursor = index->find(&error, value);
-    assert(cursor);
-
-    grnxx::Array<grnxx::Record> records;
-    auto result = cursor->read_all(&error, &records);
-    assert(result.is_ok);
-    for (grnxx::Int i = 1; i < records.size(); ++i) {
-      assert(values[records.get_row_id(i)] == value);
-    }
-
-    grnxx::Int count = 0;
-    for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-      if (values[i] == value) {
-        ++count;
-      }
+  values.resize(NUM_ROWS);
+  size_t total_count = 0;
+  for (size_t i = 0; i < NUM_ROWS; ++i) {
+    if ((mersenne_twister() % 256) != 0) {
+      values[i] = grnxx::Float((mersenne_twister() % 256) / 256.0);
+      ++total_count;
+    } else {
+      values[i] = grnxx::Float::na();
     }
-    assert(count == records.size());
-  }
-}
-
-void test_text_exact_match() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
-
-  // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
-
-  // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
-
-  // Create a column.
-  auto column = table->create_column(&error, "Text", grnxx::TEXT_DATA);
-  assert(column);
-
-  // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
-
-  // Generate random values.
-  // Text: ["0", "99"].
-  grnxx::Array<grnxx::Text> values;
-  char bodies[100][3];
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (int i = 0; i < 100; ++i) {
-    std::sprintf(bodies[i], "%d", i);
-  }
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, bodies[mersenne_twister() % 100]);
   }
 
   // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
+  for (size_t i = 0; i < NUM_ROWS; ++i) {
+    grnxx::Int row_id = table->insert_row();
+    assert(row_id.match(grnxx::Int(i)));
+    column->set(row_id, values[i]);
   }
 
   // Test cursors for each value.
-  for (int int_value = 0; int_value < 100; ++int_value) {
-    grnxx::Text value = bodies[int_value];
-
-    auto cursor = index->find(&error, value);
-    assert(cursor);
+  for (int raw = 0; raw < 256; ++raw) {
+    grnxx::Float value(raw / 256.0);
+    auto cursor = index->find(value);
 
     grnxx::Array<grnxx::Record> records;
-    auto result = cursor->read_all(&error, &records);
-    assert(result.is_ok);
-    for (grnxx::Int i = 1; i < records.size(); ++i) {
-      assert(values[records.get_row_id(i)] == value);
+    size_t count = cursor->read_all(&records);
+    for (size_t i = 0; i < records.size(); ++i) {
+      assert(values[records[i].row_id.raw()].match(value));
     }
 
-    grnxx::Int count = 0;
-    for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-      if (values[i] == value) {
+    count = 0;
+    for (size_t i = 0; i < NUM_ROWS; ++i) {
+      if (values[i].match(value)) {
         ++count;
       }
     }
@@ -465,370 +405,60 @@ void test_text_exact_match() {
   }
 }
 
-void test_int_range() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
-
-  // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
-
-  // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
-
-  // Create a column.
-  auto column = table->create_column(&error, "Int", grnxx::INT_DATA);
-  assert(column);
-
-  // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
-
-  // Generate random values.
-  // Int: [0, 100).
-  grnxx::Array<grnxx::Int> values;
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, mersenne_twister() % 100);
-  }
-
-  // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
-  }
-
-  // Create a cursor.
-  grnxx::IndexRange range;
-  range.set_lower_bound(grnxx::Int(10), grnxx::INCLUSIVE_END_POINT);
-  range.set_upper_bound(grnxx::Int(90), grnxx::EXCLUSIVE_END_POINT);
-  auto cursor = index->find_in_range(&error, range);
-  assert(cursor);
-
-  grnxx::Array<grnxx::Record> records;
-  auto result = cursor->read_all(&error, &records);
-  assert(result.is_ok);
-  for (grnxx::Int i = 1; i < records.size(); ++i) {
-    assert(values[records.get_row_id(i - 1)] <= values[records.get_row_id(i)]);
-  }
-
-  grnxx::Int count = 0;
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    if ((values[i] >= 10) && (values[i] < 90)) {
-      ++count;
-    }
-  }
-  assert(count == records.size());
-}
-
-void test_float_range() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
-
-  // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
-
-  // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
-
-  // Create a column.
-  auto column = table->create_column(&error, "Float", grnxx::FLOAT_DATA);
-  assert(column);
-
-  // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
-
-  // Generate random values.
-  // Float: [0.0, 1.0).
-  grnxx::Array<grnxx::Float> values;
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, (mersenne_twister() % 256) / 256.0);
-  }
-
-  // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
-  }
-
-  // Create a cursor.
-  grnxx::IndexRange range;
-  range.set_lower_bound(grnxx::Float(64 / 256.0), grnxx::INCLUSIVE_END_POINT);
-  range.set_upper_bound(grnxx::Float(192 / 256.0), grnxx::EXCLUSIVE_END_POINT);
-  auto cursor = index->find_in_range(&error, range);
-  assert(cursor);
-
-  grnxx::Array<grnxx::Record> records;
-  auto result = cursor->read_all(&error, &records);
-  assert(result.is_ok);
-  for (grnxx::Int i = 1; i < records.size(); ++i) {
-    assert(values[records.get_row_id(i - 1)] <= values[records.get_row_id(i)]);
-  }
-
-  grnxx::Int count = 0;
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    if ((values[i] >= (64 / 256.0)) && (values[i] < (192 / 256.0))) {
-      ++count;
-    }
-  }
-  assert(count == records.size());
-}
-
-void test_text_range() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
+void test_text_exact_match() {
+  constexpr size_t NUM_ROWS = 1 << 16;
 
   // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
+  auto db = grnxx::open_db("");
 
   // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
+  auto table = db->create_table("Table");
 
   // Create a column.
-  auto column = table->create_column(&error, "Text", grnxx::TEXT_DATA);
-  assert(column);
+  auto column = table->create_column("Text", grnxx::TEXT_DATA);
 
   // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
+  auto index = column->create_index("Index", grnxx::TREE_INDEX);
 
   // Generate random values.
-  // Text: ["0", "99"].
-  grnxx::Array<grnxx::Text> values;
-  char bodies[100][3];
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (int i = 0; i < 100; ++i) {
+  // Text: ["0", "256") or N/A.
+  char bodies[256][4];
+  for (int i = 0; i < 256; ++i) {
     std::sprintf(bodies[i], "%d", i);
   }
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, bodies[mersenne_twister() % 100]);
-  }
-
-  // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
-  }
-
-  // Create a cursor.
-  grnxx::IndexRange range;
-  range.set_lower_bound(grnxx::Text("25"), grnxx::EXCLUSIVE_END_POINT);
-  range.set_upper_bound(grnxx::Text("75"), grnxx::INCLUSIVE_END_POINT);
-  auto cursor = index->find_in_range(&error, range);
-  assert(cursor);
-
-  grnxx::Array<grnxx::Record> records;
-  auto result = cursor->read_all(&error, &records);
-  assert(result.is_ok);
-  for (grnxx::Int i = 1; i < records.size(); ++i) {
-    assert(values[records.get_row_id(i - 1)] <= values[records.get_row_id(i)]);
-  }
-
-  grnxx::Int count = 0;
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    if ((values[i] > "25") && (values[i] <= "75")) {
-      ++count;
-    }
-  }
-  assert(count == records.size());
-}
-
-bool inclusive_starts_with(const grnxx::Text &arg1, const grnxx::Text &arg2) {
-  if (arg1.size() < arg2.size()) {
-    return false;
-  }
-  for (grnxx::Int i = 0; i < arg2.size(); ++i) {
-    if (arg1[i] != arg2[i]) {
-      return false;
-    }
-  }
-  return true;
-}
-
-bool exclusive_starts_with(const grnxx::Text &arg1, const grnxx::Text &arg2) {
-  if (arg1.size() <= arg2.size()) {
-    return false;
-  }
-  for (grnxx::Int i = 0; i < arg2.size(); ++i) {
-    if (arg1[i] != arg2[i]) {
-      return false;
-    }
-  }
-  return true;
-}
-
-void test_text_find_starts_with() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
-
-  // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
-
-  // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
-
-  // Create a column.
-  auto column = table->create_column(&error, "Text", grnxx::TEXT_DATA);
-  assert(column);
-
-  // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
-
-  // Generate random values.
-  // Text: ["0", "99"].
   grnxx::Array<grnxx::Text> values;
-  char bodies[100][3];
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (int i = 0; i < 100; ++i) {
-    std::sprintf(bodies[i], "%d", i);
-  }
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, bodies[mersenne_twister() % 100]);
-  }
-
-  // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
-  }
-
-  // Test cursors for each value.
-  for (int int_value = 0; int_value < 100; ++int_value) {
-    grnxx::Text value = bodies[int_value];
-
-    grnxx::EndPoint prefix;
-    prefix.value = value;
-    prefix.type = grnxx::INCLUSIVE_END_POINT;
-    auto cursor = index->find_starts_with(&error, prefix);
-    assert(cursor);
-
-    grnxx::Array<grnxx::Record> records;
-    auto result = cursor->read_all(&error, &records);
-    assert(result.is_ok);
-    for (grnxx::Int i = 1; i < records.size(); ++i) {
-      assert(inclusive_starts_with(values[records.get_row_id(i)], value));
-    }
-
-    grnxx::Int count = 0;
-    for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-      if (inclusive_starts_with(values[i], value)) {
-        ++count;
-      }
+  values.resize(NUM_ROWS);
+  size_t total_count = 0;
+  for (size_t i = 0; i < NUM_ROWS; ++i) {
+    if ((mersenne_twister() % 256) != 0) {
+      values[i] = grnxx::Text(bodies[mersenne_twister() % 256]);
+      ++total_count;
+    } else {
+      values[i] = grnxx::Text::na();
     }
-    assert(count == records.size());
-  }
-
-  // Test cursors for each value.
-  for (int int_value = 0; int_value < 100; ++int_value) {
-    grnxx::Text value = bodies[int_value];
-
-    grnxx::EndPoint prefix;
-    prefix.value = value;
-    prefix.type = grnxx::EXCLUSIVE_END_POINT;
-    auto cursor = index->find_starts_with(&error, prefix);
-    assert(cursor);
-
-    grnxx::Array<grnxx::Record> records;
-    auto result = cursor->read_all(&error, &records);
-    assert(result.is_ok);
-    for (grnxx::Int i = 1; i < records.size(); ++i) {
-      assert(exclusive_starts_with(values[records.get_row_id(i)], value));
-    }
-
-    grnxx::Int count = 0;
-    for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-      if (exclusive_starts_with(values[i], value)) {
-        ++count;
-      }
-    }
-    assert(count == records.size());
-  }
-}
-
-void test_text_find_prefixes() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
-
-  // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
-
-  // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
-
-  // Create a column.
-  auto column = table->create_column(&error, "Text", grnxx::TEXT_DATA);
-  assert(column);
-
-  // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
-
-  // Generate random values.
-  // Text: ["0", "99"].
-  grnxx::Array<grnxx::Text> values;
-  char bodies[100][3];
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (int i = 0; i < 100; ++i) {
-    std::sprintf(bodies[i], "%d", i);
-  }
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, bodies[mersenne_twister() % 100]);
   }
 
   // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
+  for (size_t i = 0; i < NUM_ROWS; ++i) {
+    grnxx::Int row_id = table->insert_row();
+    assert(row_id.match(grnxx::Int(i)));
+    column->set(row_id, values[i]);
   }
 
   // Test cursors for each value.
-  for (int int_value = 0; int_value < 100; ++int_value) {
-    grnxx::Text value = bodies[int_value];
-    auto cursor = index->find_prefixes(&error, value);
-    assert(cursor);
+  for (int raw = 0; raw < 256; ++raw) {
+    grnxx::Text value(bodies[raw]);
+    auto cursor = index->find(value);
 
     grnxx::Array<grnxx::Record> records;
-    auto result = cursor->read_all(&error, &records);
-    assert(result.is_ok);
-    for (grnxx::Int i = 1; i < records.size(); ++i) {
-      assert(inclusive_starts_with(value, values[records.get_row_id(i)]));
+    size_t count = cursor->read_all(&records);
+    for (size_t i = 0; i < records.size(); ++i) {
+      assert(values[records[i].row_id.raw()].match(value));
     }
 
-    grnxx::Int count = 0;
-    for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-      if (inclusive_starts_with(value, values[i])) {
+    count = 0;
+    for (size_t i = 0; i < NUM_ROWS; ++i) {
+      if (values[i].match(value)) {
         ++count;
       }
     }
@@ -836,149 +466,586 @@ void test_text_find_prefixes() {
   }
 }
 
-void test_reverse() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
-
-  // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
-
-  // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
-
-  // Create a column.
-  auto column = table->create_column(&error, "Int", grnxx::INT_DATA);
-  assert(column);
-
-  // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
-
-  // Generate random values.
-  // Int: [0, 100).
-  grnxx::Array<grnxx::Int> values;
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, mersenne_twister() % 100);
-  }
-
-  // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
-  }
-
-  // Create a cursor.
-  grnxx::IndexRange range;
-  range.set_lower_bound(grnxx::Int(10), grnxx::INCLUSIVE_END_POINT);
-  range.set_upper_bound(grnxx::Int(90), grnxx::EXCLUSIVE_END_POINT);
-  grnxx::CursorOptions options;
-  options.order_type = grnxx::REVERSE_ORDER;
-  auto cursor = index->find_in_range(&error, range, options);
-  assert(cursor);
-
-  grnxx::Array<grnxx::Record> records;
-  auto result = cursor->read_all(&error, &records);
-  assert(result.is_ok);
-  for (grnxx::Int i = 1; i < records.size(); ++i) {
-    assert(values[records.get_row_id(i - 1)] >= values[records.get_row_id(i)]);
-  }
-
-  grnxx::Int count = 0;
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    if ((values[i] >= 10) && (values[i] < 90)) {
-      ++count;
-    }
-  }
-  assert(count == records.size());
-}
-
-void test_offset_and_limit() {
-  constexpr grnxx::Int NUM_ROWS = 1 << 16;
-
-  grnxx::Error error;
-
-  // Create a database with the default options.
-  auto db = grnxx::open_db(&error, "");
-  assert(db);
-
-  // Create a table with the default options.
-  auto table = db->create_table(&error, "Table");
-  assert(table);
-
-  // Create a column.
-  auto column = table->create_column(&error, "Int", grnxx::INT_DATA);
-  assert(column);
-
-  // Generate random values.
-  // Int: [0, 100).
-  grnxx::Array<grnxx::Int> values;
-  assert(values.resize(&error, NUM_ROWS + 1));
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    values.set(i, mersenne_twister() % 100);
-  }
-
-  // Store generated values into columns.
-  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
-    grnxx::Int row_id;
-    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
-                             grnxx::Datum(), &row_id));
-    assert(row_id == i);
-    assert(column->set(&error, row_id, values[i]));
-  }
-
-  // Create an index.
-  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
-  assert(index);
-
-  // Create a cursor.
-  auto cursor = index->find_in_range(&error);
-  assert(cursor);
-
-  grnxx::Array<grnxx::Record> records;
-  auto result = cursor->read_all(&error, &records);
-  assert(result.is_ok);
-  assert(result.count == NUM_ROWS);
-
-  constexpr grnxx::Int OFFSET = 1000;
-
-  // Create a cursor with an offset.
-  grnxx::CursorOptions options;
-  options.offset = OFFSET;
-  cursor = index->find_in_range(&error, grnxx::IndexRange(), options);
-
-  grnxx::Array<grnxx::Record> records_with_offset;
-  result = cursor->read_all(&error, &records_with_offset);
-  assert(result.is_ok);
-  assert(result.count == (NUM_ROWS - OFFSET));
-
-  for (grnxx::Int i = 0; i < records_with_offset.size(); ++i) {
-    assert(records.get_row_id(OFFSET + i) ==
-           records_with_offset.get_row_id(i));
-  }
-
-  constexpr grnxx::Int LIMIT = 100;
-
-  // Create a cursor with an offset and a limit.
-  options.limit = LIMIT;
-  cursor = index->find_in_range(&error, grnxx::IndexRange(), options);
-
-  grnxx::Array<grnxx::Record> records_with_offset_and_limit;
-  result = cursor->read_all(&error, &records_with_offset_and_limit);
-  assert(result.is_ok);
-  assert(result.count == LIMIT);
-
-  for (grnxx::Int i = 0; i < records_with_offset_and_limit.size(); ++i) {
-    assert(records.get_row_id(OFFSET + i) ==
-           records_with_offset_and_limit.get_row_id(i));
-  }
-}
+//void test_text_exact_match() {
+//  constexpr grnxx::Int NUM_ROWS = 1 << 16;
+
+//  grnxx::Error error;
+
+//  // Create a database with the default options.
+//  auto db = grnxx::open_db(&error, "");
+//  assert(db);
+
+//  // Create a table with the default options.
+//  auto table = db->create_table(&error, "Table");
+//  assert(table);
+
+//  // Create a column.
+//  auto column = table->create_column(&error, "Text", grnxx::TEXT_DATA);
+//  assert(column);
+
+//  // Create an index.
+//  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
+//  assert(index);
+
+//  // Generate random values.
+//  // Text: ["0", "99"].
+//  grnxx::Array<grnxx::Text> values;
+//  char bodies[100][3];
+//  assert(values.resize(&error, NUM_ROWS + 1));
+//  for (int i = 0; i < 100; ++i) {
+//    std::sprintf(bodies[i], "%d", i);
+//  }
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    values.set(i, bodies[mersenne_twister() % 100]);
+//  }
+
+//  // Store generated values into columns.
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    grnxx::Int row_id;
+//    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
+//                             grnxx::Datum(), &row_id));
+//    assert(row_id == i);
+//    assert(column->set(&error, row_id, values[i]));
+//  }
+
+//  // Test cursors for each value.
+//  for (int int_value = 0; int_value < 100; ++int_value) {
+//    grnxx::Text value = bodies[int_value];
+
+//    auto cursor = index->find(&error, value);
+//    assert(cursor);
+
+//    grnxx::Array<grnxx::Record> records;
+//    auto result = cursor->read_all(&error, &records);
+//    assert(result.is_ok);
+//    for (grnxx::Int i = 1; i < records.size(); ++i) {
+//      assert(values[records.get_row_id(i)] == value);
+//    }
+
+//    grnxx::Int count = 0;
+//    for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//      if (values[i] == value) {
+//        ++count;
+//      }
+//    }
+//    assert(count == records.size());
+//  }
+//}
+
+//void test_int_range() {
+//  constexpr grnxx::Int NUM_ROWS = 1 << 16;
+
+//  grnxx::Error error;
+
+//  // Create a database with the default options.
+//  auto db = grnxx::open_db(&error, "");
+//  assert(db);
+
+//  // Create a table with the default options.
+//  auto table = db->create_table(&error, "Table");
+//  assert(table);
+
+//  // Create a column.
+//  auto column = table->create_column(&error, "Int", grnxx::INT_DATA);
+//  assert(column);
+
+//  // Create an index.
+//  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
+//  assert(index);
+
+//  // Generate random values.
+//  // Int: [0, 100).
+//  grnxx::Array<grnxx::Int> values;
+//  assert(values.resize(&error, NUM_ROWS + 1));
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    values.set(i, mersenne_twister() % 100);
+//  }
+
+//  // Store generated values into columns.
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    grnxx::Int row_id;
+//    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
+//                             grnxx::Datum(), &row_id));
+//    assert(row_id == i);
+//    assert(column->set(&error, row_id, values[i]));
+//  }
+
+//  // Create a cursor.
+//  grnxx::IndexRange range;
+//  range.set_lower_bound(grnxx::Int(10), grnxx::INCLUSIVE_END_POINT);
+//  range.set_upper_bound(grnxx::Int(90), grnxx::EXCLUSIVE_END_POINT);
+//  auto cursor = index->find_in_range(&error, range);
+//  assert(cursor);
+
+//  grnxx::Array<grnxx::Record> records;
+//  auto result = cursor->read_all(&error, &records);
+//  assert(result.is_ok);
+//  for (grnxx::Int i = 1; i < records.size(); ++i) {
+//    assert(values[records.get_row_id(i - 1)] <= values[records.get_row_id(i)]);
+//  }
+
+//  grnxx::Int count = 0;
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    if ((values[i] >= 10) && (values[i] < 90)) {
+//      ++count;
+//    }
+//  }
+//  assert(count == records.size());
+//}
+
+//void test_float_range() {
+//  constexpr grnxx::Int NUM_ROWS = 1 << 16;
+
+//  grnxx::Error error;
+
+//  // Create a database with the default options.
+//  auto db = grnxx::open_db(&error, "");
+//  assert(db);
+
+//  // Create a table with the default options.
+//  auto table = db->create_table(&error, "Table");
+//  assert(table);
+
+//  // Create a column.
+//  auto column = table->create_column(&error, "Float", grnxx::FLOAT_DATA);
+//  assert(column);
+
+//  // Create an index.
+//  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
+//  assert(index);
+
+//  // Generate random values.
+//  // Float: [0.0, 1.0).
+//  grnxx::Array<grnxx::Float> values;
+//  assert(values.resize(&error, NUM_ROWS + 1));
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    values.set(i, (mersenne_twister() % 256) / 256.0);
+//  }
+
+//  // Store generated values into columns.
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    grnxx::Int row_id;
+//    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
+//                             grnxx::Datum(), &row_id));
+//    assert(row_id == i);
+//    assert(column->set(&error, row_id, values[i]));
+//  }
+
+//  // Create a cursor.
+//  grnxx::IndexRange range;
+//  range.set_lower_bound(grnxx::Float(64 / 256.0), grnxx::INCLUSIVE_END_POINT);
+//  range.set_upper_bound(grnxx::Float(192 / 256.0), grnxx::EXCLUSIVE_END_POINT);
+//  auto cursor = index->find_in_range(&error, range);
+//  assert(cursor);
+
+//  grnxx::Array<grnxx::Record> records;
+//  auto result = cursor->read_all(&error, &records);
+//  assert(result.is_ok);
+//  for (grnxx::Int i = 1; i < records.size(); ++i) {
+//    assert(values[records.get_row_id(i - 1)] <= values[records.get_row_id(i)]);
+//  }
+
+//  grnxx::Int count = 0;
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    if ((values[i] >= (64 / 256.0)) && (values[i] < (192 / 256.0))) {
+//      ++count;
+//    }
+//  }
+//  assert(count == records.size());
+//}
+
+//void test_text_range() {
+//  constexpr grnxx::Int NUM_ROWS = 1 << 16;
+
+//  grnxx::Error error;
+
+//  // Create a database with the default options.
+//  auto db = grnxx::open_db(&error, "");
+//  assert(db);
+
+//  // Create a table with the default options.
+//  auto table = db->create_table(&error, "Table");
+//  assert(table);
+
+//  // Create a column.
+//  auto column = table->create_column(&error, "Text", grnxx::TEXT_DATA);
+//  assert(column);
+
+//  // Create an index.
+//  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
+//  assert(index);
+
+//  // Generate random values.
+//  // Text: ["0", "99"].
+//  grnxx::Array<grnxx::Text> values;
+//  char bodies[100][3];
+//  assert(values.resize(&error, NUM_ROWS + 1));
+//  for (int i = 0; i < 100; ++i) {
+//    std::sprintf(bodies[i], "%d", i);
+//  }
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    values.set(i, bodies[mersenne_twister() % 100]);
+//  }
+
+//  // Store generated values into columns.
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    grnxx::Int row_id;
+//    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
+//                             grnxx::Datum(), &row_id));
+//    assert(row_id == i);
+//    assert(column->set(&error, row_id, values[i]));
+//  }
+
+//  // Create a cursor.
+//  grnxx::IndexRange range;
+//  range.set_lower_bound(grnxx::Text("25"), grnxx::EXCLUSIVE_END_POINT);
+//  range.set_upper_bound(grnxx::Text("75"), grnxx::INCLUSIVE_END_POINT);
+//  auto cursor = index->find_in_range(&error, range);
+//  assert(cursor);
+
+//  grnxx::Array<grnxx::Record> records;
+//  auto result = cursor->read_all(&error, &records);
+//  assert(result.is_ok);
+//  for (grnxx::Int i = 1; i < records.size(); ++i) {
+//    assert(values[records.get_row_id(i - 1)] <= values[records.get_row_id(i)]);
+//  }
+
+//  grnxx::Int count = 0;
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    if ((values[i] > "25") && (values[i] <= "75")) {
+//      ++count;
+//    }
+//  }
+//  assert(count == records.size());
+//}
+
+//bool inclusive_starts_with(const grnxx::Text &arg1, const grnxx::Text &arg2) {
+//  if (arg1.size() < arg2.size()) {
+//    return false;
+//  }
+//  for (grnxx::Int i = 0; i < arg2.size(); ++i) {
+//    if (arg1[i] != arg2[i]) {
+//      return false;
+//    }
+//  }
+//  return true;
+//}
+
+//bool exclusive_starts_with(const grnxx::Text &arg1, const grnxx::Text &arg2) {
+//  if (arg1.size() <= arg2.size()) {
+//    return false;
+//  }
+//  for (grnxx::Int i = 0; i < arg2.size(); ++i) {
+//    if (arg1[i] != arg2[i]) {
+//      return false;
+//    }
+//  }
+//  return true;
+//}
+
+//void test_text_find_starts_with() {
+//  constexpr grnxx::Int NUM_ROWS = 1 << 16;
+
+//  grnxx::Error error;
+
+//  // Create a database with the default options.
+//  auto db = grnxx::open_db(&error, "");
+//  assert(db);
+
+//  // Create a table with the default options.
+//  auto table = db->create_table(&error, "Table");
+//  assert(table);
+
+//  // Create a column.
+//  auto column = table->create_column(&error, "Text", grnxx::TEXT_DATA);
+//  assert(column);
+
+//  // Create an index.
+//  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
+//  assert(index);
+
+//  // Generate random values.
+//  // Text: ["0", "99"].
+//  grnxx::Array<grnxx::Text> values;
+//  char bodies[100][3];
+//  assert(values.resize(&error, NUM_ROWS + 1));
+//  for (int i = 0; i < 100; ++i) {
+//    std::sprintf(bodies[i], "%d", i);
+//  }
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    values.set(i, bodies[mersenne_twister() % 100]);
+//  }
+
+//  // Store generated values into columns.
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    grnxx::Int row_id;
+//    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
+//                             grnxx::Datum(), &row_id));
+//    assert(row_id == i);
+//    assert(column->set(&error, row_id, values[i]));
+//  }
+
+//  // Test cursors for each value.
+//  for (int int_value = 0; int_value < 100; ++int_value) {
+//    grnxx::Text value = bodies[int_value];
+
+//    grnxx::EndPoint prefix;
+//    prefix.value = value;
+//    prefix.type = grnxx::INCLUSIVE_END_POINT;
+//    auto cursor = index->find_starts_with(&error, prefix);
+//    assert(cursor);
+
+//    grnxx::Array<grnxx::Record> records;
+//    auto result = cursor->read_all(&error, &records);
+//    assert(result.is_ok);
+//    for (grnxx::Int i = 1; i < records.size(); ++i) {
+//      assert(inclusive_starts_with(values[records.get_row_id(i)], value));
+//    }
+
+//    grnxx::Int count = 0;
+//    for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//      if (inclusive_starts_with(values[i], value)) {
+//        ++count;
+//      }
+//    }
+//    assert(count == records.size());
+//  }
+
+//  // Test cursors for each value.
+//  for (int int_value = 0; int_value < 100; ++int_value) {
+//    grnxx::Text value = bodies[int_value];
+
+//    grnxx::EndPoint prefix;
+//    prefix.value = value;
+//    prefix.type = grnxx::EXCLUSIVE_END_POINT;
+//    auto cursor = index->find_starts_with(&error, prefix);
+//    assert(cursor);
+
+//    grnxx::Array<grnxx::Record> records;
+//    auto result = cursor->read_all(&error, &records);
+//    assert(result.is_ok);
+//    for (grnxx::Int i = 1; i < records.size(); ++i) {
+//      assert(exclusive_starts_with(values[records.get_row_id(i)], value));
+//    }
+
+//    grnxx::Int count = 0;
+//    for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//      if (exclusive_starts_with(values[i], value)) {
+//        ++count;
+//      }
+//    }
+//    assert(count == records.size());
+//  }
+//}
+
+//void test_text_find_prefixes() {
+//  constexpr grnxx::Int NUM_ROWS = 1 << 16;
+
+//  grnxx::Error error;
+
+//  // Create a database with the default options.
+//  auto db = grnxx::open_db(&error, "");
+//  assert(db);
+
+//  // Create a table with the default options.
+//  auto table = db->create_table(&error, "Table");
+//  assert(table);
+
+//  // Create a column.
+//  auto column = table->create_column(&error, "Text", grnxx::TEXT_DATA);
+//  assert(column);
+
+//  // Create an index.
+//  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
+//  assert(index);
+
+//  // Generate random values.
+//  // Text: ["0", "99"].
+//  grnxx::Array<grnxx::Text> values;
+//  char bodies[100][3];
+//  assert(values.resize(&error, NUM_ROWS + 1));
+//  for (int i = 0; i < 100; ++i) {
+//    std::sprintf(bodies[i], "%d", i);
+//  }
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    values.set(i, bodies[mersenne_twister() % 100]);
+//  }
+
+//  // Store generated values into columns.
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    grnxx::Int row_id;
+//    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
+//                             grnxx::Datum(), &row_id));
+//    assert(row_id == i);
+//    assert(column->set(&error, row_id, values[i]));
+//  }
+
+//  // Test cursors for each value.
+//  for (int int_value = 0; int_value < 100; ++int_value) {
+//    grnxx::Text value = bodies[int_value];
+//    auto cursor = index->find_prefixes(&error, value);
+//    assert(cursor);
+
+//    grnxx::Array<grnxx::Record> records;
+//    auto result = cursor->read_all(&error, &records);
+//    assert(result.is_ok);
+//    for (grnxx::Int i = 1; i < records.size(); ++i) {
+//      assert(inclusive_starts_with(value, values[records.get_row_id(i)]));
+//    }
+
+//    grnxx::Int count = 0;
+//    for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//      if (inclusive_starts_with(value, values[i])) {
+//        ++count;
+//      }
+//    }
+//    assert(count == records.size());
+//  }
+//}
+
+//void test_reverse() {
+//  constexpr grnxx::Int NUM_ROWS = 1 << 16;
+
+//  grnxx::Error error;
+
+//  // Create a database with the default options.
+//  auto db = grnxx::open_db(&error, "");
+//  assert(db);
+
+//  // Create a table with the default options.
+//  auto table = db->create_table(&error, "Table");
+//  assert(table);
+
+//  // Create a column.
+//  auto column = table->create_column(&error, "Int", grnxx::INT_DATA);
+//  assert(column);
+
+//  // Create an index.
+//  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
+//  assert(index);
+
+//  // Generate random values.
+//  // Int: [0, 100).
+//  grnxx::Array<grnxx::Int> values;
+//  assert(values.resize(&error, NUM_ROWS + 1));
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    values.set(i, mersenne_twister() % 100);
+//  }
+
+//  // Store generated values into columns.
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    grnxx::Int row_id;
+//    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
+//                             grnxx::Datum(), &row_id));
+//    assert(row_id == i);
+//    assert(column->set(&error, row_id, values[i]));
+//  }
+
+//  // Create a cursor.
+//  grnxx::IndexRange range;
+//  range.set_lower_bound(grnxx::Int(10), grnxx::INCLUSIVE_END_POINT);
+//  range.set_upper_bound(grnxx::Int(90), grnxx::EXCLUSIVE_END_POINT);
+//  grnxx::CursorOptions options;
+//  options.order_type = grnxx::REVERSE_ORDER;
+//  auto cursor = index->find_in_range(&error, range, options);
+//  assert(cursor);
+
+//  grnxx::Array<grnxx::Record> records;
+//  auto result = cursor->read_all(&error, &records);
+//  assert(result.is_ok);
+//  for (grnxx::Int i = 1; i < records.size(); ++i) {
+//    assert(values[records.get_row_id(i - 1)] >= values[records.get_row_id(i)]);
+//  }
+
+//  grnxx::Int count = 0;
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    if ((values[i] >= 10) && (values[i] < 90)) {
+//      ++count;
+//    }
+//  }
+//  assert(count == records.size());
+//}
+
+//void test_offset_and_limit() {
+//  constexpr grnxx::Int NUM_ROWS = 1 << 16;
+
+//  grnxx::Error error;
+
+//  // Create a database with the default options.
+//  auto db = grnxx::open_db(&error, "");
+//  assert(db);
+
+//  // Create a table with the default options.
+//  auto table = db->create_table(&error, "Table");
+//  assert(table);
+
+//  // Create a column.
+//  auto column = table->create_column(&error, "Int", grnxx::INT_DATA);
+//  assert(column);
+
+//  // Generate random values.
+//  // Int: [0, 100).
+//  grnxx::Array<grnxx::Int> values;
+//  assert(values.resize(&error, NUM_ROWS + 1));
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    values.set(i, mersenne_twister() % 100);
+//  }
+
+//  // Store generated values into columns.
+//  for (grnxx::Int i = 1; i <= NUM_ROWS; ++i) {
+//    grnxx::Int row_id;
+//    assert(table->insert_row(&error, grnxx::NULL_ROW_ID,
+//                             grnxx::Datum(), &row_id));
+//    assert(row_id == i);
+//    assert(column->set(&error, row_id, values[i]));
+//  }
+
+//  // Create an index.
+//  auto index = column->create_index(&error, "Index", grnxx::TREE_INDEX);
+//  assert(index);
+
+//  // Create a cursor.
+//  auto cursor = index->find_in_range(&error);
+//  assert(cursor);
+
+//  grnxx::Array<grnxx::Record> records;
+//  auto result = cursor->read_all(&error, &records);
+//  assert(result.is_ok);
+//  assert(result.count == NUM_ROWS);
+
+//  constexpr grnxx::Int OFFSET = 1000;
+
+//  // Create a cursor with an offset.
+//  grnxx::CursorOptions options;
+//  options.offset = OFFSET;
+//  cursor = index->find_in_range(&error, grnxx::IndexRange(), options);
+
+//  grnxx::Array<grnxx::Record> records_with_offset;
+//  result = cursor->read_all(&error, &records_with_offset);
+//  assert(result.is_ok);
+//  assert(result.count == (NUM_ROWS - OFFSET));
+
+//  for (grnxx::Int i = 0; i < records_with_offset.size(); ++i) {
+//    assert(records.get_row_id(OFFSET + i) ==
+//           records_with_offset.get_row_id(i));
+//  }
+
+//  constexpr grnxx::Int LIMIT = 100;
+
+//  // Create a cursor with an offset and a limit.
+//  options.limit = LIMIT;
+//  cursor = index->find_in_range(&error, grnxx::IndexRange(), options);
+
+//  grnxx::Array<grnxx::Record> records_with_offset_and_limit;
+//  result = cursor->read_all(&error, &records_with_offset_and_limit);
+//  assert(result.is_ok);
+//  assert(result.count == LIMIT);
+
+//  for (grnxx::Int i = 0; i < records_with_offset_and_limit.size(); ++i) {
+//    assert(records.get_row_id(OFFSET + i) ==
+//           records_with_offset_and_limit.get_row_id(i));
+//  }
+//}
 
 int main() {
   test_index();
@@ -987,20 +1054,20 @@ int main() {
   test_index_and_set();
   test_remove();
 
-  test_bool_exact_match();
+//  test_bool_exact_match();
   test_int_exact_match();
   test_float_exact_match();
   test_text_exact_match();
 
-  test_int_range();
-  test_float_range();
-  test_text_range();
+//  test_int_range();
+//  test_float_range();
+//  test_text_range();
 
-  test_text_find_starts_with();
-  test_text_find_prefixes();
+//  test_text_find_starts_with();
+//  test_text_find_prefixes();
 
-  test_reverse();
-  test_offset_and_limit();
+//  test_reverse();
+//  test_offset_and_limit();
 
   return 0;
 }
-------------- next part --------------
HTML����������������������������...
下载 



More information about the Groonga-commit mailing list
Back to archive index