[Groonga-commit] groonga/grnxx at 0e6ce6d [master] Add Index::find_prefixes(). (#52)

Back to archive index

susumu.yata null+****@clear*****
Wed Sep 17 16:48:07 JST 2014


susumu.yata	2014-09-17 16:48:07 +0900 (Wed, 17 Sep 2014)

  New Revision: 0e6ce6d00d8ef2300f6ce5e93666aafb4c754466
  https://github.com/groonga/grnxx/commit/0e6ce6d00d8ef2300f6ce5e93666aafb4c754466

  Message:
    Add Index::find_prefixes(). (#52)

  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-17 14:17:10 +0900 (32ff2e0)
+++ include/grnxx/index.hpp    2014-09-17 16:48:07 +0900 (403fe72)
@@ -112,6 +112,16 @@ class Index {
       const EndPoint &prefix,
       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.
+  virtual unique_ptr<Cursor> find_prefixes(
+      Error *error,
+      const Datum &datum,
+      const CursorOptions &options = CursorOptions()) const;
+
   // Insert a new entry.
   //
   // On success, returns true.

  Modified: lib/grnxx/index.cpp (+117 -0)
===================================================================
--- lib/grnxx/index.cpp    2014-09-17 14:17:10 +0900 (ca9f249)
+++ lib/grnxx/index.cpp    2014-09-17 16:48:07 +0900 (72991e1)
@@ -36,6 +36,14 @@ unique_ptr<Cursor> Index::find_starts_with(
   return nullptr;
 }
 
+unique_ptr<Cursor> Index::find_prefixes(
+    Error *error,
+    const Datum &,
+    const CursorOptions &) const {
+  GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supoprted yet");
+  return nullptr;
+}
+
 Index::Index()
     : column_(nullptr),
       name_(),
@@ -351,6 +359,83 @@ unique_ptr<Cursor> create_reverse_map_set_cursor(Error *error,
   return cursor;
 }
 
+// -- ArrayCursor --
+
+class ArrayCursor : public Cursor {
+ public:
+  using Set = std::set<Int>;
+  using Map = std::map<std::string, Set>;
+
+  ArrayCursor(const Table *table,
+              Array<Map::iterator> &&array,
+              Int offset,
+              Int limit)
+      : Cursor(table),
+        array_(std::move(array)),
+        pos_(0),
+        it_(),
+        end_(),
+        offset_(offset),
+        limit_(limit),
+        offset_left_(offset),
+        limit_left_(limit) {
+    if (array_.size() != 0) {
+      it_ = array_[0]->second.begin();
+      end_ = array_[0]->second.end();
+    }
+  }
+  ~ArrayCursor() {}
+
+  Int read(Error *error, Int max_count, Array<Record> *records);
+
+ private:
+  Array<Map::iterator> array_;
+  Int pos_;
+  Set::iterator it_;
+  Set::iterator end_;
+  Int offset_;
+  Int limit_;
+  Int offset_left_;
+  Int limit_left_;
+};
+
+Int ArrayCursor::read(Error *error,
+                      Int max_count,
+                      Array<Record> *records) {
+  if (max_count > limit_left_) {
+    max_count = limit_left_;
+  }
+  if (max_count <= 0) {
+    return 0;
+  }
+  Int count = 0;
+  while ((count < max_count) && (pos_ < array_.size())) {
+    if (it_ == end_) {
+      ++pos_;
+      if (pos_ >= array_.size()) {
+        break;
+      }
+      it_ = array_[pos_]->second.begin();
+      end_ = array_[pos_]->second.end();
+      if (it_ == end_) {
+        continue;
+      }
+    }
+
+    if (offset_left_ > 0) {
+      --offset_left_;
+    } else {
+      if (!records->push_back(error, Record(*it_, 0.0))) {
+        return -1;
+      }
+      ++count;
+    }
+    ++it_;
+  }
+  limit_left_ -= count;
+  return count;
+}
+
 // -- TreeIndex<Bool> --
 
 unique_ptr<TreeIndex<Bool>> TreeIndex<Bool>::create(
@@ -1016,6 +1101,38 @@ unique_ptr<Cursor> TreeIndex<Text>::find_starts_with(
   }
 }
 
+unique_ptr<Cursor> TreeIndex<Text>::find_prefixes(
+    Error *error,
+    const Datum &prefix,
+    const CursorOptions &options) const {
+  Text prefix_text = prefix.force_text();
+  std::string value(prefix_text.data(), prefix_text.size());
+  Array<Map::iterator> array;
+  for (std::size_t i = 0; i <= value.size(); ++i) {
+    auto it = map_.find(value.substr(0, i));
+    if (it != map_.end()) {
+      if (!array.push_back(error, it)) {
+        return nullptr;
+      }
+    }
+  }
+  if (options.order_type == REVERSE_ORDER) {
+    for (Int i = 0; i < (array.size() / 2); ++i) {
+      Map::iterator temp = array[i];
+      array[i] = array[array.size() - i - 1];
+      array[array.size() - i - 1] = temp;
+    }
+  }
+  unique_ptr<Cursor> cursor(
+      new (nothrow) ArrayCursor(column_->table(), std::move(array),
+                                options.offset, options.limit));
+  if (!cursor) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  return cursor;
+}
+
 bool TreeIndex<Text>::insert(Error *, Int row_id, const Datum &value) {
   Text text = value.force_text();
   std::string string(text.data(), text.size());

  Modified: lib/grnxx/tree_index.hpp (+5 -0)
===================================================================
--- lib/grnxx/tree_index.hpp    2014-09-17 14:17:10 +0900 (d3e4c30)
+++ lib/grnxx/tree_index.hpp    2014-09-17 16:48:07 +0900 (a32a32f)
@@ -156,6 +156,11 @@ class TreeIndex<Text> : public Index {
       const EndPoint &prefix,
       const CursorOptions &options = CursorOptions()) const;
 
+  unique_ptr<Cursor> find_prefixes(
+      Error *error,
+      const Datum &prefix,
+      const CursorOptions &options = CursorOptions()) const;
+
   bool insert(Error *error, Int row_id, const Datum &value);
   bool remove(Error *error, Int row_id, const Datum &value);
 
-------------- next part --------------
HTML����������������������������...
Download 



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