Skip to content
Snippets Groups Projects
Unverified Commit db3a7da9 authored by nevermore's avatar nevermore Committed by GitHub
Browse files

deduce function & typecast type (#136)


* add functioncall deduce

* print err msg

* add error status

* add more test case

* modify code

* fix functioncall

* validator typecast & test case

* pre-allocated memory for vector

* add typecast deduceprop & more test case

* rewrite deduce typecast

* process null

Co-authored-by: default avatarjimingquan <mingquan.ji@vesoft.com>
Co-authored-by: default avatardutor <440396+dutor@users.noreply.github.com>
parent dfcb3655
No related branches found
No related tags found
No related merge requests found
......@@ -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: {
......
......@@ -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) {
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment