diff --git a/src/graph/optimizer/rule/PushFilterDownTraverseRule.cpp b/src/graph/optimizer/rule/PushFilterDownTraverseRule.cpp index 0ad74b1dd01..6ed65388839 100644 --- a/src/graph/optimizer/rule/PushFilterDownTraverseRule.cpp +++ b/src/graph/optimizer/rule/PushFilterDownTraverseRule.cpp @@ -55,6 +55,7 @@ StatusOr PushFilterDownTraverseRule::transform( auto* filterGroup = filterGroupNode->group(); auto* filter = static_cast(filterGroupNode->node()); auto* condition = filter->condition(); + LOG(ERROR) << "condition: " << condition->toString(); auto* avGroupNode = matched.dependencies[0].node; auto* av = static_cast(avGroupNode->node()); @@ -67,26 +68,32 @@ StatusOr PushFilterDownTraverseRule::transform( auto pool = qctx->objPool(); // Pick the expr looks like `$-.e[0].likeness - auto picker = [&edgeAlias](const Expression* e) -> bool { - // TODO(jie): Handle the strange exists expr. e.g. exists(e.likeness) - auto exprs = graph::ExpressionUtils::collectAll(e, {Expression::Kind::kPredicate}); - for (auto* expr : exprs) { - if (static_cast(expr)->name() == "exists") { + auto picker = [&edgeAlias](const Expression* expr) -> bool { + bool shouldNotPick = false; + auto finder = [&shouldNotPick, &edgeAlias](const Expression* e) -> bool { + if (e->kind() == Expression::Kind::kInputProperty || + e->kind() == Expression::Kind::kVarProperty) { + shouldNotPick = true; + return false; + } + + // TODO(jie): Handle the strange exists expr. e.g. exists(e.likeness) + if (e->kind() == Expression::Kind::kPredicate && + static_cast(e)->name() == "exists") { + shouldNotPick = true; return false; } - } - auto varProps = graph::ExpressionUtils::collectAll( - e, {Expression::Kind::kInputProperty, Expression::Kind::kVarProperty}); - if (varProps.empty()) { + if (graph::ExpressionUtils::isOneStepEdgeProp(edgeAlias, e)) return true; return false; + }; + graph::FindVisitor visitor(finder, true, true); + const_cast(expr)->accept(&visitor); + if (shouldNotPick) return false; + if (!visitor.results().empty()) { + return true; } - for (auto* expr : varProps) { - DCHECK(graph::ExpressionUtils::isPropertyExpr(expr)); - auto& propName = static_cast(expr)->prop(); - if (propName != edgeAlias) return false; - } - return true; + return false; }; Expression* filterPicked = nullptr; Expression* filterUnpicked = nullptr; @@ -97,10 +104,12 @@ StatusOr PushFilterDownTraverseRule::transform( } auto* newFilterPicked = graph::ExpressionUtils::rewriteEdgePropertyFilter(pool, edgeAlias, filterPicked->clone()); + LOG(ERROR) << "newFilterPicked: " << newFilterPicked->toString(); Filter* newFilter = nullptr; OptGroupNode* newFilterGroupNode = nullptr; if (filterUnpicked) { + LOG(ERROR) << "filterUnpicked: " << filterUnpicked->toString(); newFilter = Filter::make(qctx, nullptr, filterUnpicked); newFilter->setOutputVar(filter->outputVar()); newFilter->setColNames(filter->colNames()); @@ -125,6 +134,8 @@ StatusOr PushFilterDownTraverseRule::transform( ? LogicalExpression::makeAnd(pool, newFilterPicked, eFilter->clone()) : newFilterPicked; + LOG(ERROR) << "newEFilter: " << newEFilter->toString(); + auto* newTv = static_cast(tv->clone()); newAv->setInputVar(newTv->outputVar()); newTv->setEdgeFilter(newEFilter); diff --git a/src/graph/util/ExpressionUtils.cpp b/src/graph/util/ExpressionUtils.cpp index 54b06b3d959..71499459358 100644 --- a/src/graph/util/ExpressionUtils.cpp +++ b/src/graph/util/ExpressionUtils.cpp @@ -152,6 +152,38 @@ Expression *ExpressionUtils::rewriteAttr2LabelTagProp( return RewriteVisitor::transform(expr, std::move(matcher), std::move(rewriter)); } +// rewrite rank(e) to e._rank +Expression *ExpressionUtils::rewriteRankFunc2LabelAttribute( + const Expression *expr, const std::unordered_map &aliasTypeMap) { + ObjectPool *pool = expr->getObjPool(); + auto matcher = [&aliasTypeMap](const Expression *e) -> bool { + if (e->kind() != Expression::Kind::kFunctionCall) return false; + + auto *funcExpr = static_cast(e); + auto funcName = funcExpr->name(); + std::transform(funcName.begin(), funcName.end(), funcName.begin(), ::tolower); + if (funcName != "rank") return false; + auto args = funcExpr->args()->args(); + if (args.size() != 1) return false; + if (args[0]->kind() != Expression::Kind::kLabel) return false; + + auto &label = static_cast(args[0])->name(); + auto iter = aliasTypeMap.find(label); + if (iter == aliasTypeMap.end() || iter->second != AliasType::kEdge) { + return false; + } + return true; + }; + auto rewriter = [pool](const Expression *e) -> Expression * { + auto funcExpr = static_cast(e); + auto args = funcExpr->args()->args(); + return LabelAttributeExpression::make( + pool, static_cast(args[0]), ConstantExpression::make(pool, "_rank")); + }; + + return RewriteVisitor::transform(expr, std::move(matcher), std::move(rewriter)); +} + Expression *ExpressionUtils::rewriteLabelAttr2TagProp(const Expression *expr) { ObjectPool *pool = expr->getObjPool(); auto matcher = [](const Expression *e) -> bool { @@ -1518,7 +1550,7 @@ bool ExpressionUtils::checkExprDepth(const Expression *expr) { } /*static*/ -bool ExpressionUtils::isSingleLenExpandExpr(const std::string &edgeAlias, const Expression *expr) { +bool ExpressionUtils::isOneStepEdgeProp(const std::string &edgeAlias, const Expression *expr) { if (expr->kind() != Expression::Kind::kAttribute) { return false; } @@ -1562,7 +1594,7 @@ bool ExpressionUtils::isSingleLenExpandExpr(const std::string &edgeAlias, const const std::string &edgeAlias, Expression *expr) { graph::RewriteVisitor::Matcher matcher = [&edgeAlias](const Expression *e) -> bool { - return isSingleLenExpandExpr(edgeAlias, e); + return isOneStepEdgeProp(edgeAlias, e); }; graph::RewriteVisitor::Rewriter rewriter = [pool](const Expression *e) -> Expression * { DCHECK_EQ(e->kind(), Expression::Kind::kAttribute); diff --git a/src/graph/util/ExpressionUtils.h b/src/graph/util/ExpressionUtils.h index ac10f1570d7..87dc45b0090 100644 --- a/src/graph/util/ExpressionUtils.h +++ b/src/graph/util/ExpressionUtils.h @@ -64,6 +64,10 @@ class ExpressionUtils { static Expression* rewriteAttr2LabelTagProp( const Expression* expr, const std::unordered_map& aliasTypeMap); + // rewrite rank(e) to e._rank + static Expression* rewriteRankFunc2LabelAttribute( + const Expression* expr, const std::unordered_map& aliasTypeMap); + // rewrite LabelAttr to tagProp static Expression* rewriteLabelAttr2TagProp(const Expression* expr); @@ -239,7 +243,7 @@ class ExpressionUtils { static bool isVidPredication(const Expression* expr); // Check if the expr looks like `$-.e[0].likeness` - static bool isSingleLenExpandExpr(const std::string& edgeAlias, const Expression* expr); + static bool isOneStepEdgeProp(const std::string& edgeAlias, const Expression* expr); static Expression* rewriteEdgePropertyFilter(ObjectPool* pool, const std::string& edgeAlias, diff --git a/src/graph/validator/MatchValidator.cpp b/src/graph/validator/MatchValidator.cpp index 0abb29431ca..59600f43d1b 100644 --- a/src/graph/validator/MatchValidator.cpp +++ b/src/graph/validator/MatchValidator.cpp @@ -333,13 +333,23 @@ Status MatchValidator::buildEdgeInfo(const MatchPath *path, // Rewrite expression to fit semantic, check type and check used aliases. Status MatchValidator::validateFilter(const Expression *filter, WhereClauseContext &whereClauseCtx) { + LOG(ERROR) << "filter: " << filter->toString(); auto *newFilter = graph::ExpressionUtils::rewriteParameter(filter, qctx_); + LOG(ERROR) << "newFilter after rewriteParameter: " << newFilter->toString(); newFilter = graph::ExpressionUtils::rewriteInnerInExpr(filter); + LOG(ERROR) << "newFilter after rewriteInnerInExpr: " << newFilter->toString(); auto transformRes = ExpressionUtils::filterTransform(newFilter); NG_RETURN_IF_ERROR(transformRes); + LOG(ERROR) << "transformRes after filterTransform: " << transformRes.value()->toString(); // rewrite Attribute to LabelTagProperty - whereClauseCtx.filter = ExpressionUtils::rewriteAttr2LabelTagProp( - transformRes.value(), whereClauseCtx.aliasesAvailable); + newFilter = ExpressionUtils::rewriteAttr2LabelTagProp(transformRes.value(), + whereClauseCtx.aliasesAvailable); + LOG(ERROR) << "newFilter after rewriteAttr2LabelTagProp: " << newFilter->toString(); + newFilter = + ExpressionUtils::rewriteRankFunc2LabelAttribute(newFilter, whereClauseCtx.aliasesAvailable); + LOG(ERROR) << "newFilter after rewriteRankFunc2LabelAttribute: " << newFilter->toString(); + + whereClauseCtx.filter = newFilter; auto typeStatus = deduceExprType(whereClauseCtx.filter); NG_RETURN_IF_ERROR(typeStatus); diff --git a/src/graph/visitor/FindVisitor.cpp b/src/graph/visitor/FindVisitor.cpp index a86efc4e0f7..90ddb618158 100644 --- a/src/graph/visitor/FindVisitor.cpp +++ b/src/graph/visitor/FindVisitor.cpp @@ -7,19 +7,19 @@ namespace nebula { namespace graph { void FindVisitor::visit(TypeCastingExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; expr->operand()->accept(this); } void FindVisitor::visit(UnaryExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; expr->operand()->accept(this); } void FindVisitor::visit(FunctionCallExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; for (const auto& arg : expr->args()->args()) { arg->accept(this); @@ -28,13 +28,13 @@ void FindVisitor::visit(FunctionCallExpression* expr) { } void FindVisitor::visit(AggregateExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; expr->arg()->accept(this); } void FindVisitor::visit(ListExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; for (const auto& item : expr->items()) { item->accept(this); @@ -43,7 +43,7 @@ void FindVisitor::visit(ListExpression* expr) { } void FindVisitor::visit(SetExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; for (const auto& item : expr->items()) { item->accept(this); @@ -52,7 +52,7 @@ void FindVisitor::visit(SetExpression* expr) { } void FindVisitor::visit(MapExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; for (const auto& pair : expr->items()) { pair.second->accept(this); @@ -61,7 +61,7 @@ void FindVisitor::visit(MapExpression* expr) { } void FindVisitor::visit(CaseExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; if (expr->hasCondition()) { @@ -81,7 +81,7 @@ void FindVisitor::visit(CaseExpression* expr) { } void FindVisitor::visit(PredicateExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; expr->collection()->accept(this); @@ -92,7 +92,7 @@ void FindVisitor::visit(PredicateExpression* expr) { } void FindVisitor::visit(ReduceExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; expr->initial()->accept(this); @@ -104,7 +104,7 @@ void FindVisitor::visit(ReduceExpression* expr) { } void FindVisitor::visit(ListComprehensionExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; expr->collection()->accept(this); @@ -121,7 +121,7 @@ void FindVisitor::visit(ListComprehensionExpression* expr) { } void FindVisitor::visit(LogicalExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; for (const auto& operand : expr->operands()) { operand->accept(this); @@ -130,67 +130,67 @@ void FindVisitor::visit(LogicalExpression* expr) { } void FindVisitor::visit(ConstantExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(EdgePropertyExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(TagPropertyExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(InputPropertyExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(VariablePropertyExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(SourcePropertyExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(DestPropertyExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(EdgeSrcIdExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(EdgeTypeExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(EdgeRankExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(EdgeDstIdExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(UUIDExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(VariableExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(VersionedVariableExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(LabelExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(LabelAttributeExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; expr->left()->accept(this); if (!needFindAll_ && !foundExprs_.empty()) return; @@ -198,25 +198,25 @@ void FindVisitor::visit(LabelAttributeExpression* expr) { } void FindVisitor::visit(VertexExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(LabelTagPropertyExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; expr->label()->accept(this); } void FindVisitor::visit(EdgeExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(ColumnExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; } void FindVisitor::visit(PathBuildExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; for (const auto& item : expr->items()) { item->accept(this); @@ -225,7 +225,7 @@ void FindVisitor::visit(PathBuildExpression* expr) { } void FindVisitor::visit(SubscriptRangeExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; expr->list()->accept(this); @@ -243,7 +243,7 @@ void FindVisitor::visit(SubscriptRangeExpression* expr) { } void FindVisitor::visit(MatchPathPatternExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; if (expr->genList() != nullptr) { expr->genList()->accept(this); @@ -252,17 +252,19 @@ void FindVisitor::visit(MatchPathPatternExpression* expr) { } void FindVisitor::visitBinaryExpr(BinaryExpression* expr) { - findInCurrentExpr(expr); + if (findInCurrentExpr(expr) && stopVisitChildrenAfterFind_) return; if (!needFindAll_ && !foundExprs_.empty()) return; expr->left()->accept(this); if (!needFindAll_ && !foundExprs_.empty()) return; expr->right()->accept(this); } -void FindVisitor::findInCurrentExpr(Expression* expr) { +bool FindVisitor::findInCurrentExpr(Expression* expr) { if (finder_(expr)) { foundExprs_.emplace_back(expr); + return true; } + return false; } } // namespace graph diff --git a/src/graph/visitor/FindVisitor.h b/src/graph/visitor/FindVisitor.h index b2b779fd3b3..7df710e9cbc 100644 --- a/src/graph/visitor/FindVisitor.h +++ b/src/graph/visitor/FindVisitor.h @@ -15,8 +15,12 @@ class FindVisitor final : public ExprVisitorImpl { public: using Finder = std::function; - explicit FindVisitor(Finder finder, bool needFindAll = false) - : finder_(finder), needFindAll_(needFindAll) {} + explicit FindVisitor(Finder finder, + bool needFindAll = false, + bool stopVisitChildrenAfterFind = false) + : finder_(finder), + needFindAll_(needFindAll), + stopVisitChildrenAfterFind_(stopVisitChildrenAfterFind) {} bool ok() const override { // TODO: delete this interface @@ -80,11 +84,12 @@ class FindVisitor final : public ExprVisitorImpl { void visit(MatchPathPatternExpression* expr) override; void visitBinaryExpr(BinaryExpression* expr) override; - void findInCurrentExpr(Expression* expr); + bool findInCurrentExpr(Expression* expr); private: Finder finder_; bool needFindAll_; + bool stopVisitChildrenAfterFind_{false}; std::vector foundExprs_; };