[Groonga-commit] groonga/grnxx at 3b5523e [master] Add TreeIndex<Bool>. (#51)

Back to archive index

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 



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