susumu.yata
null+****@clear*****
Mon Jul 14 15:12:20 JST 2014
susumu.yata 2014-07-14 15:12:20 +0900 (Mon, 14 Jul 2014) New Revision: 6de6e5ba8c5790e721e374fa33d33a0754a826cf https://github.com/groonga/grnxx/commit/6de6e5ba8c5790e721e374fa33d33a0754a826cf Message: Add comparison operators. Modified files: include/grnxx/expression.hpp lib/grnxx/expression.cpp test/test_grnxx.cpp Modified: include/grnxx/expression.hpp (+12 -1) =================================================================== --- include/grnxx/expression.hpp 2014-07-14 15:11:34 +0900 (50b7744) +++ include/grnxx/expression.hpp 2014-07-14 15:12:20 +0900 (4ed0b7b) @@ -12,8 +12,15 @@ enum OperatorType { // -- Binary operators -- + // Equality operators. EQUAL_OPERATOR, - NOT_EQUAL_OPERATOR + NOT_EQUAL_OPERATOR, + + // Comparison operators. + LESS_OPERATOR, + LESS_EQUAL_OPERATOR, + GREATER_OPERATOR, + GREATER_EQUAL_OPERATOR }; class Expression { @@ -115,8 +122,12 @@ class ExpressionBuilder { explicit ExpressionBuilder(const Table *table); + // Push an operator == or !=. template <typename T> bool push_equality_operator(Error *error); + // Push an operator <, <=, >, or >=. + template <typename T> + bool push_comparison_operator(Error *error); }; } // namespace grnxx Modified: lib/grnxx/expression.cpp (+104 -6) =================================================================== --- lib/grnxx/expression.cpp 2014-07-14 15:11:34 +0900 (265f4e1) +++ lib/grnxx/expression.cpp 2014-07-14 15:12:20 +0900 (77cf135) @@ -240,6 +240,54 @@ struct NotEqual { }; }; +struct Less { + template <typename T> + struct Functor { + using Arg1 = T; + using Arg2 = T; + using Result = Bool; + Bool operator()(Arg1 lhs, Arg2 rhs) const { + return lhs < rhs; + }; + }; +}; + +struct LessEqual { + template <typename T> + struct Functor { + using Arg1 = T; + using Arg2 = T; + using Result = Bool; + Bool operator()(Arg1 lhs, Arg2 rhs) const { + return lhs <= rhs; + }; + }; +}; + +struct Greater { + template <typename T> + struct Functor { + using Arg1 = T; + using Arg2 = T; + using Result = Bool; + Bool operator()(Arg1 lhs, Arg2 rhs) const { + return lhs > rhs; + }; + }; +}; + +struct GreaterEqual { + template <typename T> + struct Functor { + using Arg1 = T; + using Arg2 = T; + using Result = Bool; + Bool operator()(Arg1 lhs, Arg2 rhs) const { + return lhs >= rhs; + }; + }; +}; + template <typename Op> class BinaryNode : public Node<Bool> { public: @@ -410,6 +458,18 @@ bool ExpressionBuilder::push_operator(Error *error, case NOT_EQUAL_OPERATOR: { return push_equality_operator<NotEqual>(error); } + case LESS_OPERATOR: { + return push_comparison_operator<Less>(error); + } + case LESS_EQUAL_OPERATOR: { + return push_comparison_operator<LessEqual>(error); + } + case GREATER_OPERATOR: { + return push_comparison_operator<Greater>(error); + } + case GREATER_EQUAL_OPERATOR: { + return push_comparison_operator<GreaterEqual>(error); + } default: { // TODO: Not supported yet. GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supported yet"); @@ -451,17 +511,55 @@ bool ExpressionBuilder::push_equality_operator(Error *error) { unique_ptr<ExpressionNode> node; switch (lhs->data_type()) { case BOOL_DATA: { - typename T::template Functor<Bool> equal; - node.reset(new (nothrow) BinaryNode<decltype(equal)>( - equal, std::move(lhs), std::move(rhs))); + typename T::template Functor<Bool> functor; + node.reset(new (nothrow) BinaryNode<decltype(functor)>( + functor, std::move(lhs), std::move(rhs))); break; } case INT_DATA: { - typename T::template Functor<Int> equal; - node.reset(new (nothrow) BinaryNode<decltype(equal)>( - equal, std::move(lhs), std::move(rhs))); + typename T::template Functor<Int> functor; + node.reset(new (nothrow) BinaryNode<decltype(functor)>( + functor, std::move(lhs), std::move(rhs))); + break; + } + // TODO: Support other types. + default: { + GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supported yet"); + return false; + } + } + if (!node) { + GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); + return false; + } + stack_.pop_back(); + stack_.back() = std::move(node); + return true; +} + +template <typename T> +bool ExpressionBuilder::push_comparison_operator(Error *error) { + if (stack_.size() < 2) { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Not enough operands"); + return false; + } + auto &lhs = stack_[stack_.size() - 2]; + auto &rhs = stack_[stack_.size() - 1]; + if (lhs->data_type() != rhs->data_type()) { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Type conflict"); + return false; + } + unique_ptr<ExpressionNode> node; + switch (lhs->data_type()) { + case INT_DATA: { + typename T::template Functor<Int> functor; + node.reset(new (nothrow) BinaryNode<decltype(functor)>( + functor, std::move(lhs), std::move(rhs))); break; } + // TODO: Support other comparable types. default: { GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supported yet"); return false; Modified: test/test_grnxx.cpp (+34 -0) =================================================================== --- test/test_grnxx.cpp 2014-07-14 15:11:34 +0900 (c4b29b4) +++ test/test_grnxx.cpp 2014-07-14 15:12:20 +0900 (a8bb175) @@ -382,6 +382,40 @@ void test_expression() { assert(expression->filter(&error, &record_set)); assert(record_set.size() == 1); assert(record_set.get(0).row_id == 2); + + record_set.clear(); + cursor = table->create_cursor(&error, grnxx::CursorOptions()); + assert(cursor); + assert(cursor->read(&error, 2, &record_set) == 2); + + // 大小関係による比較を試す. + assert(builder->push_column(&error, "IntColumn")); + assert(builder->push_datum(&error, grnxx::Int(300))); + assert(builder->push_operator(&error, grnxx::LESS_OPERATOR)); + expression = builder->release(&error); + assert(expression); + + // フィルタとして使ったときの結果を確認する. + assert(expression->filter(&error, &record_set)); + assert(record_set.size() == 1); + assert(record_set.get(0).row_id == 1); + + record_set.clear(); + cursor = table->create_cursor(&error, grnxx::CursorOptions()); + assert(cursor); + assert(cursor->read(&error, 2, &record_set) == 2); + + // 大小関係による比較を試す. + assert(builder->push_column(&error, "IntColumn")); + assert(builder->push_datum(&error, grnxx::Int(456))); + assert(builder->push_operator(&error, grnxx::GREATER_EQUAL_OPERATOR)); + expression = builder->release(&error); + assert(expression); + + // フィルタとして使ったときの結果を確認する. + assert(expression->filter(&error, &record_set)); + assert(record_set.size() == 1); + assert(record_set.get(0).row_id == 2); } } // namespace -------------- next part -------------- HTML����������������������������...Download