susumu.yata
null+****@clear*****
Tue Sep 16 13:22:50 JST 2014
susumu.yata 2014-09-16 13:22:50 +0900 (Tue, 16 Sep 2014) New Revision: 3b5523e898b26cd7464b22d46fb9f406140fba63 https://github.com/groonga/grnxx/commit/3b5523e898b26cd7464b22d46fb9f406140fba63 Message: Add TreeIndex<Bool>. (#51) Modified files: lib/grnxx/index.cpp lib/grnxx/tree_index.hpp Modified: lib/grnxx/index.cpp (+162 -2) =================================================================== --- lib/grnxx/index.cpp 2014-09-16 11:32:48 +0900 (42d5a2b) +++ lib/grnxx/index.cpp 2014-09-16 13:22:50 +0900 (6e6fdf0) @@ -57,8 +57,7 @@ unique_ptr<Index> Index::create(Error *error, } switch (column->data_type()) { case BOOL_DATA: { - GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supoprted yet"); - return nullptr; + return TreeIndex<Bool>::create(error, column, name, options); } case INT_DATA: { return TreeIndex<Int>::create(error, column, name, options); @@ -339,6 +338,167 @@ unique_ptr<Cursor> create_reverse_map_set_cursor(Error *error, return cursor; } +// -- TreeIndex<Bool> -- + +unique_ptr<TreeIndex<Bool>> TreeIndex<Bool>::create( + Error *error, + Column *column, + String name, + const IndexOptions &options) { + unique_ptr<TreeIndex> index(new (nothrow) TreeIndex); + if (!index) { + GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); + return nullptr; + } + if (!index->initialize_base(error, column, name, TREE_INDEX, options)) { + return nullptr; + } + auto cursor = column->table()->create_cursor(error); + if (!cursor) { + return nullptr; + } + auto typed_column = static_cast<ColumnImpl<Bool> *>(column); + Array<Record> records; + for ( ; ; ) { + Int count = cursor->read(error, 1024, &records); + if (count < 0) { + return nullptr; + } else if (count == 0) { + break; + } + for (Int i = 0; i < count; ++i) { + Int row_id = records.get_row_id(i); + if (!index->insert(error, row_id, typed_column->get(row_id))) { + return nullptr; + } + } + records.clear(); + } + return index; +} + +TreeIndex<Bool>::~TreeIndex() {} + +unique_ptr<Cursor> TreeIndex<Bool>::create_cursor( + Error *error, + const Datum &datum, + const CursorOptions &options) const { + if (datum.type() != BOOL_DATA) { + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Data type conflict"); + return nullptr; + } + + auto map_it = map_.find(datum.force_bool()); + 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<Bool>::create_cursor( + Error *error, + const IndexRange &range, + const CursorOptions &options) const { + Bool lower_bound_value = false; + if (range.has_lower_bound()) { + const EndPoint &lower_bound = range.lower_bound(); + if (lower_bound.value.type() != BOOL_DATA) { + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Data type conflict"); + return nullptr; + } + lower_bound_value = lower_bound.value.force_bool(); + if (lower_bound.type == EXCLUSIVE_END_POINT) { + if (lower_bound_value) { + // TODO: Invalid range. + return nullptr; + } + lower_bound_value = true; + } + } + + Bool upper_bound_value = true; + if (range.has_upper_bound()) { + const EndPoint &upper_bound = range.upper_bound(); + if (upper_bound.value.type() != BOOL_DATA) { + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Data type conflict"); + return nullptr; + } + upper_bound_value = upper_bound.value.force_bool(); + if (upper_bound.type == EXCLUSIVE_END_POINT) { + if (!upper_bound_value) { + // TODO: Invalid range. + return nullptr; + } + upper_bound_value = false; + } + } + + if (lower_bound_value > upper_bound_value) { + // TODO: Invalid range. + return nullptr; + } + + auto begin = map_.lower_bound(lower_bound_value); + auto end = map_.upper_bound(upper_bound_value); + if (options.order_type == REGULAR_ORDER) { + return create_map_set_cursor(error, + column_->table(), + begin, + end, + options.offset, + options.limit); + } else { + return create_reverse_map_set_cursor(error, + column_->table(), + begin, + end, + options.offset, + options.limit); + } +} + +bool TreeIndex<Bool>::insert(Error *, Int row_id, const Datum &value) { + auto result = map_[value.force_bool()].insert(row_id); + if (!result.second) { + // Already exists. + return false; + } + return true; +} + +bool TreeIndex<Bool>::remove(Error *, Int row_id, const Datum &value) { + auto map_it = map_.find(value.force_bool()); + if (map_it == map_.end()) { + return false; + } + auto set_it = map_it->second.find(row_id); + if (set_it == map_it->second.end()) { + return false; + } + map_it->second.erase(set_it); + if (map_it->second.size() == 0) { + map_.erase(map_it); + } + return true; +} + // -- TreeIndex<Int> -- unique_ptr<TreeIndex<Int>> TreeIndex<Int>::create( Modified: lib/grnxx/tree_index.hpp (+34 -0) =================================================================== --- lib/grnxx/tree_index.hpp 2014-09-16 11:32:48 +0900 (f665232) +++ lib/grnxx/tree_index.hpp 2014-09-16 13:22:50 +0900 (3f63270) @@ -12,6 +12,40 @@ namespace grnxx { template <typename T> class TreeIndex; +// TODO: This is a test implementation. +template <> +class TreeIndex<Bool> : public Index { + public: + using Value = Bool; + using Set = std::set<Int>; + using Map = std::map<Value, Set>; + + static unique_ptr<TreeIndex> create(Error *error, + Column *column, + String name, + const IndexOptions &options); + + ~TreeIndex(); + + 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; + + bool insert(Error *error, Int row_id, const Datum &value); + bool remove(Error *error, Int row_id, const Datum &value); + + private: + mutable Map map_; + + TreeIndex() : Index(), map_() {} +}; + // TODO: This is just a test implementation. template <> class TreeIndex<Int> : public Index { -------------- next part -------------- HTML����������������������������...Download