diff --git a/src/codec/RowWriterV2.cpp b/src/codec/RowWriterV2.cpp index 5fcd457f30a..7bb881cfa1a 100644 --- a/src/codec/RowWriterV2.cpp +++ b/src/codec/RowWriterV2.cpp @@ -201,8 +201,13 @@ WriteResult RowWriterV2::setValue(ssize_t index, const Value& val) { } switch (val.type()) { - case Value::Type::NULLVALUE: + case Value::Type::NULLVALUE: { + if (val.isBadNull()) { + // Property value never be bad null + return WriteResult::TYPE_MISMATCH; + } return setNull(index); + } case Value::Type::BOOL: return write(index, val.getBool()); case Value::Type::INT: diff --git a/src/graph/util/SchemaUtil.cpp b/src/graph/util/SchemaUtil.cpp index 7180e2e2dda..4cae786348f 100644 --- a/src/graph/util/SchemaUtil.cpp +++ b/src/graph/util/SchemaUtil.cpp @@ -134,12 +134,12 @@ StatusOr SchemaUtil::toVertexID(Expression *expr, Value::Type vidType) { } // static -StatusOr> SchemaUtil::toValueVec(std::vector exprs) { +StatusOr> SchemaUtil::toValueVec(QueryContext *qctx, + std::vector exprs) { std::vector values; values.reserve(exprs.size()); - QueryExpressionContext ctx; for (auto *expr : exprs) { - auto value = expr->eval(ctx(nullptr)); + auto value = expr->eval(QueryExpressionContext(qctx->ectx())()); if (value.isNull() && value.getNull() != NullType::__NULL__) { LOG(ERROR) << expr->toString() << " is the wrong value type: " << value.typeName(); return Status::Error("Wrong value type: %s", expr->toString().c_str()); diff --git a/src/graph/util/SchemaUtil.h b/src/graph/util/SchemaUtil.h index a19e8882665..f9b2d22c793 100644 --- a/src/graph/util/SchemaUtil.h +++ b/src/graph/util/SchemaUtil.h @@ -48,7 +48,8 @@ class SchemaUtil final { static StatusOr toVertexID(Expression* expr, Value::Type vidType); // Iterate exprs and calculate each element's value and return them as a vector. - static StatusOr> toValueVec(std::vector exprs); + static StatusOr> toValueVec(QueryContext* qctx, + std::vector exprs); // Returns the "Field", "Type", "Null", "Default", "Comment" of the schema as a dataset static StatusOr toDescSchema(const meta::cpp2::Schema& schema); diff --git a/src/graph/validator/MutateValidator.cpp b/src/graph/validator/MutateValidator.cpp index 6c76ac85c43..2a1bb406a7a 100644 --- a/src/graph/validator/MutateValidator.cpp +++ b/src/graph/validator/MutateValidator.cpp @@ -119,7 +119,7 @@ Status InsertVerticesValidator::prepareVertices() { return Status::SemanticError("Insert wrong value: `%s'.", value->toString().c_str()); } } - auto valsRet = SchemaUtil::toValueVec(row->values()); + auto valsRet = SchemaUtil::toValueVec(qctx_, row->values()); NG_RETURN_IF_ERROR(valsRet); auto values = std::move(valsRet).value(); @@ -252,7 +252,7 @@ Status InsertEdgesValidator::prepareEdges() { } } - auto valsRet = SchemaUtil::toValueVec(row->values()); + auto valsRet = SchemaUtil::toValueVec(qctx_, row->values()); NG_RETURN_IF_ERROR(valsRet); auto props = std::move(valsRet).value(); @@ -755,9 +755,7 @@ Expression *UpdateValidator::rewriteSymExpr(Expression *expr, Expression::Kind::kVersionedVar, Expression::Kind::kVarProperty, Expression::Kind::kInputProperty, - Expression::Kind::kVar, // Expression::Kind::kLabelAttribute, valid only for update edge - Expression::Kind::kAttribute, Expression::Kind::kSubscript, Expression::Kind::kUUID, Expression::Kind::kTagProperty, @@ -774,6 +772,10 @@ Expression *UpdateValidator::rewriteSymExpr(Expression *expr, invalidExprs.emplace(Expression::Kind::kLabelAttribute); invalidExprs.emplace(Expression::Kind::kEdgeProperty); } + if (ExpressionUtils::checkVarExprIfExist(expr, qctx_)) { + hasWrongType = true; + return nullptr; + } auto *r = ExpressionUtils::findAny(expr, invalidExprs); if (r != nullptr) { hasWrongType = true; @@ -814,7 +816,7 @@ Expression *UpdateValidator::rewriteSymExpr(Expression *expr, } }; auto *newExpr = RewriteVisitor::transform(expr, matcher, rewriter); - return newExpr; + return ExpressionUtils::rewriteParameter(newExpr, qctx_); } Status UpdateVertexValidator::validateImpl() { diff --git a/src/storage/query/QueryBaseProcessor-inl.h b/src/storage/query/QueryBaseProcessor-inl.h index c459b76d1dd..23592ef9fa8 100644 --- a/src/storage/query/QueryBaseProcessor-inl.h +++ b/src/storage/query/QueryBaseProcessor-inl.h @@ -401,6 +401,10 @@ nebula::cpp2::ErrorCode QueryBaseProcessor::checkExp( } return nebula::cpp2::ErrorCode::SUCCEEDED; } + case Expression::Kind::kAttribute: { + // Skip check for attribute expression + return nebula::cpp2::ErrorCode::SUCCEEDED; + } case Expression::Kind::kPredicate: { auto* predExp = static_cast(exp); auto ret = checkExp(predExp->collection(), returned, filtered, updated, allowNoexistentProp); @@ -601,7 +605,6 @@ nebula::cpp2::ErrorCode QueryBaseProcessor::checkExp( } case Expression::Kind::kInputProperty: case Expression::Kind::kSubscript: - case Expression::Kind::kAttribute: case Expression::Kind::kLabelTagProperty: case Expression::Kind::kLabelAttribute: case Expression::Kind::kVertex: diff --git a/tests/tck/features/yield/parameter.feature b/tests/tck/features/yield/parameter.feature index cd29521a677..3a9de58e15a 100644 --- a/tests/tck/features/yield/parameter.feature +++ b/tests/tck/features/yield/parameter.feature @@ -329,3 +329,62 @@ Feature: Parameter | v | | BAD_TYPE | | BAD_TYPE | + + Scenario: [param-test-013] DML + Given an empty graph + And load "nba" csv data to a new space + When executing query: + """ + insert vertex player(name, age) values "1":($p6.c, $p1+40) + """ + Then the execution should be successful + When executing query: + """ + insert vertex player(age, name) values "1":($p6.c, $p1+40) + """ + Then a ExecutionError should be raised at runtime: Storage Error: The data type does not meet the requirements. Use the correct type of data. + When executing query: + """ + insert edge like(likeness) values "1"->"2":($p1+40) + """ + Then the execution should be successful + When executing query: + """ + insert edge like(likeness) values "1"->"2":($p6.c) + """ + Then a ExecutionError should be raised at runtime: Storage Error: The data type does not meet the requirements. Use the correct type of data. + When executing query: + """ + update vertex on player "1" set age=age+$p1 when age>$p1 + """ + Then the execution should be successful + When executing query: + """ + update vertex on player "1" set age=age+$p6.c when age>$p1 + """ + Then a ExecutionError should be raised at runtime: Storage Error: Invalid data, may be wrong value type. + When executing query: + """ + update edge on like "1"->"2" set likeness=likeness+$p1 + """ + Then the execution should be successful + When executing query: + """ + update edge on like "1"->"2" set likeness=likeness+$p6.c when likeness>300 + """ + Then the execution should be successful + When executing query: + """ + update edge on like "1"->"2" set likeness=likeness+$p6.c when likeness<300 + """ + Then a ExecutionError should be raised at runtime: Storage Error: Invalid data, may be wrong value type. + When executing query: + """ + update edge on like "1"->"2" set likeness=likeness+$p6.c when likeness>$p1 + """ + Then a ExecutionError should be raised at runtime: Storage Error: Invalid data, may be wrong value type. + When executing query: + """ + update edge on like "1"->"2" set likeness=likeness+$p6.a when likeness>$p1 + """ + Then the execution should be successful