Skip to content

Commit

Permalink
Add uts for rewriteInExpr() and rewriteLogicalAndToLogicalOr()
Browse files Browse the repository at this point in the history
  • Loading branch information
Aiee committed Sep 26, 2021
1 parent 19df79e commit d05e508
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 14 deletions.
10 changes: 1 addition & 9 deletions src/graph/optimizer/rule/OptimizeTagIndexScanByFilterRule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,7 @@ bool OptimizeTagIndexScanByFilterRule::match(OptContext* ctx, const MatchedResul
}

// Case2: logical AND expr
if (condition->kind() == ExprKind::kLogicalAnd) {
// for (auto operand : static_cast<const LogicalExpression*>(condition)->operands()) {
// if (operand->kind() == ExprKind::kRelIn) {
// return false;
// }
// }
return true;
}
return false;
return condition->kind() == ExprKind::kLogicalAnd;
}

TagIndexScan* makeTagIndexScan(QueryContext* qctx, const TagIndexScan* scan, bool isPrefixScan) {
Expand Down
2 changes: 1 addition & 1 deletion src/graph/util/ExpressionUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ Expression *ExpressionUtils::rewriteLogicalAndToLogicalOr(const Expression *expr
}

// orExprOperands is a 2D vector where each sub-vector is the operands of AND expression.
// [[A, C], [A, D], [B, C], [B,D]] => (A and C) or (A and D) or (B and C) or (B or D)
// [[A, C], [A, D], [B, C], [B,D]] => (A and C) or (A and D) or (B and C) or (B and D)
std::vector<Expression *> andExprList;
andExprList.reserve(orExprOperands.size());
for (auto &operand : orExprOperands) {
Expand Down
75 changes: 75 additions & 0 deletions src/graph/util/test/ExpressionUtilsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,81 @@ TEST_F(ExpressionUtilsTest, flattenInnerLogicalExpr) {
}
}

TEST_F(ExpressionUtilsTest, rewriteInExpr) {
auto elist1 = ExpressionList::make(pool);
(*elist1).add(ConstantExpression::make(pool, 10)).add(ConstantExpression::make(pool, 20));
auto listExpr1 = ListExpression::make(pool, elist1);

auto elist2 = ExpressionList::make(pool);
(*elist2).add(ConstantExpression::make(pool, "a")).add(ConstantExpression::make(pool, "b"));
auto listExpr2 = ListExpression::make(pool, elist2);

auto elist3 = ExpressionList::make(pool);
(*elist3).add(ConstantExpression::make(pool, 100));
auto listExpr3 = ListExpression::make(pool, elist3);

// a IN [b,c] -> a==b OR a==c
{
auto inExpr1 =
RelationalExpression::makeIn(pool, ConstantExpression::make(pool, 10), listExpr1);
auto orExpr1 = ExpressionUtils::rewriteInExpr(inExpr1);
auto expected1 = LogicalExpression::makeOr(
pool,
RelationalExpression::makeEQ(
pool, ConstantExpression::make(pool, 10), ConstantExpression::make(pool, 10)),
RelationalExpression::makeEQ(
pool, ConstantExpression::make(pool, 10), ConstantExpression::make(pool, 20)));
ASSERT_EQ(*expected1, *orExpr1);

auto inExpr2 =
RelationalExpression::makeIn(pool, ConstantExpression::make(pool, "abc"), listExpr2);
auto orExpr2 = ExpressionUtils::rewriteInExpr(inExpr2);
auto expected2 = LogicalExpression::makeOr(
pool,
RelationalExpression::makeEQ(
pool, ConstantExpression::make(pool, "abc"), ConstantExpression::make(pool, "a")),
RelationalExpression::makeEQ(
pool, ConstantExpression::make(pool, "abc"), ConstantExpression::make(pool, "b")));
ASSERT_EQ(*expected2, *orExpr2);
}

// a IN [b] -> a == b
{
auto inExpr = RelationalExpression::makeIn(pool, ConstantExpression::make(pool, 10), listExpr3);
auto expected = RelationalExpression::makeEQ(
pool, ConstantExpression::make(pool, 10), ConstantExpression::make(pool, 100));
ASSERT_EQ(*expected, *ExpressionUtils::rewriteInExpr(inExpr));
}
}

TEST_F(ExpressionUtilsTest, rewriteLogicalAndToLogicalOr) {
auto orExpr1 = LogicalExpression::makeOr(
pool, ConstantExpression::make(pool, 10), ConstantExpression::make(pool, 20));
auto orExpr2 = LogicalExpression::makeOr(
pool, ConstantExpression::make(pool, "a"), ConstantExpression::make(pool, "b"));

// (a OR b) AND (c OR d) -> (a AND c) OR (a AND d) OR (b AND c) OR (b AND d)
{
auto andExpr = LogicalExpression::makeAnd(pool, orExpr1, orExpr2);
auto transformedExpr = ExpressionUtils::rewriteLogicalAndToLogicalOr(andExpr);

std::vector<Expression *> orOperands = {
LogicalExpression::makeAnd(
pool, ConstantExpression::make(pool, 10), ConstantExpression::make(pool, "a")),
LogicalExpression::makeAnd(
pool, ConstantExpression::make(pool, 10), ConstantExpression::make(pool, "b")),
LogicalExpression::makeAnd(
pool, ConstantExpression::make(pool, 20), ConstantExpression::make(pool, "a")),
LogicalExpression::makeAnd(
pool, ConstantExpression::make(pool, 20), ConstantExpression::make(pool, "b"))};

auto expected = LogicalExpression::makeOr(pool);
expected->setOperands(orOperands);

ASSERT_EQ(*expected, *transformedExpr);
}
}

TEST_F(ExpressionUtilsTest, splitFilter) {
using Kind = Expression::Kind;
{
Expand Down
4 changes: 0 additions & 4 deletions src/graph/validator/LookupValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,6 @@ StatusOr<Expression*> LookupValidator::handleLogicalExprOperands(LogicalExpressi
auto& operands = lExpr->operands();
for (auto i = 0u; i < operands.size(); i++) {
auto operand = lExpr->operand(i);
// if (operand->isLogicalExpr()) {
// // Not allow different logical expression to use: A AND B OR C
// return Status::SemanticError("Not supported filter: %s", lExpr->toString().c_str());
// }
auto ret = checkFilter(operand);
NG_RETURN_IF_ERROR(ret);

Expand Down

0 comments on commit d05e508

Please sign in to comment.