Skip to content

Commit 15ce971

Browse files
committed
Add shortest_path / all_shortest_paths SRFs
Add two C set-returning functions that compute unweighted (hop-count) shortest paths over the cached global graph adjacency via BFS, callable both at the SQL top level and inside a cypher() RETURN: - age_shortest_path(...) -> the single shortest path (0 or 1 rows) - age_all_shortest_paths(...) -> every shortest path, one per row The signature follows the natural Cypher argument order (graph, start, end, edge_types, direction, min_hops, max_hops), registered in sql/agtype_typecast.sql (install) and age--1.7.0--y.y.y.sql (upgrade). Unimplemented parameters fail loudly: multiple relationship types and a non-zero min_hops raise ERRCODE_FEATURE_NOT_SUPPORTED. A single edge type (string or one-element array) is honored, and a NULL endpoint yields no rows per Cypher null semantics (wrong-typed endpoints / NULL graph still error). To call the SRFs inside a cypher() RETURN, transform_cypher_return now sets query->hasTargetSRFs (it was the only results-producing clause that didn't, so the planner never added a ProjectSet node), and transform_FuncCall auto-prepends the graph name for snake_case shortest_path / all_shortest_paths. camelCase names are reserved for the future native grammar. Robustness: - BFS guards against non-existent endpoints (returns 0 rows instead of crashing) and honors CHECK_FOR_INTERRUPTS. - An unknown edge label now matches no edges instead of silently traversing all of them (get_label_relation returns InvalidOid). Adds the age_shortest_path regression test (directed/undirected, label filtering, parallel edges, self-loops, max_hops, the not-supported stubs, NULL and non-existent endpoint/graph guards). 38/38 installcheck pass. Co-authored-by: Copilot <copilot@github.com> modified: Makefile modified: age--1.7.0--y.y.y.sql modified: sql/agtype_typecast.sql modified: src/backend/parser/cypher_clause.c modified: src/backend/parser/cypher_expr.c modified: src/backend/utils/adt/age_vle.c new file: regress/expected/age_shortest_path.out new file: regress/sql/age_shortest_path.sql
1 parent 581d236 commit 15ce971

8 files changed

Lines changed: 2475 additions & 5 deletions

File tree

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ REGRESS = scan \
201201
cypher_delete \
202202
cypher_with \
203203
cypher_vle \
204+
age_shortest_path \
204205
cypher_union \
205206
cypher_call \
206207
cypher_merge \

age--1.7.0--y.y.y.sql

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,37 @@ CALLED ON NULL INPUT
537537
PARALLEL UNSAFE
538538
AS 'MODULE_PATHNAME';
539539

540+
-- Unweighted (hop-count) shortest path between two vertices, computed over the
541+
-- cached global graph adjacency via BFS. Returns a single path (0 or 1 rows).
542+
-- Argument order mirrors the Cypher shortestPath() pattern
543+
-- (a)-[:type*min_hops..max_hops]->(b):
544+
-- (graph_name, start, end, edge_types, direction, min_hops, max_hops)
545+
CREATE FUNCTION ag_catalog.age_shortest_path(IN agtype, IN agtype, IN agtype,
546+
IN agtype DEFAULT NULL,
547+
IN agtype DEFAULT NULL,
548+
IN agtype DEFAULT NULL,
549+
IN agtype DEFAULT NULL)
550+
RETURNS SETOF agtype
551+
LANGUAGE C
552+
STABLE
553+
CALLED ON NULL INPUT
554+
PARALLEL UNSAFE
555+
AS 'MODULE_PATHNAME';
556+
557+
-- All unweighted shortest paths between two vertices (one path per row).
558+
-- Same argument order as age_shortest_path.
559+
CREATE FUNCTION ag_catalog.age_all_shortest_paths(IN agtype, IN agtype, IN agtype,
560+
IN agtype DEFAULT NULL,
561+
IN agtype DEFAULT NULL,
562+
IN agtype DEFAULT NULL,
563+
IN agtype DEFAULT NULL)
564+
RETURNS SETOF agtype
565+
LANGUAGE C
566+
STABLE
567+
CALLED ON NULL INPUT
568+
PARALLEL UNSAFE
569+
AS 'MODULE_PATHNAME';
570+
540571
--
541572
-- Composite types for vertex and edge
542573
--

0 commit comments

Comments
 (0)