diff --git a/src/validator/Validator.cpp b/src/validator/Validator.cpp index dc3f41221fff71a7487477026d45e6175a2d3faa..e0dcc20e26c27724e0d6056af14bf2a5d704d5d0 100644 --- a/src/validator/Validator.cpp +++ b/src/validator/Validator.cpp @@ -23,6 +23,7 @@ #include "validator/SetValidator.h" #include "validator/UseValidator.h" #include "validator/YieldValidator.h" +#include "common/function/FunctionManager.h" namespace nebula { namespace graph { @@ -235,7 +236,7 @@ StatusOr<Value::Type> Validator::deduceExprType(const Expression* expr) const { {Value::Type::BOOL, Value(true)}, {Value::Type::INT, Value(1)}, {Value::Type::FLOAT, Value(1.0)}, - {Value::Type::STRING, Value("a")}, + {Value::Type::STRING, Value("123")}, {Value::Type::DATE, Value(Date())}, {Value::Type::DATETIME, Value(DateTime())}, {Value::Type::VERTEX, Value(Vertex())}, @@ -295,9 +296,7 @@ StatusOr<Value::Type> Validator::deduceExprType(const Expression* expr) const { case Expression::Kind::kUnaryPlus: { auto unaryExpr = static_cast<const UnaryExpression*>(expr); auto status = deduceExprType(unaryExpr->operand()); - if (!status.ok()) { - return status.status(); - } + NG_RETURN_IF_ERROR(status); return status.value(); } @@ -310,9 +309,7 @@ StatusOr<Value::Type> Validator::deduceExprType(const Expression* expr) const { case Expression::Kind::kUnaryIncr: { auto unaryExpr = static_cast<const UnaryExpression*>(expr); auto status = deduceExprType(unaryExpr->operand()); - if (!status.ok()) { - return status.status(); - } + NG_RETURN_IF_ERROR(status); auto detectVal = kConstantValues.at(status.value()) + 1; if (detectVal.isBadNull()) { @@ -326,9 +323,7 @@ StatusOr<Value::Type> Validator::deduceExprType(const Expression* expr) const { case Expression::Kind::kUnaryDecr: { auto unaryExpr = static_cast<const UnaryExpression*>(expr); auto status = deduceExprType(unaryExpr->operand()); - if (!status.ok()) { - return status.status(); - } + NG_RETURN_IF_ERROR(status); auto detectVal = kConstantValues.at(status.value()) - 1; if (detectVal.isBadNull()) { @@ -340,17 +335,40 @@ StatusOr<Value::Type> Validator::deduceExprType(const Expression* expr) const { return detectVal.type(); } case Expression::Kind::kFunctionCall: { - // TODO - return Status::Error("Not support function yet."); + auto funcExpr = static_cast<const FunctionCallExpression *>(expr); + std::vector<Value::Type> argsTypeList; + argsTypeList.reserve(funcExpr->args()->numArgs()); + for (auto &arg : funcExpr->args()->args()) { + auto status = deduceExprType(arg.get()); + NG_RETURN_IF_ERROR(status); + argsTypeList.push_back(status.value()); + } + auto result = + FunctionManager::getReturnType(*(funcExpr->name()), argsTypeList); + if (!result.ok()) { + return Status::Error("`%s` is not a valid expression : %s", + expr->toString().c_str(), + result.status().toString().c_str()); + } + return result.value(); } case Expression::Kind::kTypeCasting: { auto castExpr = static_cast<const TypeCastingExpression*>(expr); - auto status = deduceExprType(castExpr->operand()); - if (!status.ok()) { - return status.status(); + auto result = deduceExprType(castExpr->operand()); + NG_RETURN_IF_ERROR(result); + + auto* typeCastExpr = const_cast<TypeCastingExpression*>(castExpr); + if (!evaluableExpr(castExpr->operand())) { + auto detectVal = kConstantValues.at(result.value()); + typeCastExpr->setOperand(new ConstantExpression(detectVal)); + } + + QueryExpressionContext ctx(nullptr, nullptr); + auto val = typeCastExpr->eval(ctx); + if (val.isNull()) { + return Status::Error("`%s` is not a valid expression ", expr->toString().c_str()); } - // TODO - return Status::Error("Not support type casting yet."); + return val.type(); } case Expression::Kind::kTagProperty: case Expression::Kind::kDstProperty: @@ -548,11 +566,15 @@ Status Validator::deduceProps(const Expression* expr) { props.emplace_back(*prop); break; } + case Expression::Kind::kTypeCasting: { + auto* typeCastExpr = static_cast<const TypeCastingExpression*>(expr); + NG_RETURN_IF_ERROR(deduceProps(typeCastExpr->operand())); + break; + } case Expression::Kind::kUUID: case Expression::Kind::kVar: case Expression::Kind::kVersionedVar: case Expression::Kind::kSymProperty: - case Expression::Kind::kTypeCasting: case Expression::Kind::kUnaryIncr: case Expression::Kind::kUnaryDecr: case Expression::Kind::kRelIn: { diff --git a/src/validator/test/YieldValidatorTest.cpp b/src/validator/test/YieldValidatorTest.cpp index b820309891bf5f433d70ea4443fb0e6f1a9be7af..478cf0e918db38285dfc3b04c9587ceaf0cdeac4 100644 --- a/src/validator/test/YieldValidatorTest.cpp +++ b/src/validator/test/YieldValidatorTest.cpp @@ -39,7 +39,7 @@ TEST_F(YieldValidatorTest, Base) { #endif } -TEST_F(YieldValidatorTest, DISABLED_HashCall) { +TEST_F(YieldValidatorTest, HashCall) { { std::string query = "YIELD hash(\"Boris\")"; EXPECT_TRUE(checkResult(query, expected_)); @@ -58,7 +58,9 @@ TEST_F(YieldValidatorTest, DISABLED_HashCall) { } { std::string query = "YIELD hash(!0)"; - EXPECT_TRUE(checkResult(query, expected_)); + auto result = checkResult(query); + EXPECT_EQ(std::string(result.message()), + "`!(0)' is not a valid expression, can not apply `!' to INT."); } } @@ -91,11 +93,145 @@ TEST_F(YieldValidatorTest, Logic) { #endif } -TEST_F(YieldValidatorTest, DISABLED_InCall) { +TEST_F(YieldValidatorTest, FuncitonCall) { + { + // TODO not support udf_is_in + // std::string query = "YIELD udf_is_in(1,0,1,2), 123"; + // EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD abs(-12)"; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD abs(0)"; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD abs(true)"; + auto result = checkResult(query); + EXPECT_EQ(std::string(result.message()), + "`abs(true)` is not a valid expression : Parameter's type error"); + } + { + std::string query = "YIELD abs(\"test\")"; + auto result = checkResult(query); + EXPECT_EQ(std::string(result.message()), + "`abs(test)` is not a valid expression : Parameter's type error"); + } + { + std::string query = "YIELD noexist(12)"; + auto result = checkResult(query); + EXPECT_EQ(std::string(result.message()), + "`noexist(12)` is not a valid expression : Function `noexist' not defined"); + } +} + +TEST_F(YieldValidatorTest, TypeCastTest) { + { + std::string query = "YIELD (INT)1.23"; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD (INT).123"; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD (INT)123"; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD (INT)\" 123\""; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD (int64)-123"; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD (int32)\"-123\""; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD (int30)\"-123\""; + auto result = checkResult(query); + EXPECT_EQ(std::string(result.message()), + "SyntaxError: syntax error near `)\"-123\"'"); + } + { + std::string query = "YIELD (int)\"123abc\""; + auto result = checkResult(query); + EXPECT_EQ(std::string(result.message()), + "`(INT)123abc` is not a valid expression "); + } + { + std::string query = "YIELD (int)\"abc123\""; + auto result = checkResult(query); + EXPECT_EQ(std::string(result.message()), + "`(INT)abc123` is not a valid expression "); + } + { + std::string query = "YIELD (doublE)\"123\""; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD (doublE)\" 123\""; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD (doublE)\".a123\""; + auto result = checkResult(query); + EXPECT_EQ(std::string(result.message()), + "`(FLOAT).a123` is not a valid expression "); + } + { + std::string query = "YIELD (STRING)1.23"; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD (STRING)123"; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD (STRING)true"; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD (BOOL)123"; + EXPECT_TRUE(checkResult(query, expected_)); + } + { + std::string query = "YIELD (BOOL)0"; + EXPECT_TRUE(checkResult(query, expected_)); + } { - std::string query = "YIELD udf_is_in(1,0,1,2), 123"; + std::string query = "YIELD (BOOL)\"12\""; EXPECT_TRUE(checkResult(query, expected_)); } + { + std::string query = "YIELD (MAP)\"12\""; + auto result = checkResult(query); + EXPECT_EQ(std::string(result.message()), + "SyntaxError: syntax error near `)\"12\"'"); + } + { + std::string query = "YIELD (SET)12"; + auto result = checkResult(query); + EXPECT_EQ(std::string(result.message()), + "SyntaxError: syntax error near `SET'"); + } + { + std::string query = "YIELD (PATH)true"; + auto result = checkResult(query); + EXPECT_EQ(std::string(result.message()), + "SyntaxError: syntax error near `)true'"); + } + { + std::string query = "YIELD (NOEXIST)true"; + auto result = checkResult(query); + EXPECT_EQ(std::string(result.message()), + "SyntaxError: syntax error near `)true'"); + } } TEST_F(YieldValidatorTest, YieldPipe) {