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