susumu.yata
null+****@clear*****
Wed Mar 5 11:59:54 JST 2014
susumu.yata 2014-03-05 11:59:54 +0900 (Wed, 05 Mar 2014) New Revision: a289dca1706d48f8a65965bc2d8a607e95a078b4 https://github.com/groonga/grnxx/commit/a289dca1706d48f8a65965bc2d8a607e95a078b4 Message: Change the interface of RowIDCursor. Redmine: refs #2370. Modified files: lib/grnxx/index.cpp lib/grnxx/table.cpp lib/grnxx/table.hpp lib/grnxx/types.hpp src/grnxx.cpp test/test_grnxx.cpp Modified: lib/grnxx/index.cpp (+36 -40) =================================================================== --- lib/grnxx/index.cpp 2014-03-05 10:52:29 +0900 (32b2ff0) +++ lib/grnxx/index.cpp 2014-03-05 11:59:54 +0900 (01b9cbb) @@ -42,9 +42,9 @@ class TreeMapIndex : public Index { public: Cursor(typename Map::iterator begin, typename Map::iterator end); - // 行 ID を最大 limit 個取得して row_ids の末尾に追加し,取得した行 ID の数を返す. - // 取得できる行 ID が尽きたときは limit より小さい値を返す. - Int64 get_next(Int64 limit, std::vector<RowID> *row_ids); + // 行 ID を最大 size 個取得して buf に格納し,取得した行 ID の数を返す. + // buf が nullptr のときは取得した行 ID をそのまま捨てる. + Int64 get_next(RowID *buf, Int64 size); private: typename Map::iterator map_it_; @@ -57,9 +57,9 @@ class TreeMapIndex : public Index { public: ReverseCursor(typename Map::iterator begin, typename Map::iterator end); - // 行 ID を最大 limit 個取得して row_ids の末尾に追加し,取得した行 ID の数を返す. - // 取得できる行 ID が尽きたときは limit より小さい値を返す. - Int64 get_next(Int64 limit, std::vector<RowID> *row_ids); + // 行 ID を最大 size 個取得して buf に格納し,取得した行 ID の数を返す. + // buf が nullptr のときは取得した行 ID をそのまま捨てる. + Int64 get_next(RowID *buf, Int64 size); private: typename Map::reverse_iterator map_it_; @@ -189,16 +189,15 @@ TreeMapIndex<T>::Cursor::Cursor(typename Map::iterator begin, } } -// 行 ID を最大 limit 個取得して row_ids の末尾に追加し,取得した行 ID の数を返す. -// 取得できる行 ID が尽きたときは limit より小さい値を返す. +// 行 ID を最大 size 個取得して buf に格納し,取得した行 ID の数を返す. +// buf が nullptr のときは取得した行 ID をそのまま捨てる. template <typename T> -Int64 TreeMapIndex<T>::Cursor::get_next(Int64 limit, - std::vector<RowID> *row_ids) { +Int64 TreeMapIndex<T>::Cursor::get_next(RowID *buf, Int64 size) { if (map_it_ == map_end_) { return 0; } Int64 count = 0; - while (count < limit) { + while (count < size) { if (set_it_ == set_end_) { ++map_it_; if (map_it_ == map_end_) { @@ -207,8 +206,8 @@ Int64 TreeMapIndex<T>::Cursor::get_next(Int64 limit, set_it_ = map_it_->second.begin(); set_end_ = map_it_->second.end(); } - if (row_ids) { - row_ids->push_back(*set_it_); + if (buf) { + buf[count] = *set_it_; } ++set_it_; ++count; @@ -230,16 +229,15 @@ TreeMapIndex<T>::ReverseCursor::ReverseCursor(typename Map::iterator begin, } } -// 行 ID を最大 limit 個取得して row_ids の末尾に追加し,取得した行 ID の数を返す. -// 取得できる行 ID が尽きたときは limit より小さい値を返す. +// 行 ID を最大 size 個取得して buf に格納し,取得した行 ID の数を返す. +// buf が nullptr のときは取得した行 ID をそのまま捨てる. template <typename T> -Int64 TreeMapIndex<T>::ReverseCursor::get_next(Int64 limit, - std::vector<RowID> *row_ids) { +Int64 TreeMapIndex<T>::ReverseCursor::get_next(RowID *buf, Int64 size) { if (map_it_ == map_end_) { return 0; } Int64 count = 0; - while (count < limit) { + while (count < size) { if (set_it_ == set_end_) { ++map_it_; if (map_it_ == map_end_) { @@ -248,8 +246,8 @@ Int64 TreeMapIndex<T>::ReverseCursor::get_next(Int64 limit, set_it_ = map_it_->second.begin(); set_end_ = map_it_->second.end(); } - if (row_ids) { - row_ids->push_back(*set_it_); + if (buf) { + buf[count] = *set_it_; } ++set_it_; ++count; @@ -306,9 +304,9 @@ class TreeMapIndex<String> : public Index { public: Cursor(Map::iterator begin, Map::iterator end); - // 行 ID を最大 limit 個取得して row_ids の末尾に追加し,取得した行 ID の数を返す. - // 取得できる行 ID が尽きたときは limit より小さい値を返す. - Int64 get_next(Int64 limit, std::vector<RowID> *row_ids); + // 行 ID を最大 size 個取得して buf に格納し,取得した行 ID の数を返す. + // buf が nullptr のときは取得した行 ID をそのまま捨てる. + Int64 get_next(RowID *buf, Int64 size); private: Map::iterator map_it_; @@ -321,9 +319,9 @@ class TreeMapIndex<String> : public Index { public: ReverseCursor(Map::iterator begin, Map::iterator end); - // 行 ID を最大 limit 個取得して row_ids の末尾に追加し,取得した行 ID の数を返す. - // 取得できる行 ID が尽きたときは limit より小さい値を返す. - Int64 get_next(Int64 limit, std::vector<RowID> *row_ids); + // 行 ID を最大 size 個取得して buf に格納し,取得した行 ID の数を返す. + // buf が nullptr のときは取得した行 ID をそのまま捨てる. + Int64 get_next(RowID *buf, Int64 size); private: Map::reverse_iterator map_it_; @@ -447,15 +445,14 @@ TreeMapIndex<String>::Cursor::Cursor(Map::iterator begin, Map::iterator end) } } -// 行 ID を最大 limit 個取得して row_ids の末尾に追加し,取得した行 ID の数を返す. -// 取得できる行 ID が尽きたときは limit より小さい値を返す. -Int64 TreeMapIndex<String>::Cursor::get_next(Int64 limit, - std::vector<RowID> *row_ids) { +// 行 ID を最大 size 個取得して buf に格納し,取得した行 ID の数を返す. +// buf が nullptr のときは取得した行 ID をそのまま捨てる. +Int64 TreeMapIndex<String>::Cursor::get_next(RowID *buf, Int64 size) { if (map_it_ == map_end_) { return 0; } Int64 count = 0; - while (count < limit) { + while (count < size) { if (set_it_ == set_end_) { ++map_it_; if (map_it_ == map_end_) { @@ -464,8 +461,8 @@ Int64 TreeMapIndex<String>::Cursor::get_next(Int64 limit, set_it_ = map_it_->second.begin(); set_end_ = map_it_->second.end(); } - if (row_ids) { - row_ids->push_back(*set_it_); + if (buf) { + buf[count] = *set_it_; } ++set_it_; ++count; @@ -486,15 +483,14 @@ TreeMapIndex<String>::ReverseCursor::ReverseCursor(Map::iterator begin, } } -// 行 ID を最大 limit 個取得して row_ids の末尾に追加し,取得した行 ID の数を返す. -// 取得できる行 ID が尽きたときは limit より小さい値を返す. -Int64 TreeMapIndex<String>::ReverseCursor::get_next( - Int64 limit, std::vector<RowID> *row_ids) { +// 行 ID を最大 size 個取得して buf に格納し,取得した行 ID の数を返す. +// buf が nullptr のときは取得した行 ID をそのまま捨てる. +Int64 TreeMapIndex<String>::ReverseCursor::get_next(RowID *buf, Int64 size) { if (map_it_ == map_end_) { return 0; } Int64 count = 0; - while (count < limit) { + while (count < size) { if (set_it_ == set_end_) { ++map_it_; if (map_it_ == map_end_) { @@ -503,8 +499,8 @@ Int64 TreeMapIndex<String>::ReverseCursor::get_next( set_it_ = map_it_->second.begin(); set_end_ = map_it_->second.end(); } - if (row_ids) { - row_ids->push_back(*set_it_); + if (buf) { + buf[count] = *set_it_; } ++set_it_; ++count; Modified: lib/grnxx/table.cpp (+8 -17) =================================================================== --- lib/grnxx/table.cpp 2014-03-05 10:52:29 +0900 (d88c10c) +++ lib/grnxx/table.cpp 2014-03-05 11:59:54 +0900 (a9303b4) @@ -223,32 +223,23 @@ Table::Cursor::Cursor(RowID range_min, RowID range_max) row_id_(range_min), max_row_id_(range_max) {} -// 行 ID を最大 limit 個取得して row_ids の末尾に追加し,取得した行 ID の数を返す. -// 取得できる行 ID が尽きたときは limit より小さい値を返す. -Int64 Table::Cursor::get_next(Int64 limit, std::vector<RowID> *row_ids) { - if (limit > (max_row_id_ - row_id_)) { - limit = (max_row_id_ - row_id_) + 1; - } - if (limit <= 0) { - return 0; - } - if (row_ids) { +// 行 ID を最大 size 個取得して buf に格納し,取得した行 ID の数を返す. +// buf が nullptr のときは取得した行 ID をそのまま捨てる. +Int64 Table::Cursor::get_next(RowID *buf, Int64 size) { + if (buf) { Int64 count = 0; - Int64 offset = row_ids->size(); - row_ids->resize(offset + limit); - while ((count < limit) && (row_id_ <= max_row_id_)) { - (*row_ids)[offset + count] = row_id_; + while ((count < size) && (row_id_ <= max_row_id_)) { + buf[count] = row_id_; ++row_id_; ++count; } - row_ids->resize(offset + count); return count; } else { Int64 count; - if (limit > (max_row_id_ - row_id_ + 1)) { + if (size > (max_row_id_ - row_id_ + 1)) { count = max_row_id_ - row_id_ + 1; } else { - count = limit; + count = size; } row_id_ += count; return count; Modified: lib/grnxx/table.hpp (+3 -3) =================================================================== --- lib/grnxx/table.hpp 2014-03-05 10:52:29 +0900 (e7124c7) +++ lib/grnxx/table.hpp 2014-03-05 11:59:54 +0900 (8b019cd) @@ -109,9 +109,9 @@ class Table { // 指定されたテーブルの範囲内にある行 ID を取得するようにカーソルを初期化する. Cursor(RowID range_min, RowID range_max); - // 行 ID を最大 limit 個取得して row_ids の末尾に追加し,取得した行 ID の数を返す. - // 取得できる行 ID が尽きたときは limit より小さい値を返す. - Int64 get_next(Int64 limit, std::vector<RowID> *row_ids); + // 行 ID を最大 size 個取得して buf に格納し,取得した行 ID の数を返す. + // buf が nullptr のときは取得した行 ID をそのまま捨てる. + Int64 get_next(RowID *buf, Int64 size); private: RowID row_id_; Modified: lib/grnxx/types.hpp (+3 -3) =================================================================== --- lib/grnxx/types.hpp 2014-03-05 10:52:29 +0900 (3fd02d1) +++ lib/grnxx/types.hpp 2014-03-05 11:59:54 +0900 (f8a1d78) @@ -63,9 +63,9 @@ class RowIDCursor { // カーソルを破棄する. virtual ~RowIDCursor() {} - // 行 ID を最大 limit 個取得して row_ids の末尾に追加し,取得した行 ID の数を返す. - // 取得できる行 ID が尽きたときは limit より小さい値を返す. - virtual Int64 get_next(Int64 limit, std::vector<RowID> *row_ids) = 0; + // 行 ID を最大 size 個取得して buf に格納し,取得した行 ID の数を返す. + // buf が nullptr のときは取得した行 ID をそのまま捨てる. + virtual Int64 get_next(RowID *buf, Int64 size) = 0; }; // データ型の種類. Modified: src/grnxx.cpp (+33 -12) =================================================================== --- src/grnxx.cpp 2014-03-05 10:52:29 +0900 (371d8d2) +++ src/grnxx.cpp 2014-03-05 11:59:54 +0900 (0d5a472) @@ -750,15 +750,33 @@ bool run_select(grnxx::Database *database, const grnxx::String ¶ms, // 整列条件がなければ offset, limit を考慮する. if (calc->empty()) { // 検索条件がなければ,先頭の offset 件をスキップした後, - // limit 件を取り出して終了する. - cursor->get_next(query.offset, nullptr); - cursor->get_next(query.limit, &row_ids); + // 最大 limit 件を取り出して終了する. + cursor->get_next(nullptr, query.offset); + grnxx::Int64 num_rows = 0; + while (num_rows < query.limit) { + grnxx::Int64 limit_left = query.limit - num_rows; + grnxx::Int64 block_size = + (limit_left < BLOCK_SIZE) ? limit_left : BLOCK_SIZE; + row_ids.resize(num_rows + block_size); + grnxx::Int64 num_new_rows = + cursor->get_next(&row_ids[num_rows], block_size); + num_rows += num_new_rows; + if (num_new_rows < block_size) { + break; + } + } + row_ids.resize(num_rows); } else { // 検索条件があればブロック単位でフィルタにかける. grnxx::Int64 num_rows = 0; grnxx::Int64 offset_left = query.offset; - grnxx::Int64 num_new_rows; - while ((num_new_rows = cursor->get_next(BLOCK_SIZE, &row_ids)) != 0) { + for ( ; ; ) { + row_ids.resize(num_rows + BLOCK_SIZE); + grnxx::Int64 num_new_rows = + cursor->get_next(&row_ids[num_rows], BLOCK_SIZE); + if (num_new_rows == 0) { + break; + } num_filtered_rows += num_new_rows; num_new_rows = calc->filter(&row_ids[num_rows], num_new_rows); if (offset_left != 0) { @@ -775,22 +793,25 @@ bool run_select(grnxx::Database *database, const grnxx::String ¶ms, } num_rows += num_new_rows; if (num_rows >= query.limit) { - row_ids.resize(query.limit); + num_rows = query.limit; break; } - row_ids.resize(num_rows); } + row_ids.resize(num_rows); } } else { // 整列条件が指定されているときは,後で offset, limit を適用する. grnxx::Int64 num_rows = 0; - grnxx::Int64 num_new_rows; - while ((num_new_rows = cursor->get_next(BLOCK_SIZE, &row_ids)) != 0) { - num_filtered_rows += num_new_rows; - num_new_rows = calc->filter(&row_ids[num_rows], num_new_rows); + for ( ; ; ) { + row_ids.resize(num_rows + BLOCK_SIZE); + grnxx::Int64 num_new_rows = + cursor->get_next(&row_ids[num_rows], BLOCK_SIZE); num_rows += num_new_rows; - row_ids.resize(num_rows); + if (num_new_rows < BLOCK_SIZE) { + break; + } } + row_ids.resize(num_rows); } if (verbose_mode) { Modified: test/test_grnxx.cpp (+39 -31) =================================================================== --- test/test_grnxx.cpp 2014-03-05 10:52:29 +0900 (439bf15) +++ test/test_grnxx.cpp 2014-03-05 11:59:54 +0900 (ae32917) @@ -145,9 +145,9 @@ void test_table() { std::unique_ptr<grnxx::RowIDCursor> cursor(table->create_cursor()); assert(cursor); - std::vector<grnxx::RowID> row_ids; - assert(cursor->get_next(10, &row_ids) == 10); - assert(cursor->get_next(100, &row_ids) == 90); + std::vector<grnxx::RowID> row_ids(110); + assert(cursor->get_next(&row_ids[0], 10) == 10); + assert(cursor->get_next(&row_ids[10], 100) == 90); for (grnxx::Int64 i = 0; i < 100; ++i) { assert(row_ids[i] == (grnxx::MIN_ROW_ID + i)); } @@ -255,9 +255,9 @@ void test_calc() { string_column->set(row_id, string_data[i]); } - std::vector<grnxx::RowID> all_row_ids; + std::vector<grnxx::RowID> all_row_ids(1000); std::unique_ptr<grnxx::RowIDCursor> cursor(table->create_cursor()); - assert(cursor->get_next(INT64_MAX, &all_row_ids) == 1000); + assert(cursor->get_next(&all_row_ids[0], 1000) == 1000); // 何もしない. { @@ -532,9 +532,9 @@ void test_sorter() { string_column->set(row_id, str); } - std::vector<grnxx::RowID> all_row_ids; + std::vector<grnxx::RowID> all_row_ids(DATA_SIZE); std::unique_ptr<grnxx::RowIDCursor> cursor(table->create_cursor()); - assert(cursor->get_next(INT64_MAX, &all_row_ids) == DATA_SIZE); + assert(cursor->get_next(&all_row_ids[0], DATA_SIZE) == DATA_SIZE); // Boolean を基準に整列する. { @@ -765,9 +765,9 @@ void test_sorter_large() { less_than_1000->set(row_id, random() % 1000); } - std::vector<grnxx::RowID> all_row_ids; + std::vector<grnxx::RowID> all_row_ids(DATA_SIZE); std::unique_ptr<grnxx::RowIDCursor> cursor(table->create_cursor()); - assert(cursor->get_next(INT64_MAX, &all_row_ids) == DATA_SIZE); + assert(cursor->get_next(&all_row_ids[0], DATA_SIZE) == DATA_SIZE); std::vector<grnxx::RowID> answer; { @@ -889,8 +889,8 @@ void test_index() { { std::unique_ptr<grnxx::RowIDCursor> cursor(integer_index->find_all()); assert(cursor); - std::vector<grnxx::RowID> row_ids; - assert(cursor->get_next(INT64_MAX, &row_ids) == 1000); + std::vector<grnxx::RowID> row_ids(1000); + assert(cursor->get_next(&row_ids[0], 1000) == 1000); auto value = integer_column->get(row_ids[0]); assert(value >= 0); assert(value < 100); @@ -910,8 +910,9 @@ void test_index() { integer_index->find_between(grnxx::Int64(30), grnxx::Int64(70), false, false)); assert(cursor); - std::vector<grnxx::RowID> row_ids; - assert(cursor->get_next(INT64_MAX, &row_ids) > 100); + std::vector<grnxx::RowID> row_ids(1000); + row_ids.resize(cursor->get_next(&row_ids[0], 1000)); + assert(row_ids.size() > 100); auto value = integer_column->get(row_ids[0]); assert(value > 30); assert(value < 70); @@ -931,8 +932,9 @@ void test_index() { integer_index->find_between(grnxx::Int64(30), grnxx::Int64(70), true, true)); assert(cursor); - std::vector<grnxx::RowID> row_ids; - assert(cursor->get_next(INT64_MAX, &row_ids) > 100); + std::vector<grnxx::RowID> row_ids(1000); + row_ids.resize(cursor->get_next(&row_ids[0], 1000)); + assert(row_ids.size() > 100); auto value = integer_column->get(row_ids[0]); assert(value >= 30); assert(value <= 70); @@ -951,8 +953,9 @@ void test_index() { std::unique_ptr<grnxx::RowIDCursor> cursor( float_index->find_between(0.3, 0.7)); assert(cursor); - std::vector<grnxx::RowID> row_ids; - assert(cursor->get_next(INT64_MAX, &row_ids) > 100); + std::vector<grnxx::RowID> row_ids(1000); + row_ids.resize(cursor->get_next(&row_ids[0], 1000)); + assert(row_ids.size() > 100); auto value = float_column->get(row_ids[0]); assert(value > 0.3); assert(value < 0.7); @@ -971,8 +974,9 @@ void test_index() { std::unique_ptr<grnxx::RowIDCursor> cursor( string_index->find_between("G", "P")); assert(cursor); - std::vector<grnxx::RowID> row_ids; - assert(cursor->get_next(INT64_MAX, &row_ids) > 100); + std::vector<grnxx::RowID> row_ids(1000); + row_ids.resize(cursor->get_next(&row_ids[0], 1000)); + assert(row_ids.size() > 100); auto value = string_column->get(row_ids[0]); assert(value > "G"); assert(value < "P"); @@ -990,8 +994,8 @@ void test_index() { { std::unique_ptr<grnxx::RowIDCursor> cursor(integer_index->find_all(true)); assert(cursor); - std::vector<grnxx::RowID> row_ids; - assert(cursor->get_next(INT64_MAX, &row_ids) == 1000); + std::vector<grnxx::RowID> row_ids(1000); + assert(cursor->get_next(&row_ids[0], 1000) == 1000); auto value = integer_column->get(row_ids[0]); assert(value >= 0); assert(value < 100); @@ -1011,8 +1015,9 @@ void test_index() { integer_index->find_between(grnxx::Int64(30), grnxx::Int64(70), false, false, true)); assert(cursor); - std::vector<grnxx::RowID> row_ids; - assert(cursor->get_next(INT64_MAX, &row_ids) > 100); + std::vector<grnxx::RowID> row_ids(1000); + row_ids.resize(cursor->get_next(&row_ids[0], 1000)); + assert(row_ids.size() > 100); auto value = integer_column->get(row_ids[0]); assert(value > 30); assert(value < 70); @@ -1032,8 +1037,9 @@ void test_index() { integer_index->find_between(grnxx::Int64(30), grnxx::Int64(70), true, true, true)); assert(cursor); - std::vector<grnxx::RowID> row_ids; - assert(cursor->get_next(INT64_MAX, &row_ids) > 100); + std::vector<grnxx::RowID> row_ids(1000); + row_ids.resize(cursor->get_next(&row_ids[0], 1000)); + assert(row_ids.size() > 100); auto value = integer_column->get(row_ids[0]); assert(value >= 30); assert(value <= 70); @@ -1052,8 +1058,9 @@ void test_index() { std::unique_ptr<grnxx::RowIDCursor> cursor( float_index->find_between(0.3, 0.7, false, false, true)); assert(cursor); - std::vector<grnxx::RowID> row_ids; - assert(cursor->get_next(INT64_MAX, &row_ids) > 100); + std::vector<grnxx::RowID> row_ids(1000); + row_ids.resize(cursor->get_next(&row_ids[0], 1000)); + assert(row_ids.size() > 100); auto value = float_column->get(row_ids[0]); assert(value > 0.3); assert(value < 0.7); @@ -1072,8 +1079,9 @@ void test_index() { std::unique_ptr<grnxx::RowIDCursor> cursor( string_index->find_between("G", "P", false, false, true)); assert(cursor); - std::vector<grnxx::RowID> row_ids; - assert(cursor->get_next(INT64_MAX, &row_ids) > 100); + std::vector<grnxx::RowID> row_ids(1000); + row_ids.resize(cursor->get_next(&row_ids[0], 1000)); + assert(row_ids.size() > 100); auto value = string_column->get(row_ids[0]); assert(value > "G"); assert(value < "P"); @@ -1091,8 +1099,8 @@ void test_index() { { std::unique_ptr<grnxx::RowIDCursor> cursor(integer_index->find_all()); assert(cursor); - std::vector<grnxx::RowID> ordered_row_ids; - assert(cursor->get_next(INT64_MAX, &ordered_row_ids) == 1000); + std::vector<grnxx::RowID> ordered_row_ids(1000); + assert(cursor->get_next(&ordered_row_ids[0], 1000) == 1000); std::unique_ptr<grnxx::Calc> calc( table->create_calc("(Boolean && Integer >= 50) || (String <= \"O\")")); assert(calc); -------------- next part -------------- HTML����������������������������... Download