Commit 4ff702b
committed
Support relationship-type filters and a minimum hop count
Support relationship-type filters and a minimum hop count in shortest_path SRFs
age_shortest_path / age_all_shortest_paths gain two related capabilities,
both following openCypher / Neo4j semantics.
Relationship-type filtering: the edge_types argument now accepts an array
of types; an edge matches when its label is any one of the requested
types. A bare string or a one-element array keeps the single-type
behaviour, an empty string/array or NULL means no filter, and an unknown
type matches nothing. sp_run_bfs takes an Oid set rather than a single
oid, and sp_compute_paths resolves the argument into that set.
Minimum hop count: the new min_hops argument is a lower bound on the path
length. When it does not exceed the true shortest distance it imposes no
constraint, so the normal BFS shortest-path result is returned. When it
exceeds the shortest distance, BFS cannot produce a qualifying path, so
the search falls back to the variable-length-edge depth-first engine
(sp_minhops_fallback), which enumerates edge-distinct paths
(relationship-uniqueness / trail semantics) and returns the shortest
path(s) whose length is at least min_hops. This regime permits revisiting
a vertex and closed walks back to the start, but never reusing an edge. A
private memory context bounds the search and a cost guard caps the number
of examined paths, raising PROGRAM_LIMIT_EXCEEDED (with a hint to bound the
search with a maximum hop count) when the cap is exceeded. The hard regime
combined with multiple relationship types is unsupported, because the VLE
engine matches a single label; that case raises FEATURE_NOT_SUPPORTED.
Regression coverage spans single- and multi-type filters, directed and
undirected reachability, multiplicity of equal-length paths, max_hops
bounds, NULL and non-existent endpoints, and both min_hops regimes,
including a vertex-revisiting longer path (sp_revisit) and a closed-walk
cycle back to the start (sp_tri). The in-cypher() Tier 1 call forms are
exercised as well.
Review feedback addressed:
1. Error messages now report the function actually called. age_shortest_path
and age_all_shortest_paths share their argument-resolution helpers, which
hard-coded an "age_shortest_path" prefix regardless of the caller; the
caller's name is now threaded through so each function reports its own
(this also corrects a mislabeled multi-type min_hops error). A new
regression case (sp_errname) pins the behaviour for both functions.
2. age_all_shortest_paths now bounds the number of materialized result paths.
The shortest-path DAG can contain exponentially many equal-length paths,
all built up front before the first row streams; enumeration is capped at
SP_MAX_RESULT_PATHS (1,000,000), raising PROGRAM_LIMIT_EXCEEDED with a hint
to narrow the search, mirroring the existing min-hops candidate cap.
3. The BFS search state (visited table, frontier queue, predecessor multiset,
and intermediate path arrays) now lives in a private scratch memory context
that is deleted once the surviving result Datums are built in the SRF
context, rather than persisting in multi_call_memory_ctx for the life of
the SRF. This bounds peak memory to the result set plus one search and
matches the pattern sp_minhops_fallback already used.
41/41 installcheck.
Co-authored-by: Copilot <copilot@github.com>
modified: regress/expected/age_shortest_path.out
modified: regress/sql/age_shortest_path.sql
modified: src/backend/utils/adt/age_vle.c
modified: regress/expected/age_shortest_path.out1 parent 2bc8e95 commit 4ff702b
3 files changed
Lines changed: 1607 additions & 67 deletions
0 commit comments