Skip to content

Commit

Permalink
Fix graphd's crash due to lack of support of xor. (#4952)
Browse files Browse the repository at this point in the history
* add some support for xor.

* minor

Co-authored-by: Sophie <[email protected]>
  • Loading branch information
xtcyclist and Sophie-Xie authored Nov 30, 2022
1 parent e1a0283 commit 92ac71a
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 3 deletions.
27 changes: 24 additions & 3 deletions src/graph/util/ExpressionUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,14 @@ void ExpressionUtils::pullOrs(Expression *expr) {
logic->setOperands(std::move(operands));
}

void ExpressionUtils::pullXors(Expression *expr) {
DCHECK(expr->kind() == Expression::Kind::kLogicalXor);
auto *logic = static_cast<LogicalExpression *>(expr);
std::vector<Expression *> operands;
pullXorsImpl(logic, operands);
logic->setOperands(std::move(operands));
}

void ExpressionUtils::pullAndsImpl(LogicalExpression *expr, std::vector<Expression *> &operands) {
for (auto &operand : expr->operands()) {
if (operand->kind() != Expression::Kind::kLogicalAnd) {
Expand All @@ -778,6 +786,16 @@ void ExpressionUtils::pullOrsImpl(LogicalExpression *expr, std::vector<Expressio
}
}

void ExpressionUtils::pullXorsImpl(LogicalExpression *expr, std::vector<Expression *> &operands) {
for (auto &operand : expr->operands()) {
if (operand->kind() != Expression::Kind::kLogicalXor) {
operands.emplace_back(std::move(operand));
continue;
}
pullXorsImpl(static_cast<LogicalExpression *>(operand), operands);
}
}

Expression *ExpressionUtils::flattenInnerLogicalAndExpr(const Expression *expr) {
auto matcher = [](const Expression *e) -> bool {
return e->kind() == Expression::Kind::kLogicalAnd;
Expand Down Expand Up @@ -1094,8 +1112,12 @@ LogicalExpression *ExpressionUtils::reverseLogicalExpr(LogicalExpression *expr)
std::vector<Expression *> operands;
if (expr->kind() == Expression::Kind::kLogicalAnd) {
pullAnds(expr);
} else {
} else if (expr->kind() == Expression::Kind::kLogicalOr) {
pullOrs(expr);
} else if (expr->kind() == Expression::Kind::kLogicalXor) {
pullXors(expr);
} else {
LOG(FATAL) << "Invalid logical expression kind: " << static_cast<uint8_t>(expr->kind());
}

auto &flattenOperands = static_cast<LogicalExpression *>(expr)->operands();
Expand All @@ -1118,8 +1140,7 @@ Expression::Kind ExpressionUtils::getNegatedLogicalExprKind(const Expression::Ki
case Expression::Kind::kLogicalOr:
return Expression::Kind::kLogicalAnd;
case Expression::Kind::kLogicalXor:
LOG(FATAL) << "Unsupported logical expression kind: " << static_cast<uint8_t>(kind);
break;
return Expression::Kind::kLogicalXor;
default:
LOG(FATAL) << "Invalid logical expression kind: " << static_cast<uint8_t>(kind);
break;
Expand Down
5 changes: 5 additions & 0 deletions src/graph/util/ExpressionUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ class ExpressionUtils {
static void pullOrs(Expression* expr);
static void pullOrsImpl(LogicalExpression* expr, std::vector<Expression*>& operands);

// For a logical XOR expression, extracts all non-logicalXorExpr from its operands and set them as
// the new operands
static void pullXors(Expression* expr);
static void pullXorsImpl(LogicalExpression* expr, std::vector<Expression*>& operands);

// Constructs a nested logical OR expression
// Example:
// [expr1, expr2, expr3] => ((expr1 OR expr2) OR expr3)
Expand Down
21 changes: 21 additions & 0 deletions tests/tck/features/expression/LogicalExpression.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright (c) 2020 vesoft inc. All rights reserved.
#
# This source code is licensed under Apache 2.0 License.
Feature: Logical Expression

Scenario: xor crash bug fix 1
Given a graph with space named "nba"
When executing query:
"""
match (v0:player)-[e:serve]->(v1) where not ((e.start_year == 1997 xor e.end_year != 2016) or (e.start_year > 1000 and e.end_year < 3000)) return count(*)
"""
Then the result should be, in any order:
| count(*) |
| 0 |
When executing query:
"""
match (v0:player)-[e:serve]->(v1) where not ((e.start_year == 1997 xor e.end_year != 2016) and (e.start_year > 1000 and e.end_year < 3000)) return count(*)
"""
Then the result should be, in any order:
| count(*) |
| 140 |

0 comments on commit 92ac71a

Please sign in to comment.