From 669570e45fa1ce5d036c41dff8cbc50484dc3ac2 Mon Sep 17 00:00:00 2001 From: xiyang Date: Thu, 13 Feb 2025 12:32:09 +0800 Subject: [PATCH] Remove recursive extend binding --- src/function/gds/all_shortest_paths.cpp | 8 +- src/function/gds/rec_joins.cpp | 70 +--- src/function/gds/single_shortest_paths.cpp | 8 +- src/function/gds/variable_length_path.cpp | 26 -- src/function/gds/weighted_shortest_paths.cpp | 4 +- src/include/function/gds/rec_joins.h | 19 +- test/test_files/function/gds/basic.test | 35 +- .../function/gds/rec_joins_large.test | 119 +++--- .../function/gds/rec_joins_small.test | 379 ++++++++---------- 9 files changed, 237 insertions(+), 431 deletions(-) diff --git a/src/function/gds/all_shortest_paths.cpp b/src/function/gds/all_shortest_paths.cpp index c88e679f142..b7674f94218 100644 --- a/src/function/gds/all_shortest_paths.cpp +++ b/src/function/gds/all_shortest_paths.cpp @@ -216,10 +216,10 @@ class AllSPPathsEdgeCompute : public SPEdgeCompute { * is returned for each destination. If paths are not returned, multiplicities indicate the * number of paths to each destination. */ -class AllSPDestinationsAlgorithm final : public SPAlgorithm { +class AllSPDestinationsAlgorithm final : public RJAlgorithm { public: AllSPDestinationsAlgorithm() = default; - AllSPDestinationsAlgorithm(const AllSPDestinationsAlgorithm& other) : SPAlgorithm{other} {} + AllSPDestinationsAlgorithm(const AllSPDestinationsAlgorithm& other) : RJAlgorithm{other} {} expression_vector getResultColumns(const function::GDSBindInput& /*bindInput*/) const override { auto columns = getBaseResultColumns(); @@ -250,10 +250,10 @@ class AllSPDestinationsAlgorithm final : public SPAlgorithm { } }; -class AllSPPathsAlgorithm final : public SPAlgorithm { +class AllSPPathsAlgorithm final : public RJAlgorithm { public: AllSPPathsAlgorithm() = default; - AllSPPathsAlgorithm(const AllSPPathsAlgorithm& other) : SPAlgorithm{other} {} + AllSPPathsAlgorithm(const AllSPPathsAlgorithm& other) : RJAlgorithm{other} {} expression_vector getResultColumns(const function::GDSBindInput& /*bindInput*/) const override { auto columns = getBaseResultColumns(); diff --git a/src/function/gds/rec_joins.cpp b/src/function/gds/rec_joins.cpp index fe55c366cea..debdd4f7591 100644 --- a/src/function/gds/rec_joins.cpp +++ b/src/function/gds/rec_joins.cpp @@ -1,11 +1,9 @@ #include "function/gds/rec_joins.h" #include "binder/binder.h" -#include "binder/expression/expression_util.h" #include "binder/expression/property_expression.h" -#include "common/enums/extend_direction_util.h" +#include "common/exception/binder.h" #include "common/exception/interrupt.h" -#include "common/exception/runtime.h" #include "common/task_system/progress_bar.h" #include "function/gds/gds.h" #include "function/gds/gds_utils.h" @@ -47,29 +45,13 @@ PathsOutputWriterInfo RJBindData::getPathWriterInfo() const { return info; } -void RJAlgorithm::setToNoPath() { - bindData->ptrCast()->writePath = false; +void RJAlgorithm::bind(const kuzu::function::GDSBindInput&, main::ClientContext&) { + throw common::BinderException("Recursive join should not be triggered through function calls. " + "Try cypher patter ()-[*]->() instead."); } -void RJAlgorithm::validateLowerUpperBound(int64_t lowerBound, int64_t upperBound) { - if (lowerBound < 0 || upperBound < 0) { - throw RuntimeException( - stringFormat("Lower and upper bound lengths of recursive join operations need to be " - "non-negative. Given lower bound is: {} and upper bound is: {}.", - lowerBound, upperBound)); - } - if (lowerBound > upperBound) { - throw RuntimeException( - stringFormat("Lower bound length of recursive join operations need to be less than or " - "equal to upper bound. Given lower bound is: {} and upper bound is: {}.", - lowerBound, upperBound)); - } - if (upperBound >= RJBindData::DEFAULT_MAXIMUM_ALLOWED_UPPER_BOUND) { - throw RuntimeException( - stringFormat("Recursive join operations only works for non-positive upper bound " - "iterations that are up to {}. Given upper bound is: {}.", - RJBindData::DEFAULT_MAXIMUM_ALLOWED_UPPER_BOUND, upperBound)); - } +void RJAlgorithm::setToNoPath() { + bindData->ptrCast()->writePath = false; } binder::expression_vector RJAlgorithm::getResultColumnsNoPath() { @@ -95,46 +77,6 @@ expression_vector RJAlgorithm::getBaseResultColumns() const { return columns; } -void RJAlgorithm::bindColumnExpressions(binder::Binder* binder) const { - auto rjBindData = bindData->ptrCast(); - if (rjBindData->extendDirection == common::ExtendDirection::BOTH) { - rjBindData->directionExpr = - binder->createVariable(DIRECTION_COLUMN_NAME, LogicalType::LIST(LogicalType::BOOL())); - } - rjBindData->lengthExpr = binder->createVariable(LENGTH_COLUMN_NAME, LogicalType::UINT16()); - rjBindData->pathNodeIDsExpr = binder->createVariable(PATH_NODE_IDS_COLUMN_NAME, - LogicalType::LIST(LogicalType::INTERNAL_ID())); - rjBindData->pathEdgeIDsExpr = binder->createVariable(PATH_EDGE_IDS_COLUMN_NAME, - LogicalType::LIST(LogicalType::INTERNAL_ID())); -} - -static void validateSPUpperBound(int64_t upperBound) { - if (upperBound == 0) { - throw RuntimeException(stringFormat("Shortest path operations only works for positive " - "upper bound iterations. Given upper bound is: {}.", - upperBound)); - } -} - -void SPAlgorithm::bind(const GDSBindInput& input, main::ClientContext& context) { - KU_ASSERT(input.getNumParams() == 4); - auto graphName = ExpressionUtil::getLiteralValue(*input.getParam(0)); - auto graphEntry = bindGraphEntry(context, graphName); - auto nodeOutput = bindNodeOutput(input, graphEntry.nodeEntries); - auto rjBindData = std::make_unique(std::move(graphEntry), nodeOutput); - rjBindData->nodeInput = input.getParam(1); - rjBindData->lowerBound = 1; - auto upperBound = ExpressionUtil::getLiteralValue(*input.getParam(2)); - validateSPUpperBound(upperBound); - validateLowerUpperBound(rjBindData->lowerBound, upperBound); - rjBindData->upperBound = upperBound; - rjBindData->semantic = PathSemantic::WALK; - rjBindData->extendDirection = ExtendDirectionUtil::fromString( - ExpressionUtil::getLiteralValue(*input.getParam(3))); - bindData = std::move(rjBindData); - bindColumnExpressions(input.binder); -} - // All recursive join computation have the same vertex compute. This vertex compute writes // result (could be dst, length or path) from a dst node ID to given source node ID. class RJVertexCompute : public VertexCompute { diff --git a/src/function/gds/single_shortest_paths.cpp b/src/function/gds/single_shortest_paths.cpp index 5c6a01fc827..17cca5327ea 100644 --- a/src/function/gds/single_shortest_paths.cpp +++ b/src/function/gds/single_shortest_paths.cpp @@ -118,11 +118,11 @@ class SingleSPPathsEdgeCompute : public SPEdgeCompute { * multiplicities of each destination is ignored (e.g., if there are 3 paths to a destination d, * d is returned only once). */ -class SingleSPDestinationsAlgorithm : public SPAlgorithm { +class SingleSPDestinationsAlgorithm : public RJAlgorithm { public: SingleSPDestinationsAlgorithm() = default; SingleSPDestinationsAlgorithm(const SingleSPDestinationsAlgorithm& other) - : SPAlgorithm{other} {} + : RJAlgorithm{other} {} expression_vector getResultColumns(const function::GDSBindInput& /*bindInput*/) const override { auto columns = getBaseResultColumns(); @@ -149,10 +149,10 @@ class SingleSPDestinationsAlgorithm : public SPAlgorithm { } }; -class SingleSPPathsAlgorithm : public SPAlgorithm { +class SingleSPPathsAlgorithm : public RJAlgorithm { public: SingleSPPathsAlgorithm() = default; - SingleSPPathsAlgorithm(const SingleSPPathsAlgorithm& other) : SPAlgorithm{other} {} + SingleSPPathsAlgorithm(const SingleSPPathsAlgorithm& other) : RJAlgorithm{other} {} expression_vector getResultColumns(const function::GDSBindInput& /*bindInput*/) const override { auto columns = getBaseResultColumns(); diff --git a/src/function/gds/variable_length_path.cpp b/src/function/gds/variable_length_path.cpp index d2edfae65ef..973d47d0d5d 100644 --- a/src/function/gds/variable_length_path.cpp +++ b/src/function/gds/variable_length_path.cpp @@ -1,7 +1,5 @@ #include -#include "binder/expression/expression_util.h" -#include "common/enums/extend_direction_util.h" #include "common/types/types.h" #include "function/gds/auxiliary_state/path_auxiliary_state.h" #include "function/gds/gds_function_collection.h" @@ -84,30 +82,6 @@ class VarLenJoinsAlgorithm final : public RJAlgorithm { VarLenJoinsAlgorithm() = default; VarLenJoinsAlgorithm(const VarLenJoinsAlgorithm& other) : RJAlgorithm(other) {} - // Inputs are: graph, srcNode, lowerBound, upperBound, direction - std::vector getParameterTypeIDs() const override { - return {LogicalTypeID::ANY, LogicalTypeID::NODE, LogicalTypeID::INT64, LogicalTypeID::INT64, - LogicalTypeID::STRING}; - } - - void bind(const GDSBindInput& input, main::ClientContext& context) override { - auto graphName = ExpressionUtil::getLiteralValue(*input.getParam(0)); - auto graphEntry = bindGraphEntry(context, graphName); - auto nodeOutput = bindNodeOutput(input, graphEntry.nodeEntries); - auto rjBindData = std::make_unique(std::move(graphEntry), nodeOutput); - rjBindData->nodeInput = input.getParam(1); - auto lowerBound = ExpressionUtil::getLiteralValue(*input.getParam(2)); - auto upperBound = ExpressionUtil::getLiteralValue(*input.getParam(3)); - validateLowerUpperBound(lowerBound, upperBound); - rjBindData->lowerBound = lowerBound; - rjBindData->upperBound = upperBound; - rjBindData->semantic = PathSemantic::WALK; - rjBindData->extendDirection = ExtendDirectionUtil::fromString( - ExpressionUtil::getLiteralValue(*input.getParam(4))); - bindData = std::move(rjBindData); - bindColumnExpressions(input.binder); - } - binder::expression_vector getResultColumns( const function::GDSBindInput& /*bindInput*/) const override { auto columns = getBaseResultColumns(); diff --git a/src/function/gds/weighted_shortest_paths.cpp b/src/function/gds/weighted_shortest_paths.cpp index eaf0494fd61..c5130079347 100644 --- a/src/function/gds/weighted_shortest_paths.cpp +++ b/src/function/gds/weighted_shortest_paths.cpp @@ -127,11 +127,11 @@ class DestinationsOutputWriter : public RJOutputWriter { std::unique_ptr costVector; }; -class WeightedSPDestinationsAlgorithm : public SPAlgorithm { +class WeightedSPDestinationsAlgorithm : public RJAlgorithm { public: WeightedSPDestinationsAlgorithm() = default; WeightedSPDestinationsAlgorithm(const WeightedSPDestinationsAlgorithm& other) - : SPAlgorithm{other} {} + : RJAlgorithm{other} {} binder::expression_vector getResultColumns( const function::GDSBindInput& /*bindInput*/) const override { diff --git a/src/include/function/gds/rec_joins.h b/src/include/function/gds/rec_joins.h index 45b42df8a2d..828d993b43e 100644 --- a/src/include/function/gds/rec_joins.h +++ b/src/include/function/gds/rec_joins.h @@ -67,6 +67,8 @@ class RJAlgorithm : public GDSAlgorithm { RJAlgorithm() = default; RJAlgorithm(const RJAlgorithm& other) : GDSAlgorithm{other} {} + void bind(const kuzu::function::GDSBindInput& input, main::ClientContext& context) override; + void exec(processor::ExecutionContext* context) override; virtual RJCompState getRJCompState(processor::ExecutionContext* context, @@ -77,27 +79,10 @@ class RJAlgorithm : public GDSAlgorithm { binder::expression_vector getResultColumnsNoPath(); protected: - void validateLowerUpperBound(int64_t lowerBound, int64_t upperBound); - binder::expression_vector getBaseResultColumns() const; - void bindColumnExpressions(binder::Binder* binder) const; std::unique_ptr getBFSGraph(processor::ExecutionContext* context); }; -class SPAlgorithm : public RJAlgorithm { -public: - SPAlgorithm() = default; - SPAlgorithm(const SPAlgorithm& other) : RJAlgorithm{other} {} - - // Inputs are graph, srcNode, upperBound, direction - std::vector getParameterTypeIDs() const override { - return {common::LogicalTypeID::ANY, common::LogicalTypeID::NODE, - common::LogicalTypeID::INT64, common::LogicalTypeID::STRING}; - } - - void bind(const GDSBindInput& input, main::ClientContext&) override; -}; - } // namespace function } // namespace kuzu diff --git a/test/test_files/function/gds/basic.test b/test/test_files/function/gds/basic.test index d2807febf6a..e571357ec75 100644 --- a/test/test_files/function/gds/basic.test +++ b/test/test_files/function/gds/basic.test @@ -13,9 +13,7 @@ Runtime exception: Project graph PK already exists. Binder exception: Expect catalog entry type NODE_TABLE_ENTRY but got REL_TABLE_ENTRY. -STATEMENT CALL create_project_graph('PKWO', ['person', 'organisation'], ['knows', 'workAt']) ---- ok --STATEMENT MATCH (a:person) WHERE a.ID < 6 - CALL VAR_LEN_JOINS('PK', a, 1, 2, "FWD") - RETURN a.fName, COUNT(*); +-STATEMENT MATCH (a:person)-[:knows*1..2]->(b:person) WHERE a.ID < 6 RETURN a.fName, COUNT(*); ---- 4 Alice|12 Bob|12 @@ -28,42 +26,27 @@ Runtime exception: Project graph dummy does not exists. ---- ok -STATEMENT CALL create_project_graph('PK', ['person'], ['knows']) ---- ok --STATEMENT MATCH (a:person) WHERE a.ID < 6 - CALL VAR_LEN_JOINS('PK', a, 1, 2, "BWD") - RETURN a.fName, COUNT(*); +-STATEMENT CALL VAR_LEN_JOINS() RETURN * +---- error +Binder exception: Recursive join should not be triggered through function calls. Try cypher patter ()-[*]->() instead. +-STATEMENT MATCH (a:person)<-[:knows*1..2]-(b:person) WHERE a.ID < 6 RETURN a.fName, COUNT(*); ---- 4 Alice|12 Bob|12 Carol|12 Dan|12 --STATEMENT MATCH (a:person) WHERE a.ID < 6 - CALL VAR_LEN_JOINS('PK', a, 1, 2, "BOTH") - RETURN a.fName, COUNT(*); +-STATEMENT MATCH (a:person)-[:knows*1..2]-(b:person) WHERE a.ID < 6 RETURN a.fName, COUNT(*); ---- 4 Alice|42 Bob|42 Carol|42 Dan|42 --STATEMENT MATCH (a:person) WHERE a.ID = 0 - CALL SINGLE_SP_DESTINATIONS('PK', a, 2, "FWD") - RETURN a.fName, node.name, length; ----- error -Binder exception: Cannot find property name for node. --STATEMENT MATCH (a:person) WHERE a.ID = 0 - CALL SINGLE_SP_DESTINATIONS('PK', a, 2, "X") - RETURN a.fName, node.name, length; ----- error -Runtime exception: Cannot parse X as ExtendDirection. --STATEMENT MATCH (a:person) WHERE a.ID = 0 - CALL SINGLE_SP_DESTINATIONS('PK', a, 2, "FWD") - RETURN a.fName, node.fName, length; +-STATEMENT MATCH (a:person)-[e:knows* SHORTEST 1..2]->(b:person) WHERE a.ID = 0 RETURN a.fName, b.fName, length(e); ---- 3 Alice|Bob|1 Alice|Carol|1 Alice|Dan|1 --STATEMENT MATCH (a:person) WHERE a.ID = 0 - CALL SINGLE_SP_DESTINATIONS('PKWO', a, 2, "FWD") - RETURN a.fName, node.fName, node.name, length; +-STATEMENT MATCH (a:person)-[e:knows|:workAt* SHORTEST 1..2]->(b:person:organisation) WHERE a.ID = 0 RETURN a.fName, b.fName, b.name, length(e); ---- 5 Alice|Bob||1 Alice|Carol||1 @@ -144,4 +127,4 @@ Hubert Blaine Wolfeschlegelsteinhausenbergerdorff|0 [Alice,Dan,Alice]|[2021-06-30,2021-06-30]|[0:0,0:3]|[0:3,0:0]|Alice|Alice [Alice,Dan,Bob]|[2021-06-30,1950-05-14]|[0:0,0:3]|[0:3,0:1]|Alice|Bob [Alice,Dan,Carol]|[2021-06-30,2000-01-01]|[0:0,0:3]|[0:3,0:2]|Alice|Carol -[Alice,Dan]|[2021-06-30]|[0:0]|[0:3]|Alice|Dan \ No newline at end of file +[Alice,Dan]|[2021-06-30]|[0:0]|[0:3]|Alice|Dan diff --git a/test/test_files/function/gds/rec_joins_large.test b/test/test_files/function/gds/rec_joins_large.test index 4992195cf91..9352a4a50c1 100644 --- a/test/test_files/function/gds/rec_joins_large.test +++ b/test/test_files/function/gds/rec_joins_large.test @@ -21,9 +21,8 @@ ---- ok # Layer by layer: p1_1 (len 1): 10, p1_2 (len 2):100, p1_3 (len 3): 1000, p1_4 (len 3): 100*20=2000, p1_4 (len 4): 1000*10=10000 -LOG VarLenJoins --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL var_len_joins('PK1', a, 1, 30, "FWD") - RETURN length, count(*); +-STATEMENT MATCH (a:person1)-[e:knows11 * 1..30]->(b:person1) WHERE a.ID=0 + RETURN length(e), COUNT(*); ---- 4 1|10 2|100 @@ -32,9 +31,8 @@ # Layer by layer: p2_1 (len 1): 10, p1_2 (len 2):100, p2_3 (len 3): 1000, p2_4 (len 3): 100*20=2000, p1_4 (len 4): 1000 (from p2_3)*10=10000 -LOG VarLenJoinsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL var_len_joins('PK2', a, 1, 30, "FWD") - RETURN length, count(*); +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * 1..30]->(b) WHERE a.ID=0 + RETURN length(e), COUNT(*); ---- 4 1|10 2|100 @@ -43,18 +41,16 @@ # Layer by layer distinct counts: p2_1: 10, p1_2: 10, p2_3: 10, p2_4: 10, p1:4: 10 -LOG VarLenJoinsMultilabel1CountDistinct --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL var_len_joins('PK2', a, 1, 30, "FWD") - RETURN count(distinct node); +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * 1..30]->(b) WHERE a.ID=0 + RETURN count(distinct b); ---- 1 50 # Layer by layer: p{i}_1 (len 1):10 (total 20), p{i}_2 (len 2) =20*10=200 (total 400), p{i}_3 (len 3): 400*10=4000 (total 8000) # p{i}_4 (len 3): 400*20=8000 (total 16000), p{i}_4 (len 4): 8000*10=80000 (total 160000). Note total len 3 = 16000+8000=24000 -LOG VarLenJoinsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL var_len_joins('PK3', a, 1, 30, "FWD") - RETURN length, count(*) +-STATEMENT MATCH (a:person1)-[e* 1..30]->(b) WHERE a.ID=0 + RETURN length(e), count(*) ---- 4 1|20 2|400 @@ -62,39 +58,34 @@ 4|160000 -LOG VarLenJoinsLowerBound1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL var_len_joins('PK1', a, 2, 3, "FWD") - RETURN length, count(*); +-STATEMENT MATCH (a:person1)-[e:knows11 * 2..3]->(b) WHERE a.ID=0 + RETURN length(e), count(*); ---- 2 2|100 3|3000 -LOG VarLenJoinsLowerBound2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL var_len_joins('PK1', a, 4, 30, "FWD") - RETURN length, count(*); +-STATEMENT MATCH (a:person1)-[e:knows11 * 4..30]->(b) WHERE a.ID=0 + RETURN length(e), count(*); ---- 1 4|10000 -LOG VarLenJoinsEmptyPaths --STATEMENT MATCH (a:person1) WHERE a.ID = 4 - CALL var_len_joins('PK1', a, 1, 4, "FWD") - RETURN length, count(*); +-STATEMENT MATCH (a:person1)-[e:knows11 * 1..4]->(b) WHERE a.ID=4 + RETURN length(e), count(*); ---- 0 # Layer by layer: p1_1 (len 1): 10, p1_2 (len 2): 100, p1_3 (len 3): 100*10=1000, p1:4 (len 3): 100*20=2000 -LOG AllSPDestinations --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL all_sp_destinations('PK1', a, 30, "FWD") +-STATEMENT MATCH (a:person1)-[e:knows11 * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 RETURN count(*) ---- 1 3110 # Layer by layer: p1_1 (len 1): 10, p2_2 (len 2): 100, p1_3 (len 3): 1000, p1_4 (len 3): 100*20=2000, p1_4 (len 4): 1000*10=10000 -LOG AllSPDestinationsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL all_sp_destinations('PK2', a, 30, "FWD") +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 RETURN count(*) ---- 1 13110 @@ -102,17 +93,15 @@ # Layer by layer: p{i}_1 (len 1): 10 (total 20), p{i}_2 (len 2): 100+100=200 (total 400), p{i}_3 (len 3): 2000+2000=4000 (total 8000) # p{i}_4 (len 3): 200*20 + 200*20=8000 (total 16000) -LOG AllSPDestinationsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL all_sp_destinations('PK3', a, 30, "FWD") +-STATEMENT MATCH (a:person1)-[e * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 RETURN count(*) ---- 1 24420 # See AllSPDestinations -LOG AllSPLengths --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL ALL_SP_DESTINATIONS('PK1', a, 30, "FWD") - RETURN length, count(*); +-STATEMENT MATCH (a:person1)-[e:knows11 * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN length(e), count(*); ---- 3 1|10 2|100 @@ -120,9 +109,8 @@ # See AllSPDestinationsMultilabel1 -LOG AllSPLengthsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL ALL_SP_DESTINATIONS('PK2', a, 30, "FWD") - RETURN length, count(*); +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN length(e), count(*); ---- 4 1|10 2|100 @@ -131,9 +119,8 @@ # See AllSPDestinationsMultilabel2 -LOG AllSPLengthsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL ALL_SP_DESTINATIONS('PK3', a, 30, "FWD") - RETURN length, count(*); +-STATEMENT MATCH (a:person1)-[e * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN length(e), count(*); ---- 3 1|20 2|400 @@ -141,9 +128,8 @@ # See AllSPDestinations. Note pathNodeIDs contains 1 fewer nodes than the lengths of the paths. -LOG AllSPPaths --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL all_sp_paths('PK1', a, 5, "FWD") - RETURN size(pathNodeIDs), count(*); +-STATEMENT MATCH (a:person1)-[e:knows11 * ALL SHORTEST 1..5]->(b) WHERE a.ID=0 + RETURN size(nodes(e)), count(*); ---- 3 0|10 1|100 @@ -151,9 +137,8 @@ # See AllSPDestinationsMultilabel2. Note pathNodeIDs contains 1 fewer nodes than the lengths of the paths. -LOG AllSPPathsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL all_sp_paths('PK2', a, 30, "FWD") - RETURN size(pathNodeIDs), count(*); +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN size(nodes(e)), count(*); ---- 4 0|10 1|100 @@ -162,9 +147,8 @@ # See AllSPDestinationsMultilabel2. Note pathNodeIDs contains 1 fewer nodes than the lengths of the paths. -LOG AllSPPathsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL all_sp_paths('PK3', a, 30, "FWD") - RETURN size(pathNodeIDs), count(*); +-STATEMENT MATCH (a:person1)-[e * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN size(nodes(e)), count(*); ---- 3 0|20 1|400 @@ -173,33 +157,29 @@ # Layer by layer: p1_1 (len 1): 10, p1_2 (len 2): 10, p1_3 (len 3): 10, p1:4 (len 3): 10 -LOG SingleSPDestinations --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL single_sp_destinations('PK1', a, 30, "FWD") - RETURN count(*); +-STATEMENT MATCH (a:person1)-[e:knows11 * SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN count(*) ---- 1 40 # Layer by layer: p1_1 (len 1): 10, p2_2 (len 2): 10, p1_3 (len 3): 10, p1_4 (len 3): 10, p1_4 (len 4): 10 -LOG SingleSPDestinationsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL single_sp_destinations('PK2', a, 30, "FWD") - RETURN count(*); +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN count(*) ---- 1 50 # Layer by layer: p{i}_{j} (len j except when j=4 len is 3): 10 -LOG SingleSPDestinationsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL single_sp_destinations('PK3', a, 30, "FWD") - RETURN count(*); +-STATEMENT MATCH (a:person1)-[e * SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN count(*) ---- 1 80 # See SingleSPDestinations -LOG SingleSPLengths --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL SINGLE_SP_DESTINATIONS('PK1', a, 30, "FWD") - RETURN length, count(*); +-STATEMENT MATCH (a:person1)-[e:knows11 * SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN length(e), count(*); ---- 3 1|10 2|10 @@ -207,9 +187,8 @@ # See SingleSPDestinationsMultilabel1 -LOG SingleSPLengthsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL SINGLE_SP_DESTINATIONS('PK2', a, 30, "FWD") - RETURN length, count(*); +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN length(e), count(*); ---- 4 1|10 2|10 @@ -218,9 +197,8 @@ # See SingleSPDestinationsMultilabel2 -LOG SingleSPLengthsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL SINGLE_SP_DESTINATIONS('PK3', a, 30, "FWD") - RETURN length, count(*); +-STATEMENT MATCH (a:person1)-[e * SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN length(e), count(*); ---- 3 1|20 2|20 @@ -228,9 +206,8 @@ # See SingleSPDestinations. Note pathNodeIDs contains 1 fewer nodes than the lengths of the paths. -LOG SingleSPPaths --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL single_sp_paths('PK1', a, 5, "FWD") - RETURN size(pathNodeIDs), count(*); +-STATEMENT MATCH (a:person1)-[e:knows11 * SHORTEST 1..5]->(b) WHERE a.ID=0 + RETURN size(nodes(e)), count(*); ---- 3 0|10 1|10 @@ -238,9 +215,8 @@ # See SingleSPDestinationsMultilabel1. Note pathNodeIDs contains 1 fewer nodes than the lengths of the paths. -LOG SingleSPPathsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL single_sp_paths('PK2', a, 30, "FWD") - RETURN size(pathNodeIDs), count(*); +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN size(nodes(e)), count(*); ---- 4 0|10 1|10 @@ -249,9 +225,8 @@ # See SingleSPDestinationsMultilabel2. Note pathNodeIDs contains 1 fewer nodes than the lengths of the paths. -LOG SingleSPPathsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL single_sp_paths('PK3', a, 30, "FWD") - RETURN size(pathNodeIDs), count(*) +-STATEMENT MATCH (a:person1)-[e * SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN size(nodes(e)), count(*); ---- 3 0|20 1|20 diff --git a/test/test_files/function/gds/rec_joins_small.test b/test/test_files/function/gds/rec_joins_small.test index 4719657f077..fdd5f66331b 100644 --- a/test/test_files/function/gds/rec_joins_small.test +++ b/test/test_files/function/gds/rec_joins_small.test @@ -226,98 +226,71 @@ -STATEMENT CALL create_project_graph('PK1', ['person1'], ['knows11']) ---- ok -LOG VarLenJoinsUBLessThanLBError --STATEMENT MATCH (a:person1) - CALL var_len_joins('PK1', a, 2, 1, "FWD") - RETURN *; +-STATEMENT MATCH (a:person1)-[e:knows11 * 2..1]->(b:person1) RETURN *; ---- error -Runtime exception: Lower bound length of recursive join operations need to be less than or equal to upper bound. Given lower bound is: 2 and upper bound is: 1. - +Binder exception: Lower bound of rel e is greater than upperBound. -LOG VarLenJoinsUBTooHighError --STATEMENT MATCH (a:person1) - CALL var_len_joins('PK1', a, 1, 10000,"FWD") - RETURN *; ----- error -Runtime exception: Recursive join operations only works for non-positive upper bound iterations that are up to 255. Given upper bound is: 10000. - --LOG VarLenJoinsLBNonPositiveError --STATEMENT MATCH (a:person1) - CALL var_len_joins('PK1', a, -1, 3, "FWD") - RETURN *; +-STATEMENT MATCH (a:person1)-[e:knows11 * 1..10000]->(b:person1) RETURN *; ---- error -Runtime exception: Lower and upper bound lengths of recursive join operations need to be non-negative. Given lower bound is: -1 and upper bound is: 3. +Binder exception: Upper bound of rel e exceeds maximum: 30. -LOG ShortestPathsJoinsUBNonPositiveError --STATEMENT MATCH (a:person1) - CALL all_sp_paths('PK1', a, -5, "FWD") - RETURN *; +-STATEMENT MATCH (a:person1)-[e:knows11 * ALL SHORTEST 0..1]->(b:person1) RETURN *; ---- error -Runtime exception: Lower and upper bound lengths of recursive join operations need to be non-negative. Given lower bound is: 1 and upper bound is: -5. - --LOG ShortestPathsJoinsUBNonPositiveError --STATEMENT MATCH (a:person1) - CALL all_sp_paths('PK1', a, 0, "FWD") - RETURN *; ----- error -Runtime exception: Shortest path operations only works for positive upper bound iterations. Given upper bound is: 0. +Binder exception: Lower bound of shortest/all_shortest path must be 1. -LOG VarLenJoins --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL var_len_joins('PK1', a, 1, 30, "FWD") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +-STATEMENT MATCH (a:person1)-[e:knows11 * 1..30]->(b:person1) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e), properties(nodes(e), 'id'), properties(rels(e), 'score'); ---- 6 -0|1|1|[]|[2:0] -0|2|2|[0:1]|[2:0,2:1] -0|3|3|[0:1,0:2]|[2:0,2:1,2:2] -0|4|3|[0:1,0:2]|[2:0,2:1,2:4] -0|4|3|[0:1,0:2]|[2:0,2:1,2:5] -0|4|4|[0:1,0:2,0:3]|[2:0,2:1,2:2,2:3] - --STATEMENT MATCH (a:person1) WHERE a.ID = 4 - CALL var_len_joins('PK1', a, 1, 30, "BWD") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +0|1|1|[]|[1] +0|2|2|[1]|[1,2] +0|3|3|[1,2]|[1,2,3] +0|4|3|[1,2]|[1,2,5] +0|4|3|[1,2]|[1,2,6] +0|4|4|[1,2,3]|[1,2,3,4] +-STATEMENT MATCH (a:person1)<-[e:knows11 * 1..30]-(b:person1) WHERE a.ID=4 + RETURN a.ID, b.ID, length(e), properties(nodes(e), 'id'), properties(rels(e), 'score'); ---- 10 -4|0|3|[0:2,0:1]|[2:4,2:1,2:0] -4|0|3|[0:2,0:1]|[2:5,2:1,2:0] -4|0|4|[0:3,0:2,0:1]|[2:3,2:2,2:1,2:0] -4|1|2|[0:2]|[2:4,2:1] -4|1|2|[0:2]|[2:5,2:1] -4|1|3|[0:3,0:2]|[2:3,2:2,2:1] -4|2|1|[]|[2:4] -4|2|1|[]|[2:5] -4|2|2|[0:3]|[2:3,2:2] -4|3|1|[]|[2:3] --STATEMENT MATCH (a:person1) WHERE a.ID = 1 - CALL var_len_joins('PK1', a, 1, 2, "BOTH") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs, direction; +4|0|3|[2,1]|[5,2,1] +4|0|3|[2,1]|[6,2,1] +4|0|4|[3,2,1]|[4,3,2,1] +4|1|2|[2]|[5,2] +4|1|2|[2]|[6,2] +4|1|3|[3,2]|[4,3,2] +4|2|1|[]|[5] +4|2|1|[]|[6] +4|2|2|[3]|[4,3] +4|3|1|[]|[4] +-STATEMENT MATCH (a:person1)-[e:knows11 * 1..2]-(b:person1) WHERE a.ID=1 + RETURN a.ID, b.ID, length(e), properties(nodes(e), 'id'), properties(rels(e), 'score'); ---- 7 -1|0|1|[]|[2:0]|[False] -1|1|2|[0:0]|[2:0,2:0]|[False,True] -1|1|2|[0:2]|[2:1,2:1]|[True,False] -1|2|1|[]|[2:1]|[True] -1|3|2|[0:2]|[2:1,2:2]|[True,True] -1|4|2|[0:2]|[2:1,2:4]|[True,True] -1|4|2|[0:2]|[2:1,2:5]|[True,True] +1|0|1|[]|[1] +1|1|2|[0]|[1,1] +1|1|2|[2]|[2,2] +1|2|1|[]|[2] +1|3|2|[2]|[2,3] +1|4|2|[2]|[2,5] +1|4|2|[2]|[2,6] -STATEMENT CALL create_project_graph('PK2', ['person1', 'person2'], ['knows12', 'knows21']) ---- ok -LOG VarLenJoinsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL var_len_joins('PK2', a, 1, 30, "FWD") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * 1..30]->(b:person2:person1) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e), properties(nodes(e), 'id'), properties(rels(e), 'score'); ---- 6 -0|1|1|[]|[3:0] -0|2|2|[1:1]|[3:0,4:1] -0|3|3|[1:1,0:2]|[3:0,4:1,3:2] -0|4|3|[1:1,0:2]|[3:0,4:1,3:4] -0|4|3|[1:1,0:2]|[3:0,4:1,3:5] -0|4|4|[1:1,0:2,1:3]|[3:0,4:1,3:2,4:3] +0|1|1|[]|[1] +0|2|2|[1]|[1,2] +0|3|3|[1,2]|[1,2,3] +0|4|3|[1,2]|[1,2,5] +0|4|3|[1,2]|[1,2,6] +0|4|4|[1,2,3]|[1,2,3,4] -STATEMENT CALL create_project_graph('PK3', ['person1', 'person2'], ['knows11', 'knows12', 'knows21', 'knows22']) ---- ok -LOG VarLenJoinsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL var_len_joins('PK3', a, 1, 30, "FWD") - RETURN length, count(*) +-STATEMENT MATCH (a:person1)-[e * 1..30]->(b:person2:person1) WHERE a.ID=0 + RETURN length(e), COUNT(*); ---- 4 1|2 2|4 @@ -325,49 +298,42 @@ Runtime exception: Shortest path operations only works for positive upper bound 4|16 -LOG VarLenJoinsLowerBoundZeroUpperBoundOne --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL var_len_joins('PK1', a, 0, 2, "FWD") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +-STATEMENT MATCH (a:person1)-[e:knows11 * 0..2]->(b:person1) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e), properties(nodes(e), 'id'), properties(rels(e), 'score'); ---- 3 0|0|0|[]|[] -0|1|1|[]|[2:0] -0|2|2|[0:1]|[2:0,2:1] +0|1|1|[]|[1] +0|2|2|[1]|[1,2] -LOG VarLenJoinsLowerBoundZeroUpperBoundZero --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL var_len_joins('PK1', a, 0, 0, "FWD") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +-STATEMENT MATCH (a:person1)-[e:knows11 * 0..0]->(b:person1) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e), properties(nodes(e), 'id'), properties(rels(e), 'score'); ---- 1 0|0|0|[]|[] -LOG VarLenJoinsLowerBound1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL var_len_joins('PK1', a, 2, 3, "FWD") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +-STATEMENT MATCH (a:person1)-[e:knows11 * 2..3]->(b:person1) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e), properties(nodes(e), 'id'), properties(rels(e), 'score'); ---- 4 -0|2|2|[0:1]|[2:0,2:1] -0|3|3|[0:1,0:2]|[2:0,2:1,2:2] -0|4|3|[0:1,0:2]|[2:0,2:1,2:4] -0|4|3|[0:1,0:2]|[2:0,2:1,2:5] +0|2|2|[1]|[1,2] +0|3|3|[1,2]|[1,2,3] +0|4|3|[1,2]|[1,2,5] +0|4|3|[1,2]|[1,2,6] -LOG VarLenJoinsLowerBound2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL var_len_joins('PK1', a, 4, 30, "FWD") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +-STATEMENT MATCH (a:person1)-[e:knows11 * 4..30]->(b:person1) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e), properties(nodes(e), 'id'), properties(rels(e), 'score'); ---- 1 -0|4|4|[0:1,0:2,0:3]|[2:0,2:1,2:2,2:3] +0|4|4|[1,2,3]|[1,2,3,4] -LOG VarLenJoinsEmptyPaths --STATEMENT MATCH (a:person1) WHERE a.ID = 4 - CALL var_len_joins('PK1', a, 1, 4, "FWD") - RETURN a.ID, node.ID, length, pathNodeIDs; +-STATEMENT MATCH (a:person1)-[e:knows11 * 1..4]->(b:person1) WHERE a.ID=4 + RETURN a.ID, b.ID, length(e), properties(nodes(e), 'id'), properties(rels(e), 'score'); ---- 0 - -LOG AllSPDestinations --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL all_sp_destinations('PK1', a, 30, "FWD") - RETURN a.ID, node.ID; +-STATEMENT MATCH (a:person1)-[e:knows11 * ALL SHORTEST 1..30]->(b:person1) WHERE a.ID=0 + RETURN a.ID, b.ID; ---- 5 0|1 0|2 @@ -376,9 +342,8 @@ Runtime exception: Shortest path operations only works for positive upper bound 0|4 -LOG AllSPDestinationsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL all_sp_destinations('PK2', a, 30, "FWD") - RETURN a.ID, node.ID; +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN a.ID, b.ID; ---- 6 0|1 0|2 @@ -388,9 +353,8 @@ Runtime exception: Shortest path operations only works for positive upper bound 0|4 -LOG AllSPDestinationsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL all_sp_destinations('PK3', a, 30, "FWD") - RETURN a.ID, node.ID; +-STATEMENT MATCH (a:person1)-[e * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN a.ID, b.ID; ---- 30 0|1 0|1 @@ -424,9 +388,8 @@ Runtime exception: Shortest path operations only works for positive upper bound 0|4 -LOG AllSPLengths --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL ALL_SP_DESTINATIONS('PK1', a, 30, "FWD") - RETURN a.ID, node.ID, length; +-STATEMENT MATCH (a:person1)-[e:knows11 * ALL SHORTEST 1..30]->(b:person1) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e); ---- 5 0|1|1 0|2|2 @@ -435,9 +398,8 @@ Runtime exception: Shortest path operations only works for positive upper bound 0|4|3 -LOG AllSPLengthsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL ALL_SP_DESTINATIONS('PK2', a, 30, "FWD") - RETURN a.ID, node.ID, length; +-STATEMENT MATCH (a:person1)-[e:knows12|knows21 * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e); ---- 6 0|1|1 0|2|2 @@ -447,9 +409,8 @@ Runtime exception: Shortest path operations only works for positive upper bound 0|4|4 -LOG AllSPLengthsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL ALL_SP_DESTINATIONS('PK3', a, 30, "FWD") - RETURN a.ID, node.ID, length; +-STATEMENT MATCH (a:person1)-[e * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e); ---- 30 0|1|1 0|1|1 @@ -483,79 +444,74 @@ Runtime exception: Shortest path operations only works for positive upper bound 0|4|3 -LOG AllSPPaths --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL all_sp_paths('PK1', a, 5, "FWD") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +-STATEMENT MATCH (a:person1)-[e:knows11 * ALL SHORTEST 1..5]->(b:person1) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e), properties(nodes(e),'ID'), properties(rels(e), 'score'); ---- 5 -0|1|1|[]|[2:0] -0|2|2|[0:1]|[2:0,2:1] -0|3|3|[0:1,0:2]|[2:0,2:1,2:2] -0|4|3|[0:1,0:2]|[2:0,2:1,2:4] -0|4|3|[0:1,0:2]|[2:0,2:1,2:5] --STATEMENT MATCH (a:person1) WHERE a.ID = 4 - CALL all_sp_paths('PK1', a, 5, "BOTH") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +0|1|1|[]|[1] +0|2|2|[1]|[1,2] +0|3|3|[1,2]|[1,2,3] +0|4|3|[1,2]|[1,2,5] +0|4|3|[1,2]|[1,2,6] +-STATEMENT MATCH (a:person1)-[e:knows11 * ALL SHORTEST 1..5]-(b:person1) WHERE a.ID=4 + RETURN a.ID, b.ID, length(e), properties(nodes(e),'ID'), properties(rels(e), 'score'); ---- 7 -4|0|3|[0:2,0:1]|[2:4,2:1,2:0] -4|0|3|[0:2,0:1]|[2:5,2:1,2:0] -4|1|2|[0:2]|[2:4,2:1] -4|1|2|[0:2]|[2:5,2:1] -4|2|1|[]|[2:4] -4|2|1|[]|[2:5] -4|3|1|[]|[2:3] +4|0|3|[2,1]|[5,2,1] +4|0|3|[2,1]|[6,2,1] +4|1|2|[2]|[5,2] +4|1|2|[2]|[6,2] +4|2|1|[]|[5] +4|2|1|[]|[6] +4|3|1|[]|[4] -LOG AllSPPathsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL all_sp_paths('PK2', a, 30, "FWD") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e), properties(nodes(e),'ID'), properties(rels(e), 'score'); ---- 6 -0|1|1|[]|[3:0] -0|2|2|[1:1]|[3:0,4:1] -0|3|3|[1:1,0:2]|[3:0,4:1,3:2] -0|4|3|[1:1,0:2]|[3:0,4:1,3:4] -0|4|3|[1:1,0:2]|[3:0,4:1,3:5] -0|4|4|[1:1,0:2,1:3]|[3:0,4:1,3:2,4:3] +0|1|1|[]|[1] +0|2|2|[1]|[1,2] +0|3|3|[1,2]|[1,2,3] +0|4|3|[1,2]|[1,2,5] +0|4|3|[1,2]|[1,2,6] +0|4|4|[1,2,3]|[1,2,3,4] -LOG AllSPPathsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL all_sp_paths('PK3', a, 30, "FWD") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +-STATEMENT MATCH (a:person1)-[e * ALL SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e), properties(nodes(e),'ID'), properties(rels(e), 'score'); ---- 30 -0|1|1|[]|[2:0] -0|1|1|[]|[3:0] -0|2|2|[0:1]|[2:0,2:1] -0|2|2|[0:1]|[2:0,3:1] -0|2|2|[1:1]|[3:0,4:1] -0|2|2|[1:1]|[3:0,5:1] -0|3|3|[0:1,0:2]|[2:0,2:1,2:2] -0|3|3|[0:1,0:2]|[2:0,2:1,3:2] -0|3|3|[0:1,1:2]|[2:0,3:1,4:2] -0|3|3|[0:1,1:2]|[2:0,3:1,5:2] -0|3|3|[1:1,0:2]|[3:0,4:1,2:2] -0|3|3|[1:1,0:2]|[3:0,4:1,3:2] -0|3|3|[1:1,1:2]|[3:0,5:1,4:2] -0|3|3|[1:1,1:2]|[3:0,5:1,5:2] -0|4|3|[0:1,0:2]|[2:0,2:1,2:4] -0|4|3|[0:1,0:2]|[2:0,2:1,2:5] -0|4|3|[0:1,0:2]|[2:0,2:1,3:4] -0|4|3|[0:1,0:2]|[2:0,2:1,3:5] -0|4|3|[0:1,1:2]|[2:0,3:1,4:4] -0|4|3|[0:1,1:2]|[2:0,3:1,4:5] -0|4|3|[0:1,1:2]|[2:0,3:1,5:4] -0|4|3|[0:1,1:2]|[2:0,3:1,5:5] -0|4|3|[1:1,0:2]|[3:0,4:1,2:4] -0|4|3|[1:1,0:2]|[3:0,4:1,2:5] -0|4|3|[1:1,0:2]|[3:0,4:1,3:4] -0|4|3|[1:1,0:2]|[3:0,4:1,3:5] -0|4|3|[1:1,1:2]|[3:0,5:1,4:4] -0|4|3|[1:1,1:2]|[3:0,5:1,4:5] -0|4|3|[1:1,1:2]|[3:0,5:1,5:4] -0|4|3|[1:1,1:2]|[3:0,5:1,5:5] +0|1|1|[]|[1] +0|1|1|[]|[1] +0|2|2|[1]|[1,2] +0|2|2|[1]|[1,2] +0|2|2|[1]|[1,2] +0|2|2|[1]|[1,2] +0|3|3|[1,2]|[1,2,3] +0|3|3|[1,2]|[1,2,3] +0|3|3|[1,2]|[1,2,3] +0|3|3|[1,2]|[1,2,3] +0|3|3|[1,2]|[1,2,3] +0|3|3|[1,2]|[1,2,3] +0|3|3|[1,2]|[1,2,3] +0|3|3|[1,2]|[1,2,3] +0|4|3|[1,2]|[1,2,5] +0|4|3|[1,2]|[1,2,5] +0|4|3|[1,2]|[1,2,5] +0|4|3|[1,2]|[1,2,5] +0|4|3|[1,2]|[1,2,5] +0|4|3|[1,2]|[1,2,5] +0|4|3|[1,2]|[1,2,5] +0|4|3|[1,2]|[1,2,5] +0|4|3|[1,2]|[1,2,6] +0|4|3|[1,2]|[1,2,6] +0|4|3|[1,2]|[1,2,6] +0|4|3|[1,2]|[1,2,6] +0|4|3|[1,2]|[1,2,6] +0|4|3|[1,2]|[1,2,6] +0|4|3|[1,2]|[1,2,6] +0|4|3|[1,2]|[1,2,6] -LOG SingleSPDestinations --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL SINGLE_SP_DESTINATIONS('PK1', a, 30, "FWD") - RETURN a.ID, node.ID; +-STATEMENT MATCH (a:person1)-[e:knows11 * SHORTEST 1..30]->(b:person1) WHERE a.ID=0 + RETURN a.ID, b.ID; ---- 4 0|1 0|2 @@ -563,9 +519,8 @@ Runtime exception: Shortest path operations only works for positive upper bound 0|4 -LOG SingleSPDestinationsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL SINGLE_SP_DESTINATIONS('PK2', a, 30, "FWD") - RETURN a.ID, node.ID; +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN a.ID, b.ID; ---- 5 0|1 0|2 @@ -574,9 +529,8 @@ Runtime exception: Shortest path operations only works for positive upper bound 0|4 -LOG SingleSPDestinationsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL single_sp_destinations('PK3', a, 30, "FWD") - RETURN a.ID, node.ID +-STATEMENT MATCH (a:person1)-[e * SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN a.ID, b.ID; ---- 8 0|1 0|1 @@ -588,9 +542,8 @@ Runtime exception: Shortest path operations only works for positive upper bound 0|4 -LOG SingleSPLengths --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL SINGLE_SP_DESTINATIONS('PK1', a, 30, "FWD") - RETURN a.ID, node.ID, length; +-STATEMENT MATCH (a:person1)-[e:knows11 * SHORTEST 1..30]->(b:person1) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e); ---- 4 0|1|1 0|2|2 @@ -598,9 +551,8 @@ Runtime exception: Shortest path operations only works for positive upper bound 0|4|3 -LOG SingleSPLengthsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL SINGLE_SP_DESTINATIONS('PK2', a, 30, "FWD") - RETURN a.ID, node.ID, length; +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e); ---- 5 0|1|1 0|2|2 @@ -609,9 +561,8 @@ Runtime exception: Shortest path operations only works for positive upper bound 0|4|4 -LOG SingleSPLengthsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL SINGLE_SP_DESTINATIONS('PK3', a, 30, "FWD") - RETURN a.ID, node.ID, length +-STATEMENT MATCH (a:person1)-[e * SHORTEST 1..30]->(b) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e); ---- 8 0|1|1 0|1|1 @@ -623,38 +574,34 @@ Runtime exception: Shortest path operations only works for positive upper bound 0|4|3 -LOG SingleSPPaths --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL single_sp_paths('PK1', a, 5, "FWD") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +-STATEMENT MATCH (a:person1)-[e:knows11 * SHORTEST 1..5]->(b:person1) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e), properties(nodes(e),'ID'), properties(rels(e), 'score'); ---- 4 -0|1|1|[]|[2:0] -0|2|2|[0:1]|[2:0,2:1] -0|3|3|[0:1,0:2]|[2:0,2:1,2:2] -0|4|3|[0:1,0:2]|[2:0,2:1,2:4] --STATEMENT MATCH (a:person1) WHERE a.ID = 2 - CALL single_sp_paths('PK1', a, 5, "BOTH") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +0|1|1|[]|[1] +0|2|2|[1]|[1,2] +0|3|3|[1,2]|[1,2,3] +0|4|3|[1,2]|[1,2,5] +-STATEMENT MATCH (a:person1)-[e:knows11 * SHORTEST 1..5]-(b:person1) WHERE a.ID=2 + RETURN a.ID, b.ID, length(e), properties(nodes(e),'ID'), properties(rels(e), 'score'); ---- 4 -2|0|2|[0:1]|[2:1,2:0] -2|1|1|[]|[2:1] -2|3|1|[]|[2:2] -2|4|1|[]|[2:4] +2|0|2|[1]|[2,1] +2|1|1|[]|[2] +2|3|1|[]|[3] +2|4|1|[]|[5] -LOG SingleSPPathsMultilabel1 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL single_sp_paths('PK2', a, 30, "FWD") - RETURN a.ID, node.ID, length, pathNodeIDs, pathEdgeIDs; +-STATEMENT MATCH (a:person1)-[e:knows12|:knows21 * SHORTEST 1..5]->(b) WHERE a.ID=0 + RETURN a.ID, b.ID, length(e), properties(nodes(e),'ID'), properties(rels(e), 'score'); ---- 5 -0|1|1|[]|[3:0] -0|2|2|[1:1]|[3:0,4:1] -0|3|3|[1:1,0:2]|[3:0,4:1,3:2] -0|4|3|[1:1,0:2]|[3:0,4:1,3:4] -0|4|4|[1:1,0:2,1:3]|[3:0,4:1,3:2,4:3] +0|1|1|[]|[1] +0|2|2|[1]|[1,2] +0|3|3|[1,2]|[1,2,3] +0|4|3|[1,2]|[1,2,5] +0|4|4|[1,2,3]|[1,2,3,4] -LOG SingleSPPathsMultilabel2 --STATEMENT MATCH (a:person1) WHERE a.ID = 0 - CALL single_sp_paths('PK3', a, 30, "FWD") - RETURN length, count(*) +-STATEMENT MATCH (a:person1)-[e * SHORTEST 1..5]->(b) WHERE a.ID=0 + RETURN length(e), COUNT(*); ---- 3 1|2 2|2