Skip to content

Storage: introduce GraphPath, drop EntityList - #1186

Open
rjb32 wants to merge 2 commits into
mainfrom
graph-path
Open

rjb32 wants to merge 2 commits into
mainfrom
graph-path

Conversation

@rjb32

@rjb32 rjb32 commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Represent every path, named or shortest, as one GraphPath.

@rjb32

rjb32 commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Note

AI-generated summary.

Summary

Architecture after this change: db.make_path and db.shortest_path both yield !storage.path over GraphPath; EntityList, the Path alias and !storage.entity_list are removed; the encoders, decoder and clients read GraphPath

A named path and a shortest path held the same thing in two types. Now there is one type for a whole path and one for a walk in flight.

 storage type                                    IR type                 produced by
-EntityList  {EntityType, EntityID}[]            !storage.entity_list    db.make_path
-Path        vector<EntityID>, target first      !storage.path           db.shortest_path
+GraphPath   nodes[], edges[], source first      !storage.path           db.make_path, db.shortest_path
 PathRef     handle into the PathTrie            !storage.path_ref       db.explore_paths

A GraphPath holds one node more than edges. A path with no node is the null path an OPTIONAL MATCH binds.

 enum class ColumnInternalKind : uint32_t {
     BOOL,                 // 4
-    PATH,                 // 5
-    EMBEDDING,            // 6
-    ENTITY_LIST,          // 7
-    LIST_VIEW,            // 8
+    EMBEDDING,            // 5
+    LIST_VIEW,            // 6
     ...                   // every later kind moves down by 2
-    DURATION,             // 23
+    DURATION,             // 21
+    GRAPH_PATH,           // 22: [nodeCount][nodes][edges]
 };

Evidence

  • Before: MATCH (a {name: 'A'}), (b {name: 'C'}) SHORTESTPATH(a, b, weight, d, p) RETURN d, p → 3 | 2, 2, 1, 0, 0, target first with no node/edge tags. nodes(p) from Adam to Ghosts → 6, 0, 1.
    After: 3 | (0), [0], (1), [2], (2), the same rendering a named path already had. nodes(p) → 1, 0, 6, relationships(p) → 4, 1.
  • New TuringProtoRoundTripTest.RoundTripsGraphPathColumnsAcrossChunkSizes: a null path, a zero-length path and a 40-hop path, at chunk sizes 48, 64, 97 and 256, so a resume lands inside the nodes, between nodes and edges, and inside the edges. Passes.
  • ctest: 884/884 passed.
  • ctest -R test_net after the renumbering: 18/18 passed.
  • Not run: the wasm module, because this machine has no emcc. node --check passes on TuringClient.mjs, client_smoke.mjs and decoder_smoke.js.

Merge Danger

Door: one-way once released

PATH (5) and ENTITY_LIST (7) are deleted and every later wire kind moves down by 2, with GRAPH_PATH added at 22. A client and server on different sides of this PR read almost every column type wrongly, not just paths, so they have to be released together. Reverting the code is easy. Reverting a released wire format is not.

Blast Radius: clients

  • JSON shortestPath output changes from [0,1,6] to [{"type":"node","id":0},{"type":"edge","id":1},{"type":"node","id":6}].
  • The Python column type name of a named path changes from "EntityList" to "Path".
  • The shell renders every path as (0), [1], (6), not (0)-[1]->(6). The shortest path docs are updated to match.
  • DISTINCT over a shortest path used to throw and now works.

Comment thread net/decoders/TuringProtoDecoder.h Outdated
@rjb32
rjb32 requested a review from sulaimansuhas October 23, 2026 12:35

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant