[Groonga-commit] groonga/grnxx at 6de6e5b [master] Add comparison operators.

Back to archive index

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 



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