susumu.yata
null+****@clear*****
Tue Sep 16 09:36:26 JST 2014
susumu.yata 2014-09-16 09:36:26 +0900 (Tue, 16 Sep 2014) New Revision: 4fd092dbe064a8bed3e3d40a2b658a9d799f14e5 https://github.com/groonga/grnxx/commit/4fd092dbe064a8bed3e3d40a2b658a9d799f14e5 Message: Add an inteface for exact match search. Modified files: include/grnxx/index.hpp lib/grnxx/index.cpp lib/grnxx/tree_index.hpp Modified: include/grnxx/index.hpp (+10 -0) =================================================================== --- include/grnxx/index.hpp 2014-09-12 18:10:15 +0900 (baeaa23) +++ include/grnxx/index.hpp 2014-09-16 09:36:26 +0900 (86f9c64) @@ -84,6 +84,16 @@ class Index { // Create a cursor to get records. // + // On success, returns a pointer to the cursor. + // On failure, returns nullptr and stores error information into "*error" if + // "error" != nullptr. + virtual unique_ptr<Cursor> create_cursor( + Error *error, + const Datum &datum, + const CursorOptions &options = CursorOptions()) const; + + // Create a cursor to get records. + // // Returns a pointer to the cursor on success. // On failure, returns nullptr and stores error information into "*error" if // "error" != nullptr. Modified: lib/grnxx/index.cpp (+163 -0) =================================================================== --- lib/grnxx/index.cpp 2014-09-12 18:10:15 +0900 (1309790) +++ lib/grnxx/index.cpp 2014-09-16 09:36:26 +0900 (6fbdd9a) @@ -14,6 +14,14 @@ Index::~Index() {} unique_ptr<Cursor> Index::create_cursor( Error *error, + const Datum &, + const CursorOptions &) const { + GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supoprted yet"); + return nullptr; +} + +unique_ptr<Cursor> Index::create_cursor( + Error *error, const IndexRange &, const CursorOptions &) const { GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supoprted yet"); @@ -79,6 +87,128 @@ bool Index::is_removable() { return true; } +// -- EmptyCursor -- + +class EmptyCursor : public Cursor { + public: + EmptyCursor(const Table *table) : Cursor(table) {} + + Int read(Error *error, Int max_count, Array<Record> *records); +}; + +Int EmptyCursor::read(Error *, Int, Array<Record> *) { + return 0; +} + +// Create an empty cursor. +unique_ptr<Cursor> create_empty_cursor(Error *error, const Table *table) { + unique_ptr<Cursor> cursor(new (nothrow) EmptyCursor(table)); + if (!cursor) { + GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); + return nullptr; + } + return cursor; +} + +// -- IteratorCursor -- + +template <typename T> +class IteratorCursor : public Cursor { + public: + using Iterator = T; + + IteratorCursor(const Table *table, + Iterator begin, + Iterator end, + Int offset, + Int limit) + : Cursor(table), + begin_(begin), + it_(begin), + end_(end), + offset_(offset), + limit_(limit), + offset_left_(offset), + limit_left_(limit) {} + ~IteratorCursor() {} + + Int read(Error *error, Int max_count, Array<Record> *records); + + private: + Iterator begin_; + Iterator it_; + Iterator end_; + Int offset_; + Int limit_; + Int offset_left_; + Int limit_left_; +}; + +template <typename T> +Int IteratorCursor<T>::read(Error *error, + Int max_count, + Array<Record> *records) { + while ((offset_left_ > 0) && (it_ != end_)) { + ++it_; + --offset_left_; + } + Int count = 0; + if (max_count > limit_left_) { + max_count = limit_left_; + } + while ((count < max_count) && (it_ != end_)) { + if (!records->push_back(error, Record(*it_, 0.0))) { + return -1; + } + ++count; + ++it_; + } + limit_left_ -= count; + return count; +} + +// Helper function to create an iterator cursor. +template <typename T> +unique_ptr<Cursor> create_iterator_cursor(Error *error, + const Table *table, + T begin, + T end, + Int offset, + Int limit) { + unique_ptr<Cursor> cursor( + new (nothrow) IteratorCursor<T>(table, begin, end, offset, limit)); + if (!cursor) { + GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); + return nullptr; + } + return cursor; +} + +// TODO: It's not clear that a reverse cursor should return row IDs in +// reverse order or not. +// +// Helper function to create a reverse iterator cursor. +template <typename T> +unique_ptr<Cursor> create_reverse_iterator_cursor(Error *error, + const Table *table, + T begin, + T end, + Int offset, + Int limit) { + using ReverseIterator = std::reverse_iterator<T>; + unique_ptr<Cursor> cursor( + new (nothrow) IteratorCursor<ReverseIterator>(table, + ReverseIterator(end), + ReverseIterator(begin), + offset, + limit)); + if (!cursor) { + GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); + return nullptr; + } + return cursor; +} + // -- TreeIndexRegularCursor -- template <typename T> class TreeIndexRegularCursor; @@ -240,6 +370,39 @@ TreeIndex<Int>::~TreeIndex() {} unique_ptr<Cursor> TreeIndex<Int>::create_cursor( Error *error, + const Datum &datum, + const CursorOptions &options) const { + if (datum.type() != INT_DATA) { + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Data type conflict"); + return nullptr; + } + + auto map_it = map_.find(datum.force_int()); + if (map_it == map_.end()) { + return create_empty_cursor(error, column_->table()); + } else { + auto set_begin = map_it->second.begin(); + auto set_end = map_it->second.end(); + if (options.order_type == REGULAR_ORDER) { + return create_iterator_cursor(error, + column_->table(), + set_begin, + set_end, + options.offset, + options.limit); + } else { + return create_reverse_iterator_cursor(error, + column_->table(), + set_begin, + set_end, + options.offset, + options.limit); + } + } +} + +unique_ptr<Cursor> TreeIndex<Int>::create_cursor( + Error *error, const IndexRange &range, const CursorOptions &options) const { Int lower_bound_value = numeric_limits<Int>::min(); Modified: lib/grnxx/tree_index.hpp (+5 -0) =================================================================== --- lib/grnxx/tree_index.hpp 2014-09-12 18:10:15 +0900 (c126b53) +++ lib/grnxx/tree_index.hpp 2014-09-16 09:36:26 +0900 (fb87673) @@ -28,6 +28,11 @@ class TreeIndex<Int> : public Index { unique_ptr<Cursor> create_cursor( Error *error, + const Datum &datum, + const CursorOptions &options = CursorOptions()) const; + + unique_ptr<Cursor> create_cursor( + Error *error, const IndexRange &range, const CursorOptions &options) const; -------------- next part -------------- HTML����������������������������...Download