Implement valueType
openCypher function
Reviewers: buda Reviewed By: buda Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D2818
This commit is contained in:
parent
fb7025a716
commit
04ceb8d4b1
@ -74,6 +74,7 @@ struct Integer {};
|
||||
struct PositiveInteger {};
|
||||
struct NonZeroInteger {};
|
||||
struct NonNegativeInteger {};
|
||||
struct Double {};
|
||||
struct Number {};
|
||||
struct List {};
|
||||
struct String {};
|
||||
@ -96,6 +97,8 @@ bool ArgIsType(const TypedValue &arg) {
|
||||
return arg.IsInt() && arg.ValueInt() != 0;
|
||||
} else if constexpr (std::is_same_v<ArgType, NonNegativeInteger>) {
|
||||
return arg.IsInt() && arg.ValueInt() >= 0;
|
||||
} else if constexpr (std::is_same_v<ArgType, Double>) {
|
||||
return arg.IsDouble();
|
||||
} else if constexpr (std::is_same_v<ArgType, Number>) {
|
||||
return arg.IsNumeric();
|
||||
} else if constexpr (std::is_same_v<ArgType, List>) {
|
||||
@ -120,6 +123,8 @@ bool ArgIsType(const TypedValue &arg) {
|
||||
|
||||
template <class ArgType>
|
||||
constexpr const char *ArgTypeName() {
|
||||
// The type names returned should be standardized openCypher type names.
|
||||
// https://github.com/opencypher/openCypher/blob/master/docs/openCypher9.pdf
|
||||
if constexpr (std::is_same_v<ArgType, Null>) {
|
||||
return "null";
|
||||
} else if constexpr (std::is_same_v<ArgType, Bool>) {
|
||||
@ -132,6 +137,8 @@ constexpr const char *ArgTypeName() {
|
||||
return "non-zero integer";
|
||||
} else if constexpr (std::is_same_v<ArgType, NonNegativeInteger>) {
|
||||
return "non-negative integer";
|
||||
} else if constexpr (std::is_same_v<ArgType, Double>) {
|
||||
return "float";
|
||||
} else if constexpr (std::is_same_v<ArgType, Number>) {
|
||||
return "number";
|
||||
} else if constexpr (std::is_same_v<ArgType, List>) {
|
||||
@ -143,7 +150,7 @@ constexpr const char *ArgTypeName() {
|
||||
} else if constexpr (std::is_same_v<ArgType, Vertex>) {
|
||||
return "node";
|
||||
} else if constexpr (std::is_same_v<ArgType, Edge>) {
|
||||
return "edge";
|
||||
return "relationship";
|
||||
} else if constexpr (std::is_same_v<ArgType, Path>) {
|
||||
return "path";
|
||||
} else if constexpr (std::is_same_v<ArgType, void>) {
|
||||
@ -548,6 +555,36 @@ TypedValue Type(const TypedValue *args, int64_t nargs,
|
||||
ctx.memory);
|
||||
}
|
||||
|
||||
TypedValue ValueType(const TypedValue *args, int64_t nargs,
|
||||
const FunctionContext &ctx) {
|
||||
FType<Or<Null, Bool, Integer, Double, String, List, Map, Vertex, Edge, Path>>(
|
||||
"type", args, nargs);
|
||||
// The type names returned should be standardized openCypher type names.
|
||||
// https://github.com/opencypher/openCypher/blob/master/docs/openCypher9.pdf
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
return TypedValue("NULL", ctx.memory);
|
||||
case TypedValue::Type::Bool:
|
||||
return TypedValue("BOOLEAN", ctx.memory);
|
||||
case TypedValue::Type::Int:
|
||||
return TypedValue("INTEGER", ctx.memory);
|
||||
case TypedValue::Type::Double:
|
||||
return TypedValue("FLOAT", ctx.memory);
|
||||
case TypedValue::Type::String:
|
||||
return TypedValue("STRING", ctx.memory);
|
||||
case TypedValue::Type::List:
|
||||
return TypedValue("LIST", ctx.memory);
|
||||
case TypedValue::Type::Map:
|
||||
return TypedValue("MAP", ctx.memory);
|
||||
case TypedValue::Type::Vertex:
|
||||
return TypedValue("NODE", ctx.memory);
|
||||
case TypedValue::Type::Edge:
|
||||
return TypedValue("RELATIONSHIP", ctx.memory);
|
||||
case TypedValue::Type::Path:
|
||||
return TypedValue("PATH", ctx.memory);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: How is Keys different from Properties function?
|
||||
TypedValue Keys(const TypedValue *args, int64_t nargs,
|
||||
const FunctionContext &ctx) {
|
||||
@ -1088,6 +1125,7 @@ NameToFunction(const std::string &function_name) {
|
||||
if (function_name == "TOFLOAT") return ToFloat;
|
||||
if (function_name == "TOINTEGER") return ToInteger;
|
||||
if (function_name == "TYPE") return Type;
|
||||
if (function_name == "VALUETYPE") return ValueType;
|
||||
|
||||
// List functions
|
||||
if (function_name == "KEYS") return Keys;
|
||||
|
@ -1418,6 +1418,38 @@ TEST_F(FunctionTest, Type) {
|
||||
ASSERT_THROW(EvaluateFunction("TYPE", 2), QueryRuntimeException);
|
||||
}
|
||||
|
||||
TEST_F(FunctionTest, ValueType) {
|
||||
ASSERT_THROW(EvaluateFunction("VALUETYPE"), QueryRuntimeException);
|
||||
ASSERT_THROW(EvaluateFunction("VALUETYPE", TypedValue(), TypedValue()),
|
||||
QueryRuntimeException);
|
||||
ASSERT_EQ(EvaluateFunction("VALUETYPE", TypedValue()).ValueString(), "NULL");
|
||||
ASSERT_EQ(EvaluateFunction("VALUETYPE", TypedValue(true)).ValueString(),
|
||||
"BOOLEAN");
|
||||
ASSERT_EQ(EvaluateFunction("VALUETYPE", TypedValue(1)).ValueString(),
|
||||
"INTEGER");
|
||||
ASSERT_EQ(EvaluateFunction("VALUETYPE", TypedValue(1.1)).ValueString(),
|
||||
"FLOAT");
|
||||
ASSERT_EQ(EvaluateFunction("VALUETYPE", TypedValue("test")).ValueString(),
|
||||
"STRING");
|
||||
ASSERT_EQ(EvaluateFunction("VALUETYPE", TypedValue(std::vector<TypedValue>{
|
||||
TypedValue(1), TypedValue(2)}))
|
||||
.ValueString(),
|
||||
"LIST");
|
||||
ASSERT_EQ(EvaluateFunction("VALUETYPE",
|
||||
TypedValue(std::map<std::string, TypedValue>{
|
||||
{"test", TypedValue(1)}}))
|
||||
.ValueString(),
|
||||
"MAP");
|
||||
auto v1 = dba.InsertVertex();
|
||||
auto v2 = dba.InsertVertex();
|
||||
ASSERT_EQ(EvaluateFunction("VALUETYPE", v1).ValueString(), "NODE");
|
||||
auto e = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("type1"));
|
||||
ASSERT_TRUE(e.HasValue());
|
||||
ASSERT_EQ(EvaluateFunction("VALUETYPE", *e).ValueString(), "RELATIONSHIP");
|
||||
Path p(v1, *e, v2);
|
||||
ASSERT_EQ(EvaluateFunction("VALUETYPE", p).ValueString(), "PATH");
|
||||
}
|
||||
|
||||
TEST_F(FunctionTest, Labels) {
|
||||
ASSERT_THROW(EvaluateFunction("LABELS"), QueryRuntimeException);
|
||||
ASSERT_TRUE(EvaluateFunction("LABELS", TypedValue()).IsNull());
|
||||
|
Loading…
Reference in New Issue
Block a user