[Groonga-commit] groonga/grnxx at 2045b48 [master] Add expression::Builder for implementation of ExpressionBuilder.

Back to archive index

susumu.yata null+****@clear*****
Thu Sep 4 12:01:56 JST 2014


susumu.yata	2014-09-04 12:01:56 +0900 (Thu, 04 Sep 2014)

  New Revision: 2045b4859ac7290b64610998410a190328323e52
  https://github.com/groonga/grnxx/commit/2045b4859ac7290b64610998410a190328323e52

  Message:
    Add expression::Builder for implementation of ExpressionBuilder.

  Modified files:
    include/grnxx/expression.hpp
    lib/grnxx/expression.cpp

  Modified: include/grnxx/expression.hpp (+3 -55)
===================================================================
--- include/grnxx/expression.hpp    2014-09-04 11:33:16 +0900 (f154112)
+++ include/grnxx/expression.hpp    2014-09-04 12:01:56 +0900 (6d4662e)
@@ -8,6 +8,7 @@ namespace grnxx {
 namespace expression {
 
 class Node;
+class Builder;
 
 }  // namespace expression
 
@@ -189,6 +190,7 @@ class Expression {
 class ExpressionBuilder {
  public:
   using Node = expression::Node;
+  using Builder = expression::Builder;
 
   // Create an object for building expressions.
   //
@@ -249,63 +251,9 @@ class ExpressionBuilder {
 
  private:
   const Table *table_;
-  Array<unique_ptr<Node>> stack_;
+  Array<unique_ptr<Builder>> builders_;
 
   explicit ExpressionBuilder(const Table *table);
-
-  // Create a node associated with a constant.
-  unique_ptr<Node> create_datum_node(Error *error, const Datum &datum);
-  // Create a node associated with a column.
-  unique_ptr<Node> create_column_node(Error *error, String name);
-
-  // Push a unary operator.
-  bool push_unary_operator(Error *error, OperatorType operator_type);
-  // Push a binary operator.
-  bool push_binary_operator(Error *error, OperatorType operator_type);
-
-  // Create a node associated with a unary operator.
-  unique_ptr<Node> create_unary_node(
-      Error *error,
-      OperatorType operator_type,
-      unique_ptr<Node> &&arg);
-  // Create a node associated with a binary operator.
-  unique_ptr<Node> create_binary_node(
-      Error *error,
-      OperatorType operator_type,
-      unique_ptr<Node> &&arg1,
-      unique_ptr<Node> &&arg2);
-
-  // Create a equality test node.
-  template <typename T>
-  unique_ptr<Node> create_equality_test_node(
-      Error *error,
-      unique_ptr<Node> &&arg1,
-      unique_ptr<Node> &&arg2);
-  // Create a comparison node.
-  template <typename T>
-  unique_ptr<Node> create_comparison_node(
-      Error *error,
-      unique_ptr<Node> &&arg1,
-      unique_ptr<Node> &&arg2);
-  // Create a bitwise node.
-  template <typename T>
-  unique_ptr<Node> create_bitwise_node(
-      Error *error,
-      OperatorType operator_type,
-      unique_ptr<Node> &&arg1,
-      unique_ptr<Node> &&arg2);
-  // Create an arithmetic node.
-  template <typename T>
-  unique_ptr<Node> create_arithmetic_node(
-      Error *error,
-      OperatorType operator_type,
-      unique_ptr<Node> &&arg1,
-      unique_ptr<Node> &&arg2);
-  // Create a subscript node.
-  unique_ptr<Node> create_subscript_node(
-      Error *error,
-      unique_ptr<Node> &&arg1,
-      unique_ptr<Node> &&arg2);
 };
 
 }  // namespace grnxx

  Modified: lib/grnxx/expression.cpp (+360 -200)
===================================================================
--- lib/grnxx/expression.cpp    2014-09-04 11:33:16 +0900 (def886e)
+++ lib/grnxx/expression.cpp    2014-09-04 12:01:56 +0900 (dc20d66)
@@ -2364,191 +2364,126 @@ bool SubscriptNode<Float>::evaluate(Error *error,
   return true;
 }
 
-}  // namespace expression
-
-using namespace expression;
-
-// -- Expression --
-
-Expression::~Expression() {}
-
-DataType Expression::data_type() const {
-  return root_->data_type();
-}
-
-//bool Expression::filter(Error *error, Array<Record> *records, Int offset) {
-//  ArrayRef<Record> output_records = records->ref();
-//  if (!filter(error, *records, &output_records)) {
-//    return false;
-//  }
-//  return records->resize(error, output_records.size());
-//}
-
-bool Expression::filter(Error *error,
-                        Array<Record> *records,
-                        Int input_offset,
-                        Int output_offset,
-                        Int output_limit) {
-  ArrayCRef<Record> input = records->ref(input_offset);
-  ArrayRef<Record> output = records->ref(input_offset);
-  Int count = 0;
-  while ((input.size() > 0) && (output_limit > 0)) {
-    Int next_size = (input.size() < block_size_) ? input.size() : block_size_;
-    ArrayCRef<Record> next_input = input.ref(0, next_size);
-    ArrayRef<Record> next_output = output.ref(0, next_size);
-    if (!root_->filter(error, next_input, &next_output)) {
-      return false;
-    }
-    input = input.ref(next_size);
+class Builder {
+ public:
+  // Create an object for building an expression.
+  //
+  // On success, returns a poitner to the builder.
+  // On failure, returns nullptr and stores error information into "*error" if
+  // "error" != nullptr.
+  static unique_ptr<Builder> create(Error *error, const Table *table);
 
-    if (output_offset > 0) {
-      if (output_offset >= next_output.size()) {
-        output_offset -= next_output.size();
-        next_output = next_output.ref(0, 0);
-      } else {
-        for (Int i = output_offset; i < next_output.size(); ++i) {
-          next_output.set(i - output_offset, next_output[i]);
-        }
-        next_output = next_output.ref(0, next_output.size() - output_offset);
-        output_offset = 0;
-      }
-    }
-    if (next_output.size() > output_limit) {
-      next_output = next_output.ref(0, output_limit);
-    }
-    output_limit -= next_output.size();
+  ~Builder() {}
 
-    output = output.ref(next_output.size());
-    count += next_output.size();
+  // Return the target table.
+  const Table *table() const {
+    return table_;
   }
-  records->resize(nullptr, input_offset + count);
-  return true;
 
-}
+  // Push a datum.
+  //
+  // On success, returns true.
+  // On failure, returns false and stores error information into "*error" if
+  // "error" != nullptr.
+  bool push_datum(Error *error, const Datum &datum);
 
-bool Expression::filter(Error *error,
-                        ArrayCRef<Record> input_records,
-                        ArrayRef<Record> *output_records) {
-  ArrayCRef<Record> input = input_records;
-  ArrayRef<Record> output = *output_records;
-  Int count = 0;
-  while (input.size() > block_size_) {
-    ArrayCRef<Record> input_block = input.ref(0, block_size_);
-    ArrayRef<Record> output_block = output.ref(0, block_size_);
-    if (!root_->filter(error, input_block, &output_block)) {
-      return false;
-    }
-    input = input.ref(block_size_);
-    output = output.ref(output_block.size());
-    count += output_block.size();
-  }
-  if (!root_->filter(error, input, &output)) {
-    return false;
-  }
-  count += output.size();
-  *output_records = output_records->ref(0, count);
-  return true;
-}
+  // Push a column.
+  //
+  // If "name" == "_id", pushes a pseudo column associated with row IDs.
+  // If "name" == "_score", pushes a pseudo column associated with scores.
+  //
+  // On success, returns true.
+  // On failure, returns false and stores error information into "*error" if
+  // "error" != nullptr.
+  bool push_column(Error *error, String name);
 
-bool Expression::adjust(Error *error, Array<Record> *records, Int offset) {
-  return adjust(error, records->ref(offset));
-}
+  // Push an operator.
+  //
+  // Pops operands and pushes an operator.
+  // Fails if there are not enough operands.
+  // Fails if the combination of operands is invalid.
+  //
+  // On success, returns true.
+  // On failure, returns false and stores error information into "*error" if
+  // "error" != nullptr.
+  bool push_operator(Error *error, OperatorType operator_type);
 
-bool Expression::adjust(Error *error, ArrayRef<Record> records) {
-  while (records.size() > block_size_) {
-    if (!root_->adjust(error, records.ref(0, block_size_))) {
-      return false;
-    }
-    records = records.ref(block_size_);
-  }
-  return root_->adjust(error, records);
-}
+  // Clear the internal stack.
+  void clear();
 
-template <typename T>
-bool Expression::evaluate(Error *error,
-                          ArrayCRef<Record> records,
-                          Array<T> *results) {
-  if (!results->resize(error, records.size())) {
-    return false;
-  }
-  return evaluate(error, records, results->ref());
-}
+  // Complete building an expression and clear the internal stack.
+  //
+  // Fails if the stack is empty or contains more than one nodes.
+  //
+  // On success, returns a pointer to the expression root node.
+  // On failure, returns nullptr and stores error information into "*error" if
+  // "error" != nullptr.
+  unique_ptr<Node> release(Error *error);
 
-#define GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(type) \
-  template bool Expression::evaluate(Error *error, \
-                                     ArrayCRef<Record> records, \
-                                     Array<type> *results)
-GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Bool);
-GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Int);
-GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Float);
-GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(GeoPoint);
-GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Text);
-GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Vector<Bool>);
-GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Vector<Int>);
-GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Vector<Float>);
-GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Vector<GeoPoint>);
-GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Vector<Text>);
-#undef GRNXX_INSTANTIATE_EXPRESSION_EVALUATE
+ private:
+  const Table *table_;
+  Array<unique_ptr<Node>> stack_;
 
-template <typename T>
-bool Expression::evaluate(Error *error,
-                          ArrayCRef<Record> records,
-                          ArrayRef<T> results) {
-  if (TypeTraits<T>::data_type() != data_type()) {
-    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Invalid data type");
-    return false;
-  }
-  if (records.size() != results.size()) {
-    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Size conflict: "
-                    "#records = %" PRIi64 ", #results = %" PRIi64,
-                    records.size(), results.size());
-    return false;
-  }
-  auto typed_root = static_cast<TypedNode<T> *>(root_.get());
-  while (records.size() > block_size_) {
-    ArrayCRef<Record> input = records.ref(0, block_size_);
-    ArrayRef<T> output = results.ref(0, block_size_);
-    if (!typed_root->evaluate(error, input, output)) {
-      return false;
-    }
-    records = records.ref(block_size_);
-    results = results.ref(block_size_);
-  }
-  return typed_root->evaluate(error, records, results);
-}
+  Builder(const Table *table) : table_(table), stack_() {}
 
-unique_ptr<Expression> Expression::create(Error *error,
-                                          const Table *table,
-                                          unique_ptr<Node> &&root,
-                                          const ExpressionOptions &options) {
-  if (options.block_size <= 0) {
-    GRNXX_ERROR_SET(error, INVALID_ARGUMENT,
-                    "Invalid argument: block_size = %" PRIi64,
-                    options.block_size);
-    return nullptr;
-  }
-  unique_ptr<Expression> expression(
-      new (nothrow) Expression(table, std::move(root), options.block_size));
-  if (!expression) {
-    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
-    return nullptr;
-  }
-  return expression;
-}
-
-Expression::Expression(const Table *table,
-                       unique_ptr<Node> &&root,
-                       Int block_size)
-    : table_(table),
-      root_(std::move(root)),
-      block_size_(block_size) {}
+  // Create a node associated with a constant.
+  unique_ptr<Node> create_datum_node(Error *error, const Datum &datum);
+  // Create a node associated with a column.
+  unique_ptr<Node> create_column_node(Error *error, String name);
+
+  // Push a unary operator.
+  bool push_unary_operator(Error *error, OperatorType operator_type);
+  // Push a binary operator.
+  bool push_binary_operator(Error *error, OperatorType operator_type);
+
+  // Create a node associated with a unary operator.
+  unique_ptr<Node> create_unary_node(
+      Error *error,
+      OperatorType operator_type,
+      unique_ptr<Node> &&arg);
+  // Create a node associated with a binary operator.
+  unique_ptr<Node> create_binary_node(
+      Error *error,
+      OperatorType operator_type,
+      unique_ptr<Node> &&arg1,
+      unique_ptr<Node> &&arg2);
+
+  // Create a equality test node.
+  template <typename T>
+  unique_ptr<Node> create_equality_test_node(
+      Error *error,
+      unique_ptr<Node> &&arg1,
+      unique_ptr<Node> &&arg2);
+  // Create a comparison node.
+  template <typename T>
+  unique_ptr<Node> create_comparison_node(
+      Error *error,
+      unique_ptr<Node> &&arg1,
+      unique_ptr<Node> &&arg2);
+  // Create a bitwise node.
+  template <typename T>
+  unique_ptr<Node> create_bitwise_node(
+      Error *error,
+      OperatorType operator_type,
+      unique_ptr<Node> &&arg1,
+      unique_ptr<Node> &&arg2);
+  // Create an arithmetic node.
+  template <typename T>
+  unique_ptr<Node> create_arithmetic_node(
+      Error *error,
+      OperatorType operator_type,
+      unique_ptr<Node> &&arg1,
+      unique_ptr<Node> &&arg2);
+  // Create a subscript node.
+  unique_ptr<Node> create_subscript_node(
+      Error *error,
+      unique_ptr<Node> &&arg1,
+      unique_ptr<Node> &&arg2);
+};
 
-// -- ExpressionBuilder --
 
-unique_ptr<ExpressionBuilder> ExpressionBuilder::create(Error *error,
-                                                        const Table *table) {
-  unique_ptr<ExpressionBuilder> builder(
-      new (nothrow) ExpressionBuilder(table));
+unique_ptr<Builder> Builder::create(Error *error, const Table *table) {
+  unique_ptr<Builder> builder(new (nothrow) Builder(table));
   if (!builder) {
     GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
     return nullptr;
@@ -2556,9 +2491,7 @@ unique_ptr<ExpressionBuilder> ExpressionBuilder::create(Error *error,
   return builder;
 }
 
-ExpressionBuilder::~ExpressionBuilder() {}
-
-bool ExpressionBuilder::push_datum(Error *error, const Datum &datum) {
+bool Builder::push_datum(Error *error, const Datum &datum) {
   // Reserve a space for a new node.
   if (!stack_.reserve(error, stack_.size() + 1)) {
     return false;
@@ -2572,7 +2505,7 @@ bool ExpressionBuilder::push_datum(Error *error, const Datum &datum) {
   return true;
 }
 
-bool ExpressionBuilder::push_column(Error *error, String name) {
+bool Builder::push_column(Error *error, String name) {
   // Reserve a space for a new node.
   if (!stack_.reserve(error, stack_.size() + 1)) {
     return false;
@@ -2586,8 +2519,7 @@ bool ExpressionBuilder::push_column(Error *error, String name) {
   return true;
 }
 
-bool ExpressionBuilder::push_operator(Error *error,
-                                      OperatorType operator_type) {
+bool Builder::push_operator(Error *error, OperatorType operator_type) {
   switch (operator_type) {
     case LOGICAL_NOT_OPERATOR:
     case BITWISE_NOT_OPERATOR:
@@ -2624,27 +2556,21 @@ bool ExpressionBuilder::push_operator(Error *error,
   }
 }
 
-void ExpressionBuilder::clear() {
+void Builder::clear() {
   stack_.clear();
 }
 
-unique_ptr<Expression> ExpressionBuilder::release(
-    Error *error,
-    const ExpressionOptions &options) {
+unique_ptr<Node> Builder::release(Error *error) {
   if (stack_.size() != 1) {
     GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Incomplete expression");
     return nullptr;
   }
   unique_ptr<Node> root = std::move(stack_[0]);
   stack_.clear();
-  return Expression::create(error, table_, std::move(root), options);
+  return root;
 }
 
-ExpressionBuilder::ExpressionBuilder(const Table *table)
-    : table_(table),
-      stack_() {}
-
-unique_ptr<Node> ExpressionBuilder::create_datum_node(
+unique_ptr<Node> Builder::create_datum_node(
     Error *error,
     const Datum &datum) {
   switch (datum.type()) {
@@ -2689,7 +2615,7 @@ unique_ptr<Node> ExpressionBuilder::create_datum_node(
   }
 }
 
-unique_ptr<Node> ExpressionBuilder::create_column_node(
+unique_ptr<Node> Builder::create_column_node(
     Error *error,
     String name) {
   if (name == "_id") {
@@ -2756,8 +2682,7 @@ unique_ptr<Node> ExpressionBuilder::create_column_node(
   }
 }
 
-bool ExpressionBuilder::push_unary_operator(Error *error,
-                                            OperatorType operator_type) {
+bool Builder::push_unary_operator(Error *error, OperatorType operator_type) {
   if (stack_.size() < 1) {
     GRNXX_ERROR_SET(error, INVALID_OPERAND, "Not enough operands");
     return false;
@@ -2773,8 +2698,7 @@ bool ExpressionBuilder::push_unary_operator(Error *error,
   return true;
 }
 
-bool ExpressionBuilder::push_binary_operator(Error *error,
-                                             OperatorType operator_type) {
+bool Builder::push_binary_operator(Error *error, OperatorType operator_type) {
   if (stack_.size() < 2) {
     GRNXX_ERROR_SET(error, INVALID_OPERAND, "Not enough operands");
     return false;
@@ -2791,7 +2715,7 @@ bool ExpressionBuilder::push_binary_operator(Error *error,
   return true;
 }
 
-unique_ptr<Node> ExpressionBuilder::create_unary_node(
+unique_ptr<Node> Builder::create_unary_node(
     Error *error,
     OperatorType operator_type,
     unique_ptr<Node> &&arg) {
@@ -2861,7 +2785,7 @@ unique_ptr<Node> ExpressionBuilder::create_unary_node(
   }
 }
 
-unique_ptr<Node> ExpressionBuilder::create_binary_node(
+unique_ptr<Node> Builder::create_binary_node(
     Error *error,
     OperatorType operator_type,
     unique_ptr<Node> &&arg1,
@@ -2964,7 +2888,7 @@ unique_ptr<Node> ExpressionBuilder::create_binary_node(
 }
 
 template <typename T>
-unique_ptr<Node> ExpressionBuilder::create_equality_test_node(
+unique_ptr<Node> Builder::create_equality_test_node(
     Error *error,
     unique_ptr<Node> &&arg1,
     unique_ptr<Node> &&arg2) {
@@ -3027,7 +2951,7 @@ unique_ptr<Node> ExpressionBuilder::create_equality_test_node(
 }
 
 template <typename T>
-unique_ptr<Node> ExpressionBuilder::create_comparison_node(
+unique_ptr<Node> Builder::create_comparison_node(
     Error *error,
     unique_ptr<Node> &&arg1,
     unique_ptr<Node> &&arg2) {
@@ -3056,7 +2980,7 @@ unique_ptr<Node> ExpressionBuilder::create_comparison_node(
 }
 
 template <typename T>
-unique_ptr<Node> ExpressionBuilder::create_bitwise_node(
+unique_ptr<Node> Builder::create_bitwise_node(
     Error *error,
     OperatorType operator_type,
     unique_ptr<Node> &&arg1,
@@ -3086,7 +3010,7 @@ unique_ptr<Node> ExpressionBuilder::create_bitwise_node(
 }
 
 template <typename T>
-unique_ptr<Node> ExpressionBuilder::create_arithmetic_node(
+unique_ptr<Node> Builder::create_arithmetic_node(
     Error *error,
     OperatorType operator_type,
     unique_ptr<Node> &&arg1,
@@ -3119,7 +3043,7 @@ unique_ptr<Node> ExpressionBuilder::create_arithmetic_node(
   }
 }
 
-unique_ptr<Node> ExpressionBuilder::create_subscript_node(
+unique_ptr<Node> Builder::create_subscript_node(
     Error *error,
     unique_ptr<Node> &&arg1,
     unique_ptr<Node> &&arg2) {
@@ -3155,4 +3079,240 @@ unique_ptr<Node> ExpressionBuilder::create_subscript_node(
   }
 }
 
+}  // namespace expression
+
+using namespace expression;
+
+// -- Expression --
+
+Expression::~Expression() {}
+
+DataType Expression::data_type() const {
+  return root_->data_type();
+}
+
+//bool Expression::filter(Error *error, Array<Record> *records, Int offset) {
+//  ArrayRef<Record> output_records = records->ref();
+//  if (!filter(error, *records, &output_records)) {
+//    return false;
+//  }
+//  return records->resize(error, output_records.size());
+//}
+
+bool Expression::filter(Error *error,
+                        Array<Record> *records,
+                        Int input_offset,
+                        Int output_offset,
+                        Int output_limit) {
+  ArrayCRef<Record> input = records->ref(input_offset);
+  ArrayRef<Record> output = records->ref(input_offset);
+  Int count = 0;
+  while ((input.size() > 0) && (output_limit > 0)) {
+    Int next_size = (input.size() < block_size_) ? input.size() : block_size_;
+    ArrayCRef<Record> next_input = input.ref(0, next_size);
+    ArrayRef<Record> next_output = output.ref(0, next_size);
+    if (!root_->filter(error, next_input, &next_output)) {
+      return false;
+    }
+    input = input.ref(next_size);
+
+    if (output_offset > 0) {
+      if (output_offset >= next_output.size()) {
+        output_offset -= next_output.size();
+        next_output = next_output.ref(0, 0);
+      } else {
+        for (Int i = output_offset; i < next_output.size(); ++i) {
+          next_output.set(i - output_offset, next_output[i]);
+        }
+        next_output = next_output.ref(0, next_output.size() - output_offset);
+        output_offset = 0;
+      }
+    }
+    if (next_output.size() > output_limit) {
+      next_output = next_output.ref(0, output_limit);
+    }
+    output_limit -= next_output.size();
+
+    output = output.ref(next_output.size());
+    count += next_output.size();
+  }
+  records->resize(nullptr, input_offset + count);
+  return true;
+
+}
+
+bool Expression::filter(Error *error,
+                        ArrayCRef<Record> input_records,
+                        ArrayRef<Record> *output_records) {
+  ArrayCRef<Record> input = input_records;
+  ArrayRef<Record> output = *output_records;
+  Int count = 0;
+  while (input.size() > block_size_) {
+    ArrayCRef<Record> input_block = input.ref(0, block_size_);
+    ArrayRef<Record> output_block = output.ref(0, block_size_);
+    if (!root_->filter(error, input_block, &output_block)) {
+      return false;
+    }
+    input = input.ref(block_size_);
+    output = output.ref(output_block.size());
+    count += output_block.size();
+  }
+  if (!root_->filter(error, input, &output)) {
+    return false;
+  }
+  count += output.size();
+  *output_records = output_records->ref(0, count);
+  return true;
+}
+
+bool Expression::adjust(Error *error, Array<Record> *records, Int offset) {
+  return adjust(error, records->ref(offset));
+}
+
+bool Expression::adjust(Error *error, ArrayRef<Record> records) {
+  while (records.size() > block_size_) {
+    if (!root_->adjust(error, records.ref(0, block_size_))) {
+      return false;
+    }
+    records = records.ref(block_size_);
+  }
+  return root_->adjust(error, records);
+}
+
+template <typename T>
+bool Expression::evaluate(Error *error,
+                          ArrayCRef<Record> records,
+                          Array<T> *results) {
+  if (!results->resize(error, records.size())) {
+    return false;
+  }
+  return evaluate(error, records, results->ref());
+}
+
+#define GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(type) \
+  template bool Expression::evaluate(Error *error, \
+                                     ArrayCRef<Record> records, \
+                                     Array<type> *results)
+GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Bool);
+GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Int);
+GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Float);
+GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(GeoPoint);
+GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Text);
+GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Vector<Bool>);
+GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Vector<Int>);
+GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Vector<Float>);
+GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Vector<GeoPoint>);
+GRNXX_INSTANTIATE_EXPRESSION_EVALUATE(Vector<Text>);
+#undef GRNXX_INSTANTIATE_EXPRESSION_EVALUATE
+
+template <typename T>
+bool Expression::evaluate(Error *error,
+                          ArrayCRef<Record> records,
+                          ArrayRef<T> results) {
+  if (TypeTraits<T>::data_type() != data_type()) {
+    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Invalid data type");
+    return false;
+  }
+  if (records.size() != results.size()) {
+    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Size conflict: "
+                    "#records = %" PRIi64 ", #results = %" PRIi64,
+                    records.size(), results.size());
+    return false;
+  }
+  auto typed_root = static_cast<TypedNode<T> *>(root_.get());
+  while (records.size() > block_size_) {
+    ArrayCRef<Record> input = records.ref(0, block_size_);
+    ArrayRef<T> output = results.ref(0, block_size_);
+    if (!typed_root->evaluate(error, input, output)) {
+      return false;
+    }
+    records = records.ref(block_size_);
+    results = results.ref(block_size_);
+  }
+  return typed_root->evaluate(error, records, results);
+}
+
+unique_ptr<Expression> Expression::create(Error *error,
+                                          const Table *table,
+                                          unique_ptr<Node> &&root,
+                                          const ExpressionOptions &options) {
+  if (options.block_size <= 0) {
+    GRNXX_ERROR_SET(error, INVALID_ARGUMENT,
+                    "Invalid argument: block_size = %" PRIi64,
+                    options.block_size);
+    return nullptr;
+  }
+  unique_ptr<Expression> expression(
+      new (nothrow) Expression(table, std::move(root), options.block_size));
+  if (!expression) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  return expression;
+}
+
+Expression::Expression(const Table *table,
+                       unique_ptr<Node> &&root,
+                       Int block_size)
+    : table_(table),
+      root_(std::move(root)),
+      block_size_(block_size) {}
+
+// -- ExpressionBuilder --
+
+unique_ptr<ExpressionBuilder> ExpressionBuilder::create(Error *error,
+                                                        const Table *table) {
+  unique_ptr<ExpressionBuilder> builder(
+      new (nothrow) ExpressionBuilder(table));
+  if (!builder) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  unique_ptr<Builder> internal_builder = Builder::create(error, table);
+  if (!internal_builder) {
+    return nullptr;
+  }
+  if (!builder->builders_.push_back(error, std::move(internal_builder))) {
+    return nullptr;
+  }
+  return builder;
+}
+
+ExpressionBuilder::~ExpressionBuilder() {}
+
+bool ExpressionBuilder::push_datum(Error *error, const Datum &datum) {
+  return builders_.back()->push_datum(error, datum);
+}
+
+bool ExpressionBuilder::push_column(Error *error, String name) {
+  return builders_.back()->push_column(error, name);
+}
+
+bool ExpressionBuilder::push_operator(Error *error,
+                                      OperatorType operator_type) {
+  return builders_.back()->push_operator(error, operator_type);
+}
+
+void ExpressionBuilder::clear() {
+  builders_.clear();
+}
+
+unique_ptr<Expression> ExpressionBuilder::release(
+    Error *error,
+    const ExpressionOptions &options) {
+  if (builders_.size() != 1) {
+    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Incomplete expression");
+    return nullptr;
+  }
+  unique_ptr<Node> root = builders_[0]->release(error);
+  if (!root) {
+    return nullptr;
+  }
+  return Expression::create(error, table_, std::move(root), options);
+}
+
+ExpressionBuilder::ExpressionBuilder(const Table *table)
+    : table_(table),
+      builders_() {}
+
 }  // namespace grnxx
-------------- next part --------------
HTML����������������������������...
Download 



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