diff --git a/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp b/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp index 4144d22a..3e425ef0 100644 --- a/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp +++ b/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp @@ -106,8 +106,11 @@ struct PGQMatchFunction : public TableFunction { vector> &column_list, unordered_set &named_subpaths); + // static unique_ptr + // CreatePathFindingFunction(vector> &path_list, + // CreatePropertyGraphInfo &pg_table); static unique_ptr - CreatePathFindingFunction(vector> &path_list, + CreatePathFindingFunction(SubPath &subpath, CreatePropertyGraphInfo &pg_table); static void AddPathFinding(const unique_ptr &select_node, diff --git a/duckpgq/src/duckpgq/functions/scalar/iterativelength.cpp b/duckpgq/src/duckpgq/functions/scalar/iterativelength.cpp index dc70b463..abbdc124 100644 --- a/duckpgq/src/duckpgq/functions/scalar/iterativelength.cpp +++ b/duckpgq/src/duckpgq/functions/scalar/iterativelength.cpp @@ -8,7 +8,7 @@ namespace duckdb { static bool IterativeLength(int64_t v_size, int64_t *v, vector &e, - vector>> &parents_v, + vector>> &parents_v, vector> &seen, vector> &visit, vector> &next) { @@ -22,8 +22,9 @@ static bool IterativeLength(int64_t v_size, int64_t *v, vector &e, if (visit[i][lane]) { for (auto offset = v[i]; offset < v[i + 1]; offset++) { auto n = e[offset]; - if (parents_v[i][lane].find(n) == parents_v[i][lane].end()) { - parents_v[i][lane].insert(n); + if (seen[n][lane] == false || parents_v[i][lane].find(n) == parents_v[i][lane].end()) { + parents_v[n][lane] = parents_v[i][lane]; + parents_v[n][lane].insert(i); next[n][lane] = true; } } @@ -31,37 +32,11 @@ static bool IterativeLength(int64_t v_size, int64_t *v, vector &e, } } - // for (auto i = 0; i < v_size; i++) { - // if (visit[i].any()) { - // for (auto offset = v[i]; offset < v[i + 1]; offset++) { - // auto n = e[offset]; - // next[n] = next[n] | visit[i]; - // } - // } - // } for (auto i = 0; i < v_size; i++) { // next[i] = next[i] & ~seen[i]; seen[i] = seen[i] | next[i]; change |= next[i].any(); } - - // vector> next_next = vector>(v_size, 0); - // // If a vertex in next is a successor of other vertices in next, set it as unvisited - // for (auto i = 0; i < v_size; i++) { - // if (next[i].any()) { - // for (auto offset = v[i]; offset < v[i + 1]; offset++) { - // auto n = e[offset]; - // next_next[n] = next_next[n] | next[i]; - // } - // } - // } - // for (auto i = 0; i < v_size; i++) { - // next[i] = next[i] & ~next_next[i]; - // } - - // for (auto i = 0; i < v_size; i++) { - // change |= next[i].any(); - // } return change; } @@ -129,8 +104,7 @@ static void IterativeLengthFunction(DataChunk &args, ExpressionState &state, vector> seen(v_size); vector> visit1(v_size); vector> visit2(v_size); - // vector> level(v_size, std::vector(LANE_LIMIT, INT64_MAX)); - vector>> parents_v(v_size, std::vector>(LANE_LIMIT)); + vector>> parents_v(v_size, std::vector>(LANE_LIMIT)); // maps lane to search number short lane_to_num[LANE_LIMIT]; diff --git a/duckpgq/src/duckpgq/functions/scalar/shortest_path.cpp b/duckpgq/src/duckpgq/functions/scalar/shortest_path.cpp index 9cf0ad99..d02af0e5 100644 --- a/duckpgq/src/duckpgq/functions/scalar/shortest_path.cpp +++ b/duckpgq/src/duckpgq/functions/scalar/shortest_path.cpp @@ -13,12 +13,18 @@ namespace duckdb { static bool IterativeLength(int64_t v_size, int64_t *V, vector &E, vector &edge_ids, - vector> &parents_v, - vector> &parents_e, + // vector> &parents_v, + // vector> &parents_e, + vector>> &parents_v, + vector>> &paths_v, + vector>> &paths_e, vector> &seen, vector> &visit, vector> &next) { bool change = false; + map, unordered_set> parents_v_cache; + map, vector> paths_v_cache; + map, vector> paths_e_cache; for (auto v = 0; v < v_size; v++) { next[v] = 0; } @@ -28,20 +34,55 @@ static bool IterativeLength(int64_t v_size, int64_t *V, vector &E, for (auto e = V[v]; e < V[v + 1]; e++) { auto n = E[e]; auto edge_id = edge_ids[e]; - next[n] = next[n] | visit[v]; - for (auto l = 0; l < LANE_LIMIT; l++) { - parents_v[n][l] = - ((parents_v[n][l] == -1) && visit[v][l]) ? v : parents_v[n][l]; - parents_e[n][l] = ((parents_e[n][l] == -1) && visit[v][l]) - ? edge_id - : parents_e[n][l]; + + for (auto lane = 0; lane < LANE_LIMIT; lane++) { + if (visit[v][lane]) { + //! If the node has not been visited, then update the parent and edge + if (seen[n][lane] == false || parents_v[v][lane].find(n) == parents_v[v][lane].end()) { + if (visit[n][lane]) { + parents_v_cache[make_pair(n, lane)] = parents_v[v][lane]; + parents_v_cache[make_pair(n, lane)].insert(v); + paths_v_cache[make_pair(n, lane)] = paths_v[v][lane]; + paths_v_cache[make_pair(n, lane)].push_back(v); + paths_e_cache[make_pair(n, lane)] = paths_e[v][lane]; + paths_e_cache[make_pair(n, lane)].push_back(edge_id); + } else { + parents_v[n][lane] = parents_v[v][lane]; + parents_v[n][lane].insert(v); + paths_v[n][lane] = paths_v[v][lane]; + paths_v[n][lane].push_back(v); + paths_e[n][lane] = paths_e[v][lane]; + paths_e[n][lane].push_back(edge_id); + } + next[n][lane] = true; + } + } } + + // next[n] = next[n] | visit[v]; + // for (auto l = 0; l < LANE_LIMIT; l++) { + // parents_v[n][l] = + // ((parents_v[n][l] == -1) && visit[v][l]) ? v : parents_v[n][l]; + // parents_e[n][l] = ((parents_e[n][l] == -1) && visit[v][l]) + // ? edge_id + // : parents_e[n][l]; + // } } } } + for (auto const& [node, parents]: parents_v_cache) { + parents_v[node.first][node.second] = parents; + } + for (auto const& [node, path]: paths_v_cache) { + paths_v[node.first][node.second] = path; + } + for (auto const& [node, edge]: paths_e_cache) { + paths_e[node.first][node.second] = edge; + } + for (auto v = 0; v < v_size; v++) { - next[v] = next[v] & ~seen[v]; + // next[v] = next[v] & ~seen[v]; seen[v] = seen[v] | next[v]; change |= next[v].any(); } @@ -80,6 +121,16 @@ static void ShortestPathFunction(DataChunk &args, ExpressionState &state, auto src_data = (int64_t *)vdata_src.data; auto dst_data = (int64_t *)vdata_dst.data; + // get lowerbound and upperbound + auto &lower_bound = args.data[4]; + auto &upper_bound = args.data[5]; + UnifiedVectorFormat vdata_lower_bound; + UnifiedVectorFormat vdata_upper_bound; + lower_bound.ToUnifiedFormat(args.size(), vdata_lower_bound); + upper_bound.ToUnifiedFormat(args.size(), vdata_upper_bound); + auto lower_bound_data = (int64_t *)vdata_lower_bound.data; + auto upper_bound_data = (int64_t *)vdata_upper_bound.data; + result.SetVectorType(VectorType::FLAT_VECTOR); auto result_data = FlatVector::GetData(result); ValidityMask &result_validity = FlatVector::Validity(result); @@ -88,10 +139,19 @@ static void ShortestPathFunction(DataChunk &args, ExpressionState &state, vector> seen(v_size); vector> visit1(v_size); vector> visit2(v_size); - vector> parents_v(v_size, - std::vector(LANE_LIMIT, -1)); - vector> parents_e(v_size, - std::vector(LANE_LIMIT, -1)); + // vector> parents_v(v_size, + // std::vector(LANE_LIMIT, -1)); + // vector> parents_e(v_size, + // std::vector(LANE_LIMIT, -1)); + // vector> parents_v_result(v_size, + // std::vector(LANE_LIMIT, -1)); + // vector> parents_e_result(v_size, + // std::vector(LANE_LIMIT, -1)); + + vector>> parents_v(v_size, std::vector>(LANE_LIMIT)); + vector>> paths_v(v_size, std::vector>(LANE_LIMIT)); + vector>> paths_e(v_size, std::vector>(LANE_LIMIT)); + // maps lane to search number int16_t lane_to_num[LANE_LIMIT]; @@ -107,10 +167,12 @@ static void ShortestPathFunction(DataChunk &args, ExpressionState &state, for (auto i = 0; i < v_size; i++) { seen[i] = 0; visit1[i] = 0; - for (auto j = 0; j < LANE_LIMIT; j++) { - parents_v[i][j] = -1; - parents_e[i][j] = -1; - } + // for (auto j = 0; j < LANE_LIMIT; j++) { + // parents_v[i][j] = -1; + // parents_e[i][j] = -1; + // parents_v_result[i][j] = -1; + // parents_e_result[i][j] = -1; + // } } // add search jobs to free lanes @@ -122,13 +184,23 @@ static void ShortestPathFunction(DataChunk &args, ExpressionState &state, int64_t src_pos = vdata_src.sel->get_index(search_num); if (!vdata_src.validity.RowIsValid(src_pos)) { result_validity.SetInvalid(search_num); + } else if (src_data[src_pos] == dst_data[src_pos]) { + unique_ptr output = + make_uniq(LogicalType::LIST(LogicalType::BIGINT)); + ListVector::PushBack(*output, src_data[src_pos]); + ListVector::Append(result, ListVector::GetEntry(*output), + ListVector::GetListSize(*output)); + result_data[search_num].length = ListVector::GetListSize(*output); + result_data[search_num].offset = total_len; + total_len += result_data[search_num].length; } else { visit1[src_data[src_pos]][lane] = true; - parents_v[src_data[src_pos]][lane] = - src_data[src_pos]; // Mark source with source id - parents_e[src_data[src_pos]][lane] = - -2; // Mark the source with -2, there is no incoming edge for the - // source. + seen[src_data[src_pos]][lane] = true; + // parents_v[src_data[src_pos]][lane] = + // -2; // No incoming vertex for the source + // parents_e[src_data[src_pos]][lane] = + // -2; // Mark the source with -2, there is no incoming edge for the + // // source. lane_to_num[lane] = search_num; // active lane active++; break; @@ -136,22 +208,61 @@ static void ShortestPathFunction(DataChunk &args, ExpressionState &state, } } + bool stop[LANE_LIMIT] = {false}; //! make passes while a lane is still active for (int64_t iter = 1; active; iter++) { //! Perform one step of bfs exploration - if (!IterativeLength(v_size, v, e, edge_ids, parents_v, parents_e, seen, + if (!IterativeLength(v_size, v, e, edge_ids, parents_v, paths_v, paths_e, seen, (iter & 1) ? visit1 : visit2, (iter & 1) ? visit2 : visit1)) { break; } int64_t finished_searches = 0; // detect lanes that finished - for (int64_t lane = 0; lane < LANE_LIMIT; lane++) { + for (int64_t lane = 0; lane < LANE_LIMIT && (stop[lane] == false); lane++) { int64_t search_num = lane_to_num[lane]; if (search_num >= 0) { // active lane //! Check if dst for a source has been seen int64_t dst_pos = vdata_dst.sel->get_index(search_num); if (seen[dst_data[dst_pos]][lane]) { + // check if the path length is within bounds + // bound vector is either a constant or a flat vector + if (lower_bound.GetVectorType() == VectorType::CONSTANT_VECTOR ? + iter < lower_bound_data[0] : iter < lower_bound_data[dst_pos]) { + // when reach the destination too early, treat destination as null + // looks like the graph does not have that vertex + seen[dst_data[dst_pos]][lane] = false; + (iter & 1) ? visit2[dst_data[dst_pos]][lane] = false + : visit1[dst_data[dst_pos]][lane] = false; + continue; + } else if (upper_bound.GetVectorType() == VectorType::CONSTANT_VECTOR ? + iter > upper_bound_data[0] : iter > upper_bound_data[dst_pos]) { + result_validity.SetInvalid(search_num); + } else { + vector output_vector; + auto it_v = paths_v[dst_data[dst_pos]][lane].begin(), + end_v = paths_v[dst_data[dst_pos]][lane].end(); + auto it_e = paths_e[dst_data[dst_pos]][lane].begin(), + end_e = paths_e[dst_data[dst_pos]][lane].end(); + while (it_v != end_v && it_e != end_e) { + output_vector.push_back(*it_v); + output_vector.push_back(*it_e); + it_v++; + it_e++; + } + output_vector.push_back(dst_data[dst_pos]); + auto output = make_uniq(LogicalType::LIST(LogicalType::BIGINT)); + for (auto val : output_vector) { + Value value_to_insert = val; + ListVector::PushBack(*output, value_to_insert); + } + result_data[search_num].length = ListVector::GetListSize(*output); + result_data[search_num].offset = total_len; + ListVector::Append(result, ListVector::GetEntry(*output), + ListVector::GetListSize(*output)); + total_len += result_data[search_num].length; + } + stop[lane] = true; finished_searches++; } } @@ -160,71 +271,74 @@ static void ShortestPathFunction(DataChunk &args, ExpressionState &state, break; } } - //! Reconstruct the paths - for (int64_t lane = 0; lane < LANE_LIMIT; lane++) { - int64_t search_num = lane_to_num[lane]; - if (search_num == -1) { // empty lanes - continue; - } + // //! Reconstruct the paths + // for (int64_t lane = 0; lane < LANE_LIMIT; lane++) { + // int64_t search_num = lane_to_num[lane]; + // if (search_num == -1) { // empty lanes + // continue; + // } - //! Searches that have stopped have found a path - int64_t src_pos = vdata_src.sel->get_index(search_num); - int64_t dst_pos = vdata_dst.sel->get_index(search_num); - if (src_data[src_pos] == dst_data[dst_pos]) { // Source == destination - unique_ptr output = - make_uniq(LogicalType::LIST(LogicalType::BIGINT)); - ListVector::PushBack(*output, src_data[src_pos]); - ListVector::Append(result, ListVector::GetEntry(*output), - ListVector::GetListSize(*output)); - result_data[search_num].length = ListVector::GetListSize(*output); - result_data[search_num].offset = total_len; - total_len += result_data[search_num].length; - continue; - } - std::vector output_vector; - std::vector output_edge; - auto source_v = src_data[src_pos]; // Take the source - - auto parent_vertex = - parents_v[dst_data[dst_pos]] - [lane]; // Take the parent vertex of the destination vertex - auto parent_edge = - parents_e[dst_data[dst_pos]] - [lane]; // Take the parent edge of the destination vertex - - output_vector.push_back(dst_data[dst_pos]); // Add destination vertex - output_vector.push_back(parent_edge); - while (parent_vertex != source_v) { // Continue adding vertices until we - // have reached the source vertex - //! -1 is used to signify no parent - if (parent_vertex == -1 || - parent_vertex == parents_v[parent_vertex][lane]) { - result_validity.SetInvalid(search_num); - break; - } - output_vector.push_back(parent_vertex); - parent_edge = parents_e[parent_vertex][lane]; - parent_vertex = parents_v[parent_vertex][lane]; - output_vector.push_back(parent_edge); - } + // //! Searches that have stopped have found a path + // int64_t src_pos = vdata_src.sel->get_index(search_num); + // int64_t dst_pos = vdata_dst.sel->get_index(search_num); - if (!result_validity.RowIsValid(search_num)) { - continue; - } - output_vector.push_back(source_v); - std::reverse(output_vector.begin(), output_vector.end()); - auto output = make_uniq(LogicalType::LIST(LogicalType::BIGINT)); - for (auto val : output_vector) { - Value value_to_insert = val; - ListVector::PushBack(*output, value_to_insert); - } + // parents_v_result[src_data[src_pos]][lane] = src_data[src_pos]; - result_data[search_num].length = ListVector::GetListSize(*output); - result_data[search_num].offset = total_len; - ListVector::Append(result, ListVector::GetEntry(*output), - ListVector::GetListSize(*output)); - total_len += result_data[search_num].length; - } + // if (src_data[src_pos] == dst_data[dst_pos]) { // Source == destination + // unique_ptr output = + // make_uniq(LogicalType::LIST(LogicalType::BIGINT)); + // ListVector::PushBack(*output, src_data[src_pos]); + // ListVector::Append(result, ListVector::GetEntry(*output), + // ListVector::GetListSize(*output)); + // result_data[search_num].length = ListVector::GetListSize(*output); + // result_data[search_num].offset = total_len; + // total_len += result_data[search_num].length; + // continue; + // } + // std::vector output_vector; + // std::vector output_edge; + // auto source_v = src_data[src_pos]; // Take the source + + // auto parent_vertex = + // parents_v_result[dst_data[dst_pos]] + // [lane]; // Take the parent vertex of the destination vertex + // auto parent_edge = + // parents_e_result[dst_data[dst_pos]] + // [lane]; // Take the parent edge of the destination vertex + + // output_vector.push_back(dst_data[dst_pos]); // Add destination vertex + // output_vector.push_back(parent_edge); + // while (parent_vertex != source_v) { // Continue adding vertices until we + // // have reached the source vertex + // //! -1 is used to signify no parent + // if (parent_vertex == -1 || + // parent_vertex == parents_v_result[parent_vertex][lane]) { + // result_validity.SetInvalid(search_num); + // break; + // } + // output_vector.push_back(parent_vertex); + // parent_edge = parents_e_result[parent_vertex][lane]; + // parent_vertex = parents_v_result[parent_vertex][lane]; + // output_vector.push_back(parent_edge); + // } + + // if (!result_validity.RowIsValid(search_num)) { + // continue; + // } + // output_vector.push_back(source_v); + // std::reverse(output_vector.begin(), output_vector.end()); + // auto output = make_uniq(LogicalType::LIST(LogicalType::BIGINT)); + // for (auto val : output_vector) { + // Value value_to_insert = val; + // ListVector::PushBack(*output, value_to_insert); + // } + + // result_data[search_num].length = ListVector::GetListSize(*output); + // result_data[search_num].offset = total_len; + // ListVector::Append(result, ListVector::GetEntry(*output), + // ListVector::GetListSize(*output)); + // total_len += result_data[search_num].length; + // } } duckpgq_state->csr_to_delete.insert(info.csr_id); } @@ -232,6 +346,7 @@ static void ShortestPathFunction(DataChunk &args, ExpressionState &state, CreateScalarFunctionInfo DuckPGQFunctions::GetShortestPathFunction() { auto fun = ScalarFunction("shortestpath", {LogicalType::INTEGER, LogicalType::BIGINT, + LogicalType::BIGINT, LogicalType::BIGINT, LogicalType::BIGINT, LogicalType::BIGINT}, LogicalType::LIST(LogicalType::BIGINT), ShortestPathFunction, @@ -239,4 +354,4 @@ CreateScalarFunctionInfo DuckPGQFunctions::GetShortestPathFunction() { return CreateScalarFunctionInfo(fun); } -}; // namespace duckdb +} // namespace duckdb diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index 4c7a4fdb..74284eb3 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -486,7 +486,8 @@ CreateWhereClause(vector> &conditions) { } unique_ptr PGQMatchFunction::CreatePathFindingFunction( - vector> &path_list, + // vector> &path_list, + SubPath &subpath, CreatePropertyGraphInfo &pg_table) { // This method will return a SubqueryRef of a list of rowids // For every vertex and edge element, we add the rowid to the list using @@ -496,6 +497,7 @@ unique_ptr PGQMatchFunction::CreatePathFindingFunction( // full list of element rowids, using list_concat. For now we will only // support returning rowids unique_ptr final_list; + auto &path_list = subpath.path_list; auto previous_vertex_element = GetPathElement(path_list[0]); if (!previous_vertex_element) { @@ -535,6 +537,10 @@ unique_ptr PGQMatchFunction::CreatePathFindingFunction( edge_table, previous_vertex_element->variable_binding))); pathfinding_children.push_back(std::move(src_row_id)); pathfinding_children.push_back(std::move(dst_row_id)); + pathfinding_children.push_back( + make_uniq(Value::INTEGER(static_cast(subpath.lower)))); + pathfinding_children.push_back( + make_uniq(Value::INTEGER(static_cast(subpath.upper)))); auto shortest_path_function = make_uniq( "shortestpath", std::move(pathfinding_children)); @@ -658,6 +664,7 @@ void PGQMatchFunction::AddPathFinding( //! START //! WHERE __x.temp + iterativelength(, (SELECT count(c.id) //! from dst c, a.rowid, b.rowid) between lower and upper + //! from dst c, a.rowid, b.rowid, lower, upper) auto src_row_id = make_uniq("rowid", prev_binding); auto dst_row_id = make_uniq("rowid", next_binding); @@ -669,6 +676,10 @@ void PGQMatchFunction::AddPathFinding( std::move(GetCountTable(edge_table, prev_binding))); pathfinding_children.push_back(std::move(src_row_id)); pathfinding_children.push_back(std::move(dst_row_id)); + pathfinding_children.push_back( + make_uniq(Value::INTEGER(static_cast(subpath->lower)))); + pathfinding_children.push_back( + make_uniq(Value::INTEGER(static_cast(subpath->upper)))); auto reachability_function = make_uniq( "iterativelength", std::move(pathfinding_children)); @@ -681,14 +692,14 @@ void PGQMatchFunction::AddPathFinding( auto addition_function = make_uniq("add", std::move(addition_children)); - auto lower_limit = make_uniq( - Value::INTEGER(static_cast(subpath->lower))); - auto upper_limit = make_uniq( - Value::INTEGER(static_cast(subpath->upper))); - auto between_expression = make_uniq( - std::move(addition_function), std::move(lower_limit), - std::move(upper_limit)); - conditions.push_back(std::move(between_expression)); + // auto lower_limit = make_uniq( + // Value::INTEGER(static_cast(subpath->lower))); + // auto upper_limit = make_uniq( + // Value::INTEGER(static_cast(subpath->upper))); + // auto between_expression = make_uniq( + // std::move(addition_function), std::move(lower_limit), + // std::move(upper_limit)); + conditions.push_back(std::move(addition_function)); //! END //! WHERE __x.temp + iterativelength(, (SELECT count(s.id) @@ -718,8 +729,10 @@ void PGQMatchFunction::CheckNamedSubpath( if (parsed_ref->function_name == "element_id") { // Check subpath name matches the column referenced in the function --> // element_id(named_subpath) + // auto shortest_path_function = + // CreatePathFindingFunction(subpath.path_list, pg_table); auto shortest_path_function = - CreatePathFindingFunction(subpath.path_list, pg_table); + CreatePathFindingFunction(subpath, pg_table); if (column_alias.empty()) { shortest_path_function->alias = @@ -731,8 +744,10 @@ void PGQMatchFunction::CheckNamedSubpath( column_list.insert(column_list.begin() + idx_i, std::move(shortest_path_function)); } else if (parsed_ref->function_name == "path_length") { + // auto shortest_path_function = + // CreatePathFindingFunction(subpath.path_list, pg_table); auto shortest_path_function = - CreatePathFindingFunction(subpath.path_list, pg_table); + CreatePathFindingFunction(subpath, pg_table); auto path_len_children = vector>(); path_len_children.push_back(std::move(shortest_path_function)); auto path_len = @@ -751,8 +766,10 @@ void PGQMatchFunction::CheckNamedSubpath( std::move(path_length_function)); } else if (parsed_ref->function_name == "vertices" || parsed_ref->function_name == "edges") { + // auto shortest_path_function = + // CreatePathFindingFunction(subpath.path_list, pg_table); auto shortest_path_function = - CreatePathFindingFunction(subpath.path_list, pg_table); + CreatePathFindingFunction(subpath, pg_table); auto list_slice_children = vector>(); list_slice_children.push_back(std::move(shortest_path_function)); diff --git a/test/sql/path-finding/shortest_path.test b/test/sql/path-finding/shortest_path.test index a82e8ec1..4d6e7d03 100644 --- a/test/sql/path-finding/shortest_path.test +++ b/test/sql/path-finding/shortest_path.test @@ -46,18 +46,17 @@ Daniel VU query III -FROM GRAPH_TABLE (pg MATCH - p = ANY SHORTEST (a:Person WHERE a.name = 'Daniel')-[k:knows]->{1,3}(b:Person) + p = ANY SHORTEST (a:Person WHERE a.name = 'Daniel')-[k:knows]->{2,3}(b:Person) COLUMNS (element_id(p), a.name as name, b.name as b_name) ) study; ---- -[0, 0, 1] Daniel Tavneet -[0, 1, 2] Daniel Gabor -[0, 2, 3] Daniel Peter +[0, 0, 1, 4, 2] Daniel Gabor +[0, 1, 2, 6, 3] Daniel Peter query IIII -FROM GRAPH_TABLE (pg MATCH - p = ANY SHORTEST (a:Person)-[k:knows]->{1,3}(b:Person) + p = ANY SHORTEST (a:Person)-[k:knows]->{2,3}(b:Person) COLUMNS (path_length(p), element_id(p), a.name as name, b.name as b_name) ) study order by study.name, study.b_name; @@ -114,10 +113,9 @@ WITH cte1 AS ( FROM Know k JOIN student a on a.id = k.src JOIN student c on c.id = k.dst -) SELECT shortestpath(0, (select count(*) from student), a.rowid, b.rowid) as path, a.name as a_name, b.name as b_name +) SELECT shortestpath(0, (select count(*) from student), a.rowid, b.rowid, 2, 3) as path, a.name as a_name, b.name as b_name FROM student a, student b, (select count(cte1.temp) * 0 as temp from cte1) __x - WHERE a.name = 'Daniel' and __x.temp * 0 + iterativelength(0, (select count(*) from student), a.rowid, b.rowid) between 1 and 3 + WHERE a.name = 'Daniel' and __x.temp * 0 + iterativelength(0, (select count(*) from student), a.rowid, b.rowid, 2, 3); ---- -[0, 0, 1] Daniel Tavneet -[0, 1, 2] Daniel Gabor -[0, 2, 3] Daniel Peter +[0, 0, 1, 4, 2] Daniel Gabor +[0, 1, 2, 6, 3] Daniel Peter