[Groonga-commit] groonga/grnxx at 4fce3f5 [master] Add a rough implementation of Pipeline.

Back to archive index

susumu.yata null+****@clear*****
Wed Aug 20 18:54:40 JST 2014


susumu.yata	2014-08-20 18:54:40 +0900 (Wed, 20 Aug 2014)

  New Revision: 4fce3f5e024ad4ce89804414defc674af8cd9e67
  https://github.com/groonga/grnxx/commit/4fce3f5e024ad4ce89804414defc674af8cd9e67

  Message:
    Add a rough implementation of Pipeline.

  Added files:
    include/grnxx/pipeline.hpp
    lib/grnxx/pipeline.cpp
  Modified files:
    include/grnxx/Makefile.am
    include/grnxx/expression.hpp
    include/grnxx/sorter.hpp
    lib/grnxx/Makefile.am
    lib/grnxx/expression.cpp
    lib/grnxx/sorter.cpp

  Modified: include/grnxx/Makefile.am (+1 -0)
===================================================================
--- include/grnxx/Makefile.am    2014-08-20 16:35:03 +0900 (a83e849)
+++ include/grnxx/Makefile.am    2014-08-20 18:54:40 +0900 (e147311)
@@ -8,6 +8,7 @@ pkginclude_HEADERS =	\
 	expression.hpp	\
 	index.hpp	\
 	library.hpp	\
+	pipeline.hpp	\
 	sorter.hpp	\
 	table.hpp	\
 	types.hpp

  Modified: include/grnxx/expression.hpp (+27 -26)
===================================================================
--- include/grnxx/expression.hpp    2014-08-20 16:35:03 +0900 (79c497a)
+++ include/grnxx/expression.hpp    2014-08-20 18:54:40 +0900 (88702a8)
@@ -11,8 +11,6 @@ class Node;
 
 }  // namespace expression
 
-using ExpressionNode = expression::Node;
-
 enum OperatorType {
   // -- Unary operators --
 
@@ -67,6 +65,8 @@ enum OperatorType {
 
 class Expression {
  public:
+  using Node = expression::Node;
+
   ~Expression();
 
   // Return the associated table.
@@ -180,7 +180,7 @@ class Expression {
 
  private:
   const Table *table_;
-  unique_ptr<ExpressionNode> root_;
+  unique_ptr<Node> root_;
   Int block_size_;
 
   // Create an expression.
@@ -190,11 +190,11 @@ class Expression {
   // "error" != nullptr.
   static unique_ptr<Expression> create(Error *error,
                                        const Table *table,
-                                       unique_ptr<ExpressionNode> &&root,
+                                       unique_ptr<Node> &&root,
                                        const ExpressionOptions &options);
 
   Expression(const Table *table,
-             unique_ptr<ExpressionNode> &&root,
+             unique_ptr<Node> &&root,
              Int block_size);
 
   friend ExpressionBuilder;
@@ -202,6 +202,8 @@ class Expression {
 
 class ExpressionBuilder {
  public:
+  using Node = expression::Node;
+
   // Create an object for building expressons.
   //
   // On success, returns a poitner to the builder.
@@ -261,15 +263,14 @@ class ExpressionBuilder {
 
  private:
   const Table *table_;
-  Array<unique_ptr<ExpressionNode>> stack_;
+  Array<unique_ptr<Node>> stack_;
 
   explicit ExpressionBuilder(const Table *table);
 
   // Create a node associated with a constant.
-  unique_ptr<ExpressionNode> create_datum_node(Error *error,
-                                               const Datum &datum);
+  unique_ptr<Node> create_datum_node(Error *error, const Datum &datum);
   // Create a node associated with a column.
-  unique_ptr<ExpressionNode> create_column_node(Error *error, String name);
+  unique_ptr<Node> create_column_node(Error *error, String name);
 
   // Push a unary operator.
   bool push_unary_operator(Error *error, OperatorType operator_type);
@@ -277,43 +278,43 @@ class ExpressionBuilder {
   bool push_binary_operator(Error *error, OperatorType operator_type);
 
   // Create a node associated with a unary operator.
-  unique_ptr<ExpressionNode> create_unary_node(
+  unique_ptr<Node> create_unary_node(
       Error *error,
       OperatorType operator_type,
-      unique_ptr<ExpressionNode> &&arg);
+      unique_ptr<Node> &&arg);
   // Create a node associated with a binary operator.
-  unique_ptr<ExpressionNode> create_binary_node(
+  unique_ptr<Node> create_binary_node(
       Error *error,
       OperatorType operator_type,
-      unique_ptr<ExpressionNode> &&arg1,
-      unique_ptr<ExpressionNode> &&arg2);
+      unique_ptr<Node> &&arg1,
+      unique_ptr<Node> &&arg2);
 
   // Create a equality test node.
   template <typename T>
-  unique_ptr<ExpressionNode> create_equality_test_node(
+  unique_ptr<Node> create_equality_test_node(
       Error *error,
-      unique_ptr<ExpressionNode> &&arg1,
-      unique_ptr<ExpressionNode> &&arg2);
+      unique_ptr<Node> &&arg1,
+      unique_ptr<Node> &&arg2);
   // Create a comparison node.
   template <typename T>
-  unique_ptr<ExpressionNode> create_comparison_node(
+  unique_ptr<Node> create_comparison_node(
       Error *error,
-      unique_ptr<ExpressionNode> &&arg1,
-      unique_ptr<ExpressionNode> &&arg2);
+      unique_ptr<Node> &&arg1,
+      unique_ptr<Node> &&arg2);
   // Create a bitwise node.
   template <typename T>
-  unique_ptr<ExpressionNode> create_bitwise_node(
+  unique_ptr<Node> create_bitwise_node(
       Error *error,
       OperatorType operator_type,
-      unique_ptr<ExpressionNode> &&arg1,
-      unique_ptr<ExpressionNode> &&arg2);
+      unique_ptr<Node> &&arg1,
+      unique_ptr<Node> &&arg2);
   // Create an arithmetic node.
   template <typename T>
-  unique_ptr<ExpressionNode> create_arithmetic_node(
+  unique_ptr<Node> create_arithmetic_node(
       Error *error,
       OperatorType operator_type,
-      unique_ptr<ExpressionNode> &&arg1,
-      unique_ptr<ExpressionNode> &&arg2);
+      unique_ptr<Node> &&arg1,
+      unique_ptr<Node> &&arg2);
 };
 
 }  // namespace grnxx

  Added: include/grnxx/pipeline.hpp (+120 -0) 100644
===================================================================
--- /dev/null
+++ include/grnxx/pipeline.hpp    2014-08-20 18:54:40 +0900 (47fe582)
@@ -0,0 +1,120 @@
+#ifndef GRNXX_PIPELINE_HPP
+#define GRNXX_PIPELINE_HPP
+
+#include "grnxx/array.hpp"
+#include "grnxx/sorter.hpp"
+#include "grnxx/types.hpp"
+
+namespace grnxx {
+namespace pipeline {
+
+class Node;
+
+}  // namespace pipeline
+
+using PipelineNode = pipeline::Node;
+
+struct PipelineOptions {
+};
+
+class Pipeline {
+ public:
+  ~Pipeline();
+
+  const Table *table() const {
+    return table_;
+  }
+
+  // Read all the records through the pipeline.
+  //
+  // On success, returns true.
+  // On failure, returns false and stores error information into "*error" if
+  // "error" != nullptr.
+  bool flush(Error *error, Array<Record> *records);
+
+ private:
+  const Table *table_;
+  unique_ptr<PipelineNode> root_;
+
+  static unique_ptr<Pipeline> create(Error *error,
+                                     const Table *table,
+                                     unique_ptr<PipelineNode> &&root,
+                                     const PipelineOptions &options);
+
+  Pipeline(const Table *table,
+           unique_ptr<PipelineNode> &&root);
+
+  friend class PipelineBuilder;
+};
+
+class PipelineBuilder {
+ public:
+  // Create an object for building a pipeline.
+  //
+  // On success, returns a poitner to the builder.
+  // On failure, returns nullptr and stores error information into "*error" if
+  // "error" != nullptr.
+  static unique_ptr<PipelineBuilder> create(Error *error, const Table *table);
+
+  ~PipelineBuilder();
+
+  // Return the associated table.
+  const Table *table() const {
+    return table_;
+  }
+
+  // Push a cursor.
+  //
+  // On success, returns true.
+  // On failure, returns false and stores error information into "*error" if
+  // "error" != nullptr.
+  bool push_cursor(Error *error, unique_ptr<Cursor> &&cursor);
+
+  // Push a filter.
+  //
+  // On success, returns true.
+  // On failure, returns false and stores error information into "*error" if
+  // "error" != nullptr.
+  bool push_filter(Error *error,
+                   unique_ptr<Expression> &&expression,
+                   Int offset, Int limit);
+
+  // Push an adjuster.
+  //
+  // On success, returns true.
+  // On failure, returns false and stores error information into "*error" if
+  // "error" != nullptr.
+  bool push_adjuster(Error *error, unique_ptr<Expression> &&expression);
+
+  // Push a sorter.
+  //
+  // On success, returns true.
+  // On failure, returns false and stores error information into "*error" if
+  // "error" != nullptr.
+  bool push_sorter(Error *error, unique_ptr<Sorter> &&sorter);
+
+  // TODO: Not supported yet.
+//  bool push_merger(Error *error, const MergerOptions &options);
+
+  // Clear the internal stack.
+  void clear();
+
+  // Complete building a pipeline 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.
+  // On failure, returns nullptr and stores error information into "*error" if
+  // "error" != nullptr.
+  unique_ptr<Pipeline> release(Error *error, const PipelineOptions &options);
+
+ private:
+  const Table *table_;
+  Array<unique_ptr<PipelineNode>> stack_;
+
+  PipelineBuilder();
+};
+
+}  // namespace grnxx
+
+#endif  // GRNXX_PIPELINE_HPP

  Modified: include/grnxx/sorter.hpp (+3 -3)
===================================================================
--- include/grnxx/sorter.hpp    2014-08-20 16:35:03 +0900 (6c4b179)
+++ include/grnxx/sorter.hpp    2014-08-20 18:54:40 +0900 (6948745)
@@ -11,10 +11,10 @@ class Node;
 
 }  // namespace sorter
 
-using SorterNode = sorter::Node;
-
 class Sorter {
  public:
+  using Node = sorter::Node;
+
   ~Sorter();
 
   // Return the associated table.
@@ -69,7 +69,7 @@ class Sorter {
 
  private:
   const Table *table_;
-  unique_ptr<SorterNode> head_;
+  unique_ptr<Node> head_;
   Array<Record> *records_;
   Int offset_;
   Int limit_;

  Modified: lib/grnxx/Makefile.am (+1 -0)
===================================================================
--- lib/grnxx/Makefile.am    2014-08-20 16:35:03 +0900 (a9e9b12)
+++ lib/grnxx/Makefile.am    2014-08-20 18:54:40 +0900 (4c34688)
@@ -17,6 +17,7 @@ libgrnxx_la_SOURCES =			\
 	index.cpp			\
 	library.cpp			\
 	name.cpp			\
+	pipeline.cpp			\
 	sorter.cpp			\
 	table.cpp			\
 	types.cpp

  Modified: lib/grnxx/expression.cpp (+23 -23)
===================================================================
--- lib/grnxx/expression.cpp    2014-08-20 16:35:03 +0900 (bbcbd5f)
+++ lib/grnxx/expression.cpp    2014-08-20 18:54:40 +0900 (e443683)
@@ -2333,7 +2333,7 @@ bool Expression::evaluate(Error *error,
 
 unique_ptr<Expression> Expression::create(Error *error,
                                           const Table *table,
-                                          unique_ptr<ExpressionNode> &&root,
+                                          unique_ptr<Node> &&root,
                                           const ExpressionOptions &options) {
   if (options.block_size <= 0) {
     GRNXX_ERROR_SET(error, INVALID_ARGUMENT,
@@ -2351,7 +2351,7 @@ unique_ptr<Expression> Expression::create(Error *error,
 }
 
 Expression::Expression(const Table *table,
-                       unique_ptr<ExpressionNode> &&root,
+                       unique_ptr<Node> &&root,
                        Int block_size)
     : table_(table),
       root_(std::move(root)),
@@ -2391,7 +2391,7 @@ bool ExpressionBuilder::push_column(Error *error, String name) {
   if (!stack_.reserve(error, stack_.size() + 1)) {
     return false;
   }
-  unique_ptr<ExpressionNode> node = create_column_node(error, name);
+  unique_ptr<Node> node = create_column_node(error, name);
   if (!node) {
     return false;
   }
@@ -2448,7 +2448,7 @@ unique_ptr<Expression> ExpressionBuilder::release(
     GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Incomplete expression");
     return nullptr;
   }
-  unique_ptr<ExpressionNode> root = std::move(stack_[0]);
+  unique_ptr<Node> root = std::move(stack_[0]);
   stack_.clear();
   return Expression::create(error, table_, std::move(root), options);
 }
@@ -2457,7 +2457,7 @@ ExpressionBuilder::ExpressionBuilder(const Table *table)
     : table_(table),
       stack_() {}
 
-unique_ptr<ExpressionNode> ExpressionBuilder::create_datum_node(
+unique_ptr<Node> ExpressionBuilder::create_datum_node(
     Error *error,
     const Datum &datum) {
   switch (datum.type()) {
@@ -2487,7 +2487,7 @@ unique_ptr<ExpressionNode> ExpressionBuilder::create_datum_node(
   }
 }
 
-unique_ptr<ExpressionNode> ExpressionBuilder::create_column_node(
+unique_ptr<Node> ExpressionBuilder::create_column_node(
     Error *error,
     String name) {
   if (name == "_id") {
@@ -2577,10 +2577,10 @@ bool ExpressionBuilder::push_binary_operator(Error *error,
   return true;
 }
 
-unique_ptr<ExpressionNode> ExpressionBuilder::create_unary_node(
+unique_ptr<Node> ExpressionBuilder::create_unary_node(
     Error *error,
     OperatorType operator_type,
-    unique_ptr<ExpressionNode> &&arg) {
+    unique_ptr<Node> &&arg) {
   switch (operator_type) {
     case LOGICAL_NOT_OPERATOR: {
       if (arg->data_type() != BOOL_DATA) {
@@ -2647,11 +2647,11 @@ unique_ptr<ExpressionNode> ExpressionBuilder::create_unary_node(
   }
 }
 
-unique_ptr<ExpressionNode> ExpressionBuilder::create_binary_node(
+unique_ptr<Node> ExpressionBuilder::create_binary_node(
     Error *error,
     OperatorType operator_type,
-    unique_ptr<ExpressionNode> &&arg1,
-    unique_ptr<ExpressionNode> &&arg2) {
+    unique_ptr<Node> &&arg1,
+    unique_ptr<Node> &&arg2) {
   switch (operator_type) {
     case LOGICAL_AND_OPERATOR: {
       if ((arg1->data_type() != BOOL_DATA) ||
@@ -2747,10 +2747,10 @@ unique_ptr<ExpressionNode> ExpressionBuilder::create_binary_node(
 }
 
 template <typename T>
-unique_ptr<ExpressionNode> ExpressionBuilder::create_equality_test_node(
+unique_ptr<Node> ExpressionBuilder::create_equality_test_node(
     Error *error,
-    unique_ptr<ExpressionNode> &&arg1,
-    unique_ptr<ExpressionNode> &&arg2) {
+    unique_ptr<Node> &&arg1,
+    unique_ptr<Node> &&arg2) {
   if (arg1->data_type() != arg2->data_type()) {
     GRNXX_ERROR_SET(error, INVALID_OPERAND, "Data type conflict");
     return nullptr;
@@ -2789,10 +2789,10 @@ unique_ptr<ExpressionNode> ExpressionBuilder::create_equality_test_node(
 }
 
 template <typename T>
-unique_ptr<ExpressionNode> ExpressionBuilder::create_comparison_node(
+unique_ptr<Node> ExpressionBuilder::create_comparison_node(
     Error *error,
-    unique_ptr<ExpressionNode> &&arg1,
-    unique_ptr<ExpressionNode> &&arg2) {
+    unique_ptr<Node> &&arg1,
+    unique_ptr<Node> &&arg2) {
   if (arg1->data_type() != arg2->data_type()) {
     GRNXX_ERROR_SET(error, INVALID_OPERAND, "Data type conflict");
     return nullptr;
@@ -2822,11 +2822,11 @@ unique_ptr<ExpressionNode> ExpressionBuilder::create_comparison_node(
 }
 
 template <typename T>
-unique_ptr<ExpressionNode> ExpressionBuilder::create_bitwise_node(
+unique_ptr<Node> ExpressionBuilder::create_bitwise_node(
     Error *error,
     OperatorType operator_type,
-    unique_ptr<ExpressionNode> &&arg1,
-    unique_ptr<ExpressionNode> &&arg2) {
+    unique_ptr<Node> &&arg1,
+    unique_ptr<Node> &&arg2) {
   if (arg1->data_type() != arg2->data_type()) {
     GRNXX_ERROR_SET(error, INVALID_OPERAND, "Data type conflict");
     return nullptr;
@@ -2852,11 +2852,11 @@ unique_ptr<ExpressionNode> ExpressionBuilder::create_bitwise_node(
 }
 
 template <typename T>
-unique_ptr<ExpressionNode> ExpressionBuilder::create_arithmetic_node(
+unique_ptr<Node> ExpressionBuilder::create_arithmetic_node(
     Error *error,
     OperatorType operator_type,
-    unique_ptr<ExpressionNode> &&arg1,
-    unique_ptr<ExpressionNode> &&arg2) {
+    unique_ptr<Node> &&arg1,
+    unique_ptr<Node> &&arg2) {
   if (arg1->data_type() != arg2->data_type()) {
     GRNXX_ERROR_SET(error, INVALID_OPERAND, "Data type conflict");
     return nullptr;

  Added: lib/grnxx/pipeline.cpp (+284 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/pipeline.cpp    2014-08-20 18:54:40 +0900 (856725b)
@@ -0,0 +1,284 @@
+#include "grnxx/pipeline.hpp"
+
+#include "grnxx/cursor.hpp"
+#include "grnxx/error.hpp"
+#include "grnxx/expression.hpp"
+
+namespace grnxx {
+namespace pipeline {
+
+class Node {
+ public:
+  Node() {}
+  virtual ~Node() {}
+
+  virtual Int read_next(Error *error, Array<Record> *records) = 0;
+  virtual Int read_all(Error *error, Array<Record> *records);
+};
+
+Int Node::read_all(Error *error, Array<Record> *records) {
+  Int total_count = 0;
+  for ( ; ; ) {
+    Int count = read_next(error, records);
+    if (count == -1) {
+      return -1;
+    } else if (count == 0) {
+      break;
+    }
+    total_count += count;
+  }
+  return total_count;
+}
+
+class CursorNode : public Node {
+ public:
+  explicit CursorNode(unique_ptr<Cursor> &&cursor)
+      : Node(),
+        cursor_(std::move(cursor)) {}
+  ~CursorNode() {}
+
+  Int read_next(Error *error, Array<Record> *records);
+  Int read_all(Error *error, Array<Record> *records);
+
+ private:
+  unique_ptr<Cursor> cursor_;
+};
+
+Int CursorNode::read_next(Error *error, Array<Record> *records) {
+  // TODO: The following block size (1024) should be optimized.
+  return cursor_->read(error, 1024, records);
+}
+
+Int CursorNode::read_all(Error *error, Array<Record> *records) {
+  return cursor_->read_all(error, records);
+}
+
+class FilterNode : public Node {
+ public:
+  FilterNode(unique_ptr<Node> &&arg,
+             unique_ptr<Expression> &&expression,
+             Int offset,
+             Int limit)
+      : Node(),
+        arg_(std::move(arg)),
+        expression_(std::move(expression)),
+        offset_(offset),
+        limit_(limit) {}
+  ~FilterNode() {}
+
+  Int read_next(Error *error, Array<Record> *records);
+
+ private:
+  unique_ptr<Node> arg_;
+  unique_ptr<Expression> expression_;
+  Int offset_;
+  Int limit_;
+};
+
+Int FilterNode::read_next(Error *error, Array<Record> *records) {
+  // TODO: The following threshold (1024) should be optimized.
+  Int offset = records->size();
+  for ( ; ; ) {
+    Int count = arg_->read_next(error, records);
+    if (count == -1) {
+      return -1;
+    } else if (count == 0) {
+      break;
+    }
+    // TODO: offset and limit are not supported yet.
+    if (!expression_->filter(error, records, offset)) {
+      return -1;
+    }
+    if (records->size() - offset) {
+      break;
+    }
+  }
+  return records->size() - offset;
+}
+
+class AdjusterNode : public Node {
+ public:
+  explicit AdjusterNode(unique_ptr<Node> &&arg,
+                        unique_ptr<Expression> &&expression)
+      : Node(),
+        arg_(std::move(arg)),
+        expression_(std::move(expression)) {}
+  ~AdjusterNode() {}
+
+  Int read_next(Error *error, Array<Record> *records);
+
+ private:
+  unique_ptr<Node> arg_;
+  unique_ptr<Expression> expression_;
+};
+
+Int AdjusterNode::read_next(Error *error, Array<Record> *records) {
+  Int offset = records->size();
+  Int count = arg_->read_next(error, records);
+  if (count == -1) {
+    return -1;
+  }
+  if (!expression_->adjust(error, records, offset)) {
+    return -1;
+  }
+  return count;
+}
+
+class SorterNode : public Node {
+ public:
+  explicit SorterNode(unique_ptr<Node> &&arg,
+                      unique_ptr<Sorter> &&sorter)
+      : Node(),
+        arg_(std::move(arg)),
+        sorter_(std::move(sorter)) {}
+  ~SorterNode() {}
+
+  Int read_next(Error *error, Array<Record> *records);
+
+ private:
+  unique_ptr<Node> arg_;
+  unique_ptr<Sorter> sorter_;
+};
+
+Int SorterNode::read_next(Error *error, Array<Record> *records) {
+  Int count = arg_->read_all(error, records);
+  if (count == -1) {
+    return -1;
+  } else if (count == 0) {
+    return 0;
+  }
+  if (!sorter_->sort(error, records)) {
+    return -1;
+  }
+  return records->size();
+}
+
+}  // namespace pipeline
+
+using namespace pipeline;
+
+Pipeline::~Pipeline() {}
+
+bool Pipeline::flush(Error *error, Array<Record> *records) {
+  return root_->read_all(error, records) >= 0;
+}
+
+unique_ptr<Pipeline> Pipeline::create(Error *error,
+                                      const Table *table,
+                                      unique_ptr<PipelineNode> &&root,
+                                      const PipelineOptions &options) {
+  unique_ptr<Pipeline> pipeline(
+      new (nothrow) Pipeline(table, std::move(root)));
+  if (!pipeline) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  return pipeline;
+}
+
+Pipeline::Pipeline(const Table *table,
+                   unique_ptr<PipelineNode> &&root)
+    : table_(table),
+      root_(std::move(root)) {}
+
+unique_ptr<PipelineBuilder> PipelineBuilder::create(Error *error,
+                                                    const Table *table) {
+  unique_ptr<PipelineBuilder> builder(new (nothrow) PipelineBuilder);
+  if (!builder) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  builder->table_ = table;
+  return builder;
+}
+
+PipelineBuilder::~PipelineBuilder() {}
+
+bool PipelineBuilder::push_cursor(Error *error, unique_ptr<Cursor> &&cursor) {
+  // Reserve a space for a new node.
+  if (!stack_.reserve(error, stack_.size() + 1)) {
+    return false;
+  }
+  unique_ptr<Node> node(new (nothrow) CursorNode(std::move(cursor)));
+  if (!node) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return false;
+  }
+  // This push_back() must not fail because a space is already reserved.
+  stack_.push_back(nullptr, std::move(node));
+  return true;
+}
+
+bool PipelineBuilder::push_filter(Error *error,
+                                  unique_ptr<Expression> &&expression,
+                                  Int offset, Int limit) {
+  if (stack_.size() < 1) {
+    GRNXX_ERROR_SET(error, INVALID_OPERAND, "Not enough nodes");
+    return false;
+  }
+  unique_ptr<Node> arg = std::move(stack_[stack_.size() - 1]);
+  stack_.resize(nullptr, stack_.size() - 1);
+  unique_ptr<Node> node(
+      new (nothrow) FilterNode(std::move(arg), std::move(expression),
+                               offset, limit));
+  if (!node) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return false;
+  }
+  stack_.push_back(error, std::move(node));
+  return true;
+}
+
+bool PipelineBuilder::push_adjuster(Error *error,
+                                    unique_ptr<Expression> &&expression) {
+  if (stack_.size() < 1) {
+    GRNXX_ERROR_SET(error, INVALID_OPERAND, "Not enough nodes");
+    return false;
+  }
+  unique_ptr<Node> arg = std::move(stack_[stack_.size() - 1]);
+  stack_.resize(nullptr, stack_.size() - 1);
+  unique_ptr<Node> node(
+      new (nothrow) AdjusterNode(std::move(arg), std::move(expression)));
+  if (!node) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return false;
+  }
+  stack_.push_back(error, std::move(node));
+  return true;
+}
+
+bool PipelineBuilder::push_sorter(Error *error, unique_ptr<Sorter> &&sorter) {
+  if (stack_.size() < 1) {
+    GRNXX_ERROR_SET(error, INVALID_OPERAND, "Not enough nodes");
+    return false;
+  }
+  unique_ptr<Node> arg = std::move(stack_[stack_.size() - 1]);
+  stack_.resize(nullptr, stack_.size() - 1);
+  unique_ptr<Node> node(
+      new (nothrow) SorterNode(std::move(arg), std::move(sorter)));
+  if (!node) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return false;
+  }
+  stack_.push_back(error, std::move(node));
+  return true;
+}
+
+void PipelineBuilder::clear() {
+  stack_.clear();
+}
+
+unique_ptr<Pipeline> PipelineBuilder::release(Error *error,
+                                              const PipelineOptions &options) {
+  if (stack_.size() != 1) {
+    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Incomplete pipeline");
+    return nullptr;
+  }
+  unique_ptr<PipelineNode> root = std::move(stack_[0]);
+  stack_.clear();
+  return Pipeline::create(error, table_, std::move(root), options);
+}
+
+PipelineBuilder::PipelineBuilder() : table_(nullptr), stack_() {}
+
+}  // namespace grnxx

  Modified: lib/grnxx/sorter.cpp (+3 -4)
===================================================================
--- lib/grnxx/sorter.cpp    2014-08-20 16:35:03 +0900 (7c1e791)
+++ lib/grnxx/sorter.cpp    2014-08-20 18:54:40 +0900 (2819b0b)
@@ -443,8 +443,8 @@ struct ReverseComparer {
 
 using namespace sorter;
 
-unique_ptr<SorterNode> SorterNode::create(Error *error, SortOrder &&order) {
-  unique_ptr<SorterNode> node;
+unique_ptr<Node> Node::create(Error *error, SortOrder &&order) {
+  unique_ptr<Node> node;
   switch (order.expression->data_type()) {
     case BOOL_DATA: {
       if (order.type == REGULAR_ORDER) {
@@ -554,8 +554,7 @@ unique_ptr<Sorter> Sorter::create(
   }
   sorter->table_ = table;
   for (Int i = orders.size() - 1; i >= 0; --i) {
-    unique_ptr<SorterNode> node(
-        SorterNode::create(error, std::move(orders[i])));
+    unique_ptr<Node> node(Node::create(error, std::move(orders[i])));
     if (!node) {
       return nullptr;
     }
-------------- next part --------------
HTML����������������������������...
Download 



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