[Groonga-commit] groonga/grnxx at ffc54e6 [master] Support subexpressions for Vector<Int>. (#48)

アーカイブの一覧に戻る

susumu.yata null+****@clear*****
Fri Sep 12 16:24:06 JST 2014


susumu.yata	2014-09-12 16:24:06 +0900 (Fri, 12 Sep 2014)

  New Revision: ffc54e6990f44da908db539de84b18710862693c
  https://github.com/groonga/grnxx/commit/ffc54e6990f44da908db539de84b18710862693c

  Message:
    Support subexpressions for Vector<Int>. (#48)

  Modified files:
    lib/grnxx/expression.cpp

  Modified: lib/grnxx/expression.cpp (+230 -37)
===================================================================
--- lib/grnxx/expression.cpp    2014-09-12 15:45:40 +0900 (1443464)
+++ lib/grnxx/expression.cpp    2014-09-12 16:24:06 +0900 (e9a06e5)
@@ -246,6 +246,50 @@ bool TypedNode<Float>::adjust(Error *error, ArrayRef<Record> records) {
   return true;
 }
 
+template <>
+class TypedNode<Vector<Int>> : public Node {
+ public:
+  using Value = Vector<Int>;
+
+  explicit TypedNode(const Table *ref_table = nullptr)
+      : Node(),
+        ref_table_(ref_table) {}
+  virtual ~TypedNode() {}
+
+  DataType data_type() const {
+    return TypeTraits<Value>::data_type();
+  }
+  const Table *ref_table() const {
+    return ref_table_;
+  }
+
+  bool filter(Error *error, ArrayCRef<Record>, ArrayRef<Record> *) {
+    // Other than TypedNode<Bool> don't support filter().
+    GRNXX_ERROR_SET(error, INVALID_OPERATION, "Invalid operation");
+    return false;
+  }
+
+  bool adjust(Error *error, ArrayRef<Record>) {
+    // Other than TypedNode<Float> don't support adjust().
+    GRNXX_ERROR_SET(error, INVALID_OPERATION, "Invalid operation");
+    return false;
+  }
+
+  // Evaluate the expression subtree.
+  //
+  // The evaluation results are stored into "*results".
+  //
+  // On success, returns true.
+  // On failure, returns false and stores error information into "*error" if
+  // "error" != nullptr.
+  virtual bool evaluate(Error *error,
+                        ArrayCRef<Record> records,
+                        ArrayRef<Value> results) = 0;
+
+ protected:
+  const Table *ref_table_;
+};
+
 // -- DatumNode --
 
 template <typename T>
@@ -638,6 +682,40 @@ class ColumnNode<Float> : public TypedNode<Float> {
   const ColumnImpl<Value> *column_;
 };
 
+template <>
+class ColumnNode<Vector<Int>> : public TypedNode<Vector<Int>> {
+ public:
+  using Value = Vector<Int>;
+
+  static unique_ptr<Node> create(Error *error, const Column *column) {
+    unique_ptr<Node> node(new (nothrow) ColumnNode(column));
+    if (!node) {
+      GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    }
+    return node;
+  }
+
+  explicit ColumnNode(const Column *column)
+      : TypedNode<Value>(column->ref_table()),
+        column_(static_cast<const ColumnImpl<Value> *>(column)) {}
+
+  NodeType node_type() const {
+    return COLUMN_NODE;
+  }
+
+  bool evaluate(Error *,
+                ArrayCRef<Record> records,
+                ArrayRef<Value> results) {
+    for (Int i = 0; i < records.size(); ++i) {
+      results[i] = column_->get(records.get_row_id(i));
+    }
+    return true;
+  }
+
+ private:
+  const ColumnImpl<Value> *column_;
+};
+
 // -- OperatorNode --
 
 template <typename T>
@@ -2648,6 +2726,82 @@ bool ReferenceNode<Float>::evaluate(Error *error,
   return this->arg2_->evaluate(error, temp_records_, results);
 }
 
+// ---- ReferenceVectorNode ----
+
+template <typename T>
+class ReferenceVectorNode
+    : public BinaryNode<Vector<T>, Vector<Int>, T> {
+ public:
+  using Value = Vector<T>;
+  using Arg1 = Vector<Int>;
+  using Arg2 = T;
+
+  static unique_ptr<Node> create(Error *error,
+                                 unique_ptr<Node> &&arg1,
+                                 unique_ptr<Node> &&arg2) {
+    unique_ptr<Node> node(
+        new (nothrow) ReferenceVectorNode(std::move(arg1), std::move(arg2)));
+    if (!node) {
+      GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    }
+    return node;
+  }
+
+  ReferenceVectorNode(unique_ptr<Node> &&arg1, unique_ptr<Node> &&arg2)
+      : BinaryNode<Value, Arg1, Arg2>(std::move(arg1), std::move(arg2)),
+        temp_records_() {}
+
+  bool evaluate(Error *error,
+                ArrayCRef<Record> records,
+                ArrayRef<Value> results);
+
+ private:
+  Array<Record> temp_records_;
+  Array<Array<Arg2>> result_blocks_;
+};
+
+template <typename T>
+bool ReferenceVectorNode<T>::evaluate(Error *error,
+                                      ArrayCRef<Record> records,
+                                      ArrayRef<Value> results) {
+  if (!this->fill_arg1_values(error, records)) {
+    return false;
+  }
+  Int total_size = 0;
+  for (Int i = 0; i < records.size(); ++i) {
+    total_size += this->arg1_values_[i].size();
+  }
+  if (!temp_records_.resize(error, total_size)) {
+    return false;
+  }
+  Array<Arg2> result_block;
+  if (!result_block.resize(error, total_size)) {
+    return false;
+  }
+  Int count = 0;
+  for (Int i = 0; i < records.size(); ++i) {
+    Float score = records.get_score(i);
+    for (Int j = 0; j < this->arg1_values_[i].size(); ++j) {
+      temp_records_.set(count, Record(this->arg1_values_[i][j], score));
+      ++count;
+    }
+  }
+  // TODO: evaluate() should be called for each block of "temp_records_".
+  if (!this->arg2_->evaluate(error, temp_records_, result_block.ref())) {
+    return false;
+  }
+  Int offset = 0;
+  for (Int i = 0; i < records.size(); ++i) {
+    Int size = this->arg1_values_[i].size();
+    results[i] = Value(&result_block[offset], size);
+    offset += size;
+  }
+  if (!result_blocks_.push_back(error, std::move(result_block))) {
+    return false;
+  }
+  return true;
+}
+
 // -- Builder --
 
 class Builder {
@@ -3453,46 +3607,85 @@ unique_ptr<Node> Builder::create_reference_node(
     Error *error,
     unique_ptr<Node> &&arg1,
     unique_ptr<Node> &&arg2) {
-  switch (arg2->data_type()) {
-    case BOOL_DATA: {
-      return ReferenceNode<Bool>::create(
-          error, std::move(arg1), std::move(arg2));
-    }
+  switch (arg1->data_type()) {
     case INT_DATA: {
-      return ReferenceNode<Int>::create(
-          error, std::move(arg1), std::move(arg2));
-    }
-    case FLOAT_DATA: {
-      return ReferenceNode<Float>::create(
-          error, std::move(arg1), std::move(arg2));
-    }
-    case GEO_POINT_DATA: {
-      return ReferenceNode<GeoPoint>::create(
-          error, std::move(arg1), std::move(arg2));
-    }
-    case TEXT_DATA: {
-      return ReferenceNode<Text>::create(
-          error, std::move(arg1), std::move(arg2));
-    }
-    case BOOL_VECTOR_DATA: {
-      return ReferenceNode<Vector<Bool>>::create(
-          error, std::move(arg1), std::move(arg2));
+      switch (arg2->data_type()) {
+        case BOOL_DATA: {
+          return ReferenceNode<Bool>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        case INT_DATA: {
+          return ReferenceNode<Int>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        case FLOAT_DATA: {
+          return ReferenceNode<Float>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        case GEO_POINT_DATA: {
+          return ReferenceNode<GeoPoint>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        case TEXT_DATA: {
+          return ReferenceNode<Text>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        case BOOL_VECTOR_DATA: {
+          return ReferenceNode<Vector<Bool>>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        case INT_VECTOR_DATA: {
+          return ReferenceNode<Vector<Int>>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        case FLOAT_VECTOR_DATA: {
+          return ReferenceNode<Vector<Float>>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        case GEO_POINT_VECTOR_DATA: {
+          return ReferenceNode<Vector<GeoPoint>>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        case TEXT_VECTOR_DATA: {
+          return ReferenceNode<Vector<Text>>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        default: {
+          GRNXX_ERROR_SET(error, INVALID_OPERAND, "Invalid data type");
+          return nullptr;
+        }
+      }
     }
     case INT_VECTOR_DATA: {
-      return ReferenceNode<Vector<Int>>::create(
-          error, std::move(arg1), std::move(arg2));
-    }
-    case FLOAT_VECTOR_DATA: {
-      return ReferenceNode<Vector<Float>>::create(
-          error, std::move(arg1), std::move(arg2));
-    }
-    case GEO_POINT_VECTOR_DATA: {
-      return ReferenceNode<Vector<GeoPoint>>::create(
-          error, std::move(arg1), std::move(arg2));
-    }
-    case TEXT_VECTOR_DATA: {
-      return ReferenceNode<Vector<Text>>::create(
-          error, std::move(arg1), std::move(arg2));
+      switch (arg2->data_type()) {
+        case BOOL_DATA: {
+          // TODO: Not supported yet.
+//          return ReferenceVectorNode<Bool>::create(
+//              error, std::move(arg1), std::move(arg2));
+          GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supported yet");
+          return nullptr;
+        }
+        case INT_DATA: {
+          return ReferenceVectorNode<Int>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        case FLOAT_DATA: {
+          return ReferenceVectorNode<Float>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        case GEO_POINT_DATA: {
+          return ReferenceVectorNode<GeoPoint>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        case TEXT_DATA: {
+          return ReferenceVectorNode<Text>::create(
+              error, std::move(arg1), std::move(arg2));
+        }
+        default: {
+          GRNXX_ERROR_SET(error, INVALID_OPERAND, "Invalid data type");
+          return nullptr;
+        }
+      }
     }
     default: {
       GRNXX_ERROR_SET(error, INVALID_OPERAND, "Invalid data type");
-------------- next part --------------
HTML����������������������������...
ダウンロード 



More information about the Groonga-commit mailing list
アーカイブの一覧に戻る