(
&self,
collection: &str,
from: &NodeId,
to: &NodeId,
max_depth: u8,
edge_filter: Option<&EdgeFilter>,
)
| 174 | } |
| 175 | |
| 176 | pub(super) async fn graph_shortest_path_impl( |
| 177 | &self, |
| 178 | collection: &str, |
| 179 | from: &NodeId, |
| 180 | to: &NodeId, |
| 181 | max_depth: u8, |
| 182 | edge_filter: Option<&EdgeFilter>, |
| 183 | ) -> NodeDbResult<Option<Vec<NodeId>>> { |
| 184 | // Use the server's `GRAPH PATH` operator instead of the trait |
| 185 | // default's per-hop BFS — one round-trip vs O(path_length). |
| 186 | // Like `graph_traverse`, the Origin graph overlay is |
| 187 | // tenant-scoped, so `collection` is accepted for symmetry but |
| 188 | // not threaded into the DSL. |
| 189 | let _ = collection; |
| 190 | let label_clause = edge_filter |
| 191 | .and_then(|f| f.labels.first()) |
| 192 | .map(|l| format!(" LABEL {}", quote_string_literal(l))) |
| 193 | .unwrap_or_default(); |
| 194 | let from_s = quote_string_literal(from.as_str()); |
| 195 | let to_s = quote_string_literal(to.as_str()); |
| 196 | let sql = format!("GRAPH PATH FROM {from_s} TO {to_s} MAX_DEPTH {max_depth}{label_clause}"); |
| 197 | |
| 198 | let (_columns, rows) = self.simple_query_raw(&sql).await?; |
| 199 | // Server emits a single `result` column carrying a JSON array |
| 200 | // of node ids — empty array means unreachable. |
| 201 | let Some(row) = rows.first() else { |
| 202 | return Ok(None); |
| 203 | }; |
| 204 | let Some(Value::String(json_text)) = row.first() else { |
| 205 | return Ok(None); |
| 206 | }; |
| 207 | let parsed: Vec<String> = sonic_rs::from_str(json_text) |
| 208 | .map_err(|e| NodeDbError::storage(format!("graph shortest path response: {e}")))?; |
| 209 | if parsed.is_empty() { |
| 210 | return Ok(None); |
| 211 | } |
| 212 | Ok(Some( |
| 213 | parsed |
| 214 | .into_iter() |
| 215 | .map(NodeId::from_validated) |
| 216 | .collect::<Vec<_>>(), |
| 217 | )) |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | /// Build the SQL for `SHOW GRAPH STATS`. Collection and `as_of` are both |
no test coverage detected