From 467e46c3027b55d3d5e5157b44415e1de6ced461 Mon Sep 17 00:00:00 2001 From: Lovro Lugovic Date: Thu, 11 Oct 2018 13:39:36 +0200 Subject: [PATCH] Add inDegree and outDegree functions Reviewers: teon.banek, mtomic Reviewed By: mtomic Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1651 --- .../interpret/awesome_memgraph_functions.cpp | 38 +++++++++++++++++++ tests/unit/query_expression_evaluator.cpp | 30 +++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/src/query/interpret/awesome_memgraph_functions.cpp b/src/query/interpret/awesome_memgraph_functions.cpp index afdbc222f..2cd292b1d 100644 --- a/src/query/interpret/awesome_memgraph_functions.cpp +++ b/src/query/interpret/awesome_memgraph_functions.cpp @@ -182,6 +182,42 @@ TypedValue Degree(TypedValue *args, int64_t nargs, const EvaluationContext &, } } +TypedValue InDegree(TypedValue *args, int64_t nargs, const EvaluationContext &, + database::GraphDbAccessor *) { + if (nargs != 1) { + throw QueryRuntimeException("'inDegree' requires exactly one argument."); + } + + switch (args[0].type()) { + case TypedValue::Type::Null: + return TypedValue::Null; + case TypedValue::Type::Vertex: { + auto &vertex = args[0].Value(); + return static_cast(vertex.in_degree()); + } + default: + throw QueryRuntimeException("'inDegree' argument must be a node."); + } +} + +TypedValue OutDegree(TypedValue *args, int64_t nargs, const EvaluationContext &, + database::GraphDbAccessor *) { + if (nargs != 1) { + throw QueryRuntimeException("'outDegree' requires exactly one argument."); + } + + switch (args[0].type()) { + case TypedValue::Type::Null: + return TypedValue::Null; + case TypedValue::Type::Vertex: { + auto &vertex = args[0].Value(); + return static_cast(vertex.out_degree()); + } + default: + throw QueryRuntimeException("'outDegree' argument must be a node."); + } +} + TypedValue ToBoolean(TypedValue *args, int64_t nargs, const EvaluationContext &, database::GraphDbAccessor *) { if (nargs != 1) { @@ -853,6 +889,8 @@ NameToFunction(const std::string &function_name) { // Scalar functions if (function_name == "COALESCE") return Coalesce; if (function_name == "DEGREE") return Degree; + if (function_name == "INDEGREE") return InDegree; + if (function_name == "OUTDEGREE") return OutDegree; if (function_name == "ENDNODE") return EndNode; if (function_name == "HEAD") return Head; if (function_name == "ID") return Id; diff --git a/tests/unit/query_expression_evaluator.cpp b/tests/unit/query_expression_evaluator.cpp index a544f0f44..71a7e52f0 100644 --- a/tests/unit/query_expression_evaluator.cpp +++ b/tests/unit/query_expression_evaluator.cpp @@ -999,6 +999,36 @@ TEST_F(FunctionTest, Degree) { ASSERT_THROW(EvaluateFunction("DEGREE", {e12}), QueryRuntimeException); } +TEST_F(FunctionTest, InDegree) { + ASSERT_THROW(EvaluateFunction("INDEGREE", {}), QueryRuntimeException); + ASSERT_TRUE(EvaluateFunction("INDEGREE", {TypedValue::Null}).IsNull()); + auto v1 = dba->InsertVertex(); + auto v2 = dba->InsertVertex(); + auto v3 = dba->InsertVertex(); + auto e12 = dba->InsertEdge(v1, v2, dba->EdgeType("t")); + dba->InsertEdge(v3, v2, dba->EdgeType("t")); + ASSERT_EQ(EvaluateFunction("INDEGREE", {v1}).ValueInt(), 0); + ASSERT_EQ(EvaluateFunction("INDEGREE", {v2}).ValueInt(), 2); + ASSERT_EQ(EvaluateFunction("INDEGREE", {v3}).ValueInt(), 0); + ASSERT_THROW(EvaluateFunction("INDEGREE", {2}), QueryRuntimeException); + ASSERT_THROW(EvaluateFunction("INDEGREE", {e12}), QueryRuntimeException); +} + +TEST_F(FunctionTest, OutDegree) { + ASSERT_THROW(EvaluateFunction("OUTDEGREE", {}), QueryRuntimeException); + ASSERT_TRUE(EvaluateFunction("OUTDEGREE", {TypedValue::Null}).IsNull()); + auto v1 = dba->InsertVertex(); + auto v2 = dba->InsertVertex(); + auto v3 = dba->InsertVertex(); + auto e12 = dba->InsertEdge(v1, v2, dba->EdgeType("t")); + dba->InsertEdge(v3, v2, dba->EdgeType("t")); + ASSERT_EQ(EvaluateFunction("OUTDEGREE", {v1}).ValueInt(), 1); + ASSERT_EQ(EvaluateFunction("OUTDEGREE", {v2}).ValueInt(), 0); + ASSERT_EQ(EvaluateFunction("OUTDEGREE", {v3}).ValueInt(), 1); + ASSERT_THROW(EvaluateFunction("OUTDEGREE", {2}), QueryRuntimeException); + ASSERT_THROW(EvaluateFunction("OUTDEGREE", {e12}), QueryRuntimeException); +} + TEST_F(FunctionTest, ToBoolean) { ASSERT_THROW(EvaluateFunction("TOBOOLEAN", {}), QueryRuntimeException); ASSERT_TRUE(EvaluateFunction("TOBOOLEAN", {TypedValue::Null}).IsNull());