prototype implementation
This commit is contained in:
@@ -398,7 +398,7 @@ cpp<#
|
|||||||
,@(loop for op in
|
,@(loop for op in
|
||||||
'(or-operator xor-operator and-operator addition-operator
|
'(or-operator xor-operator and-operator addition-operator
|
||||||
subtraction-operator multiplication-operator division-operator
|
subtraction-operator multiplication-operator division-operator
|
||||||
mod-operator not-equal-operator equal-operator less-operator
|
mod-operator not-equal-operator less-operator
|
||||||
greater-operator less-equal-operator greater-equal-operator
|
greater-operator less-equal-operator greater-equal-operator
|
||||||
in-list-operator subscript-operator)
|
in-list-operator subscript-operator)
|
||||||
collecting
|
collecting
|
||||||
@@ -458,6 +458,33 @@ cpp<#
|
|||||||
(:clone))))))
|
(:clone))))))
|
||||||
(define-unary-operators))
|
(define-unary-operators))
|
||||||
|
|
||||||
|
(lcp:define-class equal-operator (binary-operator)
|
||||||
|
((isNullCheckRequired "bool" :initval "false" :scope :public))
|
||||||
|
(:public
|
||||||
|
#>cpp
|
||||||
|
DEFVISITABLE(ExpressionVisitor<TypedValue>);
|
||||||
|
DEFVISITABLE(ExpressionVisitor<void>);
|
||||||
|
|
||||||
|
bool Accept(HierarchicalTreeVisitor &visitor) override {
|
||||||
|
if (visitor.PreVisit(*this)) {
|
||||||
|
expression1_->Accept(visitor) && expression2_->Accept(visitor);
|
||||||
|
}
|
||||||
|
return visitor.PostVisit(*this);
|
||||||
|
}
|
||||||
|
cpp<#)
|
||||||
|
(:protected
|
||||||
|
#>cpp
|
||||||
|
using BinaryOperator::BinaryOperator;
|
||||||
|
EqualOperator(Expression *expression1, Expression *expression2, bool is_nullcheck_required = false)
|
||||||
|
: BinaryOperator(expression1, expression2), isnullcheckrequired_(is_nullcheck_required) {}
|
||||||
|
cpp<#)
|
||||||
|
(:private
|
||||||
|
#>cpp
|
||||||
|
friend class AstStorage;
|
||||||
|
cpp<#)
|
||||||
|
(:serialize (:slk))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class aggregation (binary-operator)
|
(lcp:define-class aggregation (binary-operator)
|
||||||
((op "Op" :scope :public)
|
((op "Op" :scope :public)
|
||||||
(symbol-pos :int32_t :initval -1 :scope :public
|
(symbol-pos :int32_t :initval -1 :scope :public
|
||||||
|
|||||||
@@ -2267,9 +2267,9 @@ antlrcpp::Any CypherMainVisitor::visitCaseExpression(MemgraphCypher::CaseExpress
|
|||||||
Expression *else_expression = ctx->else_expression ? ctx->else_expression->accept(this).as<Expression *>()
|
Expression *else_expression = ctx->else_expression ? ctx->else_expression->accept(this).as<Expression *>()
|
||||||
: storage_->Create<PrimitiveLiteral>(TypedValue());
|
: storage_->Create<PrimitiveLiteral>(TypedValue());
|
||||||
for (auto *alternative : alternatives) {
|
for (auto *alternative : alternatives) {
|
||||||
Expression *condition =
|
Expression *condition = test_expression ? storage_->Create<EqualOperator>(
|
||||||
test_expression ? storage_->Create<EqualOperator>(test_expression, alternative->when_expression->accept(this))
|
test_expression, alternative->when_expression->accept(this), true)
|
||||||
: alternative->when_expression->accept(this).as<Expression *>();
|
: alternative->when_expression->accept(this).as<Expression *>();
|
||||||
Expression *then_expression = alternative->then_expression->accept(this);
|
Expression *then_expression = alternative->then_expression->accept(this);
|
||||||
else_expression = storage_->Create<IfOperator>(condition, then_expression, else_expression);
|
else_expression = storage_->Create<IfOperator>(condition, then_expression, else_expression);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
|
|||||||
BINARY_OPERATOR_VISITOR(DivisionOperator, /, /);
|
BINARY_OPERATOR_VISITOR(DivisionOperator, /, /);
|
||||||
BINARY_OPERATOR_VISITOR(ModOperator, %, %);
|
BINARY_OPERATOR_VISITOR(ModOperator, %, %);
|
||||||
BINARY_OPERATOR_VISITOR(NotEqualOperator, !=, <>);
|
BINARY_OPERATOR_VISITOR(NotEqualOperator, !=, <>);
|
||||||
BINARY_OPERATOR_VISITOR(EqualOperator, ==, =);
|
// BINARY_OPERATOR_VISITOR(EqualOperator, ==, =);
|
||||||
BINARY_OPERATOR_VISITOR(LessOperator, <, <);
|
BINARY_OPERATOR_VISITOR(LessOperator, <, <);
|
||||||
BINARY_OPERATOR_VISITOR(GreaterOperator, >, >);
|
BINARY_OPERATOR_VISITOR(GreaterOperator, >, >);
|
||||||
BINARY_OPERATOR_VISITOR(LessEqualOperator, <=, <=);
|
BINARY_OPERATOR_VISITOR(LessEqualOperator, <=, <=);
|
||||||
@@ -94,6 +94,29 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
|
|||||||
#undef BINARY_OPERATOR_VISITOR
|
#undef BINARY_OPERATOR_VISITOR
|
||||||
#undef UNARY_OPERATOR_VISITOR
|
#undef UNARY_OPERATOR_VISITOR
|
||||||
|
|
||||||
|
TypedValue Visit(EqualOperator &op) override {
|
||||||
|
auto val1 = op.expression1_->Accept(*this);
|
||||||
|
auto val2 = op.expression2_->Accept(*this);
|
||||||
|
|
||||||
|
// if(val1.IsNull())
|
||||||
|
// {
|
||||||
|
// val1.V
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if(op.isoperandnull_)
|
||||||
|
// throw QueryRuntimeException("Use the generic form when checking against NULL.");
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (op.isnullcheckrequired_ && val2.IsNull()) {
|
||||||
|
throw QueryRuntimeException("Use the generic form when checking against NULL.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return val1 == val2;
|
||||||
|
} catch (const TypedValueException &) {
|
||||||
|
throw QueryRuntimeException("Invalid types: {} and {} for '='.", val1.type(), val2.type());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TypedValue Visit(AndOperator &op) override {
|
TypedValue Visit(AndOperator &op) override {
|
||||||
auto value1 = op.expression1_->Accept(*this);
|
auto value1 = op.expression1_->Accept(*this);
|
||||||
if (value1.IsBool() && !value1.ValueBool()) {
|
if (value1.IsBool() && !value1.ValueBool()) {
|
||||||
|
|||||||
@@ -790,6 +790,26 @@ TEST_P(CypherMainVisitorTest, CaseSimpleForm) {
|
|||||||
ast_generator.CheckLiteral(if_operator->else_expression_, TypedValue());
|
ast_generator.CheckLiteral(if_operator->else_expression_, TypedValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(CypherMainVisitorTest, CaseSimpleFormNullcheckIsSet) {
|
||||||
|
auto &ast_generator = *GetParam();
|
||||||
|
auto *query = dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("RETURN CASE 5 WHEN 10 THEN 1 END"));
|
||||||
|
ASSERT_TRUE(query);
|
||||||
|
ASSERT_TRUE(query->single_query_);
|
||||||
|
auto *single_query = query->single_query_;
|
||||||
|
auto *return_clause = dynamic_cast<Return *>(single_query->clauses_[0]);
|
||||||
|
auto *if_operator = dynamic_cast<IfOperator *>(return_clause->body_.named_expressions[0]->expression_);
|
||||||
|
auto *condition = dynamic_cast<EqualOperator *>(if_operator->condition_);
|
||||||
|
ASSERT_TRUE(condition);
|
||||||
|
ast_generator.CheckLiteral(condition->expression1_, 5);
|
||||||
|
ast_generator.CheckLiteral(condition->expression2_, 10);
|
||||||
|
|
||||||
|
// This might be the only line thats different.
|
||||||
|
ASSERT_TRUE(condition->isnullcheckrequired_);
|
||||||
|
|
||||||
|
ast_generator.CheckLiteral(if_operator->then_expression_, 1);
|
||||||
|
ast_generator.CheckLiteral(if_operator->else_expression_, TypedValue());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_P(CypherMainVisitorTest, IsNull) {
|
TEST_P(CypherMainVisitorTest, IsNull) {
|
||||||
auto &ast_generator = *GetParam();
|
auto &ast_generator = *GetParam();
|
||||||
auto *query = dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("RETURN 2 iS NulL"));
|
auto *query = dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("RETURN 2 iS NulL"));
|
||||||
|
|||||||
Reference in New Issue
Block a user