Skip to content

Commit

Permalink
Fix undefined parameter (#5404)
Browse files Browse the repository at this point in the history
* Fix undefined parameter

Fix tck

Fix tck

small skip for ldbc tck

fmt

* small change

* Fix error message

* small change
  • Loading branch information
czpmango authored Mar 17, 2023
1 parent c2ebc02 commit 9fee385
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 9 deletions.
19 changes: 12 additions & 7 deletions src/graph/optimizer/rule/GeoPredicateIndexScanBaseRule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ bool GeoPredicateIndexScanBaseRule::match(OptContext* ctx, const MatchedResult&

StatusOr<TransformResult> GeoPredicateIndexScanBaseRule::transform(
OptContext* ctx, const MatchedResult& matched) const {
auto qctx = ctx->qctx();
auto filter = static_cast<const Filter*>(matched.planNode());
auto node = matched.planNode({0, 0});
auto scan = static_cast<const IndexScan*>(node);

auto metaClient = ctx->qctx()->getMetaClient();
auto metaClient = qctx->getMetaClient();
auto status = node->kind() == graph::PlanNode::Kind::kTagIndexFullScan
? metaClient->getTagIndexesFromCache(scan->space())
: metaClient->getEdgeIndexesFromCache(scan->space());
Expand Down Expand Up @@ -109,10 +110,14 @@ StatusOr<TransformResult> GeoPredicateIndexScanBaseRule::transform(
} else if (geoPredicateName == "st_dwithin") {
DCHECK_GE(geoPredicate->args()->numArgs(), 3);
auto* third = geoPredicate->args()->args()[2];
DCHECK_EQ(third->kind(), Expression::Kind::kConstant);
const auto& thirdVal = static_cast<const ConstantExpression*>(third)->value();
DCHECK(thirdVal.isNumeric());
double distanceInMeters = thirdVal.isFloat() ? thirdVal.getFloat() : thirdVal.getInt();
if (!graph::ExpressionUtils::isEvaluableExpr(third, qctx)) {
return TransformResult::noTransform();
}
auto thirdVal = third->eval(graph::QueryExpressionContext(qctx->ectx())());
if (!thirdVal.isNumeric()) {
return TransformResult::noTransform();
}
auto distanceInMeters = thirdVal.isFloat() ? thirdVal.getFloat() : thirdVal.getInt();
scanRanges = geoIndex.dWithin(geog, distanceInMeters);
}
std::vector<IndexQueryContext> idxCtxs;
Expand All @@ -128,8 +133,8 @@ StatusOr<TransformResult> GeoPredicateIndexScanBaseRule::transform(
idxCtxs.emplace_back(std::move(ictx));
}

auto scanNode = IndexScan::make(ctx->qctx(), nullptr);
OptimizerUtils::copyIndexScanData(scan, scanNode, ctx->qctx());
auto scanNode = IndexScan::make(qctx, nullptr);
OptimizerUtils::copyIndexScanData(scan, scanNode, qctx);
scanNode->setIndexQueryContext(std::move(idxCtxs));
// TODO(jie): geo predicate's calculation is a little heavy,
// which is not suitable to push down to the storage
Expand Down
38 changes: 38 additions & 0 deletions src/graph/util/ExpressionUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,44 @@ Expression *ExpressionUtils::rewriteParameter(const Expression *expr, QueryConte
return graph::RewriteVisitor::transform(expr, matcher, rewriter);
}

std::vector<const Expression *> ExpressionUtils::ExtractInnerVarExprs(const Expression *expr,
QueryContext *qctx) {
auto finder = [qctx](const Expression *e) -> bool {
auto ve = static_cast<const VariableExpression *>(e);
return e->kind() == Expression::Kind::kVar && !qctx->existParameter(ve->var()) &&
!ve->isInner();
};

if (finder(expr)) {
return {expr};
}
FindVisitor visitor(finder);
const_cast<Expression *>(expr)->accept(&visitor);
return visitor.results();
}

std::vector<std::string> ExpressionUtils::ExtractInnerVars(const Expression *expr,
QueryContext *qctx) {
auto finder = [qctx](const Expression *e) -> bool {
auto ve = static_cast<const VariableExpression *>(e);
return e->kind() == Expression::Kind::kVar && !qctx->existParameter(ve->var()) &&
!ve->isInner();
};

if (finder(expr)) {
return {static_cast<const VariableExpression *>(expr)->var()};
}
FindVisitor visitor(finder, true);
const_cast<Expression *>(expr)->accept(&visitor);
auto varExprs = visitor.results();
std::vector<std::string> vars;
vars.reserve(varExprs.size());
for (const auto *varExpr : varExprs) {
vars.emplace_back(static_cast<const VariableExpression *>(varExpr)->var());
}
return vars;
}

Expression *ExpressionUtils::rewriteInnerInExpr(const Expression *expr) {
auto matcher = [](const Expression *e) -> bool {
if (e->kind() != Expression::Kind::kRelIn) {
Expand Down
7 changes: 7 additions & 0 deletions src/graph/util/ExpressionUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ class ExpressionUtils {
// Rewrites ParameterExpression to ConstantExpression
static Expression* rewriteParameter(const Expression* expr, QueryContext* qctx);

// Extract all inner Variable expressions
static std::vector<const Expression*> ExtractInnerVarExprs(const Expression* expr,
QueryContext* qctx);

// Extract all inner Variable names
static std::vector<std::string> ExtractInnerVars(const Expression* expr, QueryContext* qctx);

// Rewrite RelInExpr with only one operand in expression tree
static Expression* rewriteInnerInExpr(const Expression* expr);

Expand Down
15 changes: 15 additions & 0 deletions src/graph/validator/LookupValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,21 @@ Status LookupValidator::validateWhere() {

auto* filter = whereClause->filter();
if (filter != nullptr) {
auto vars = graph::ExpressionUtils::ExtractInnerVars(filter, qctx_);
std::vector<std::string> undefinedParams;
for (const auto& var : vars) {
if (!vctx_->existVar(var)) {
undefinedParams.emplace_back(var);
}
}
if (!undefinedParams.empty()) {
return Status::SemanticError(
"Undefined parameters: " +
std::accumulate(++undefinedParams.begin(),
undefinedParams.end(),
*undefinedParams.begin(),
[](auto& lhs, auto& rhs) { return lhs + ", " + rhs; }));
}
filter = graph::ExpressionUtils::rewriteParameter(filter, qctx_);
}
if (FTIndexUtils::needTextSearch(filter)) {
Expand Down
10 changes: 10 additions & 0 deletions src/graph/validator/MatchValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,16 @@ 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) {
auto undefinedParams = graph::ExpressionUtils::ExtractInnerVars(filter, qctx_);
if (!undefinedParams.empty()) {
return Status::SemanticError(
"Undefined parameters: " +
std::accumulate(++undefinedParams.begin(),
undefinedParams.end(),
*undefinedParams.begin(),
[](auto &lhs, auto &rhs) { return lhs + ", " + rhs; }));
}

auto *newFilter = graph::ExpressionUtils::rewriteParameter(filter, qctx_);
auto transformRes = ExpressionUtils::filterTransform(newFilter);
NG_RETURN_IF_ERROR(transformRes);
Expand Down
4 changes: 2 additions & 2 deletions tests/tck/features/ttl/TTL.feature
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ Feature: TTLTest
"""
CREATE TAG t1(name string, age int)
"""
And wait 3 seconds
And wait 5 seconds
When executing query:
"""
INSERT VERTEX t1(name, age) VALUES "1":("tom", 18)
Expand All @@ -522,7 +522,7 @@ Feature: TTLTest
ALTER TAG t1 TTL_DURATION = 30, TTL_COL = "n";
"""
Then the execution should be successful
And wait 3 seconds
And wait 5 seconds
When executing query:
"""
INSERT VERTEX t1(name, age) VALUES "2":("jerry", 18)
Expand Down
15 changes: 15 additions & 0 deletions tests/tck/features/yield/parameter.feature
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,21 @@ Feature: Parameter
LOOKUP ON player WHERE player.age>$p2+43
"""
Then a SemanticError should be raised at runtime: Type error `(true+43)'
When executing query:
"""
LOOKUP ON player WHERE ST_Distance(player.age, ST_Point($p1,$p7.a.b.c.d[0])) < $unknown_distance YIELD id(vertex)
"""
Then a SemanticError should be raised at runtime: Undefined parameters: unknown_distance
When executing query:
"""
LOOKUP ON player WHERE ST_Distance(player.age, ST_Point($p1,$p7.a.b.c.d[0])) < $unknown_distance+$unknown_factor YIELD id(vertex)
"""
Then a SemanticError should be raised at runtime: Undefined parameters: unknown_distance, unknown_factor
When executing query:
"""
MATCH (v:player) where v.player.age < $unknown_distance RETURN v
"""
Then a SemanticError should be raised at runtime: Undefined parameters: unknown_distance
When executing query:
"""
MATCH (v:player) RETURN v LIMIT $p6
Expand Down
1 change: 1 addition & 0 deletions tests/tck/ldbc/interactive_workload/ComplexReads.feature
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ Feature: LDBC Interactive Workload - Complex Reads
Then the result should be, in any order:
| personId | personFirstName | personLastName | commonInterestScore | personGender | personCityName |
@skip # Undefined parameters
Scenario: 11. Job referral
When executing query:
"""
Expand Down

0 comments on commit 9fee385

Please sign in to comment.