Preserve meaning first
Path mode, row multiplicity, optional matches, missing properties, and traverser state survive the frontend.
Graph query planning for relational data
Crabgraph is a data fusion layer that turns Cypher, Gremlin, and SPARQL into a shared graph plan, then transpiles relational regions into SQL islands. Query the Iceberg tables, warehouse data, and schemas you already have.
Rust · Apache Arrow · built on DataFusion · DuckDB by default
01 CYPHER INPUT
MATCH (p:Person)-[:KNOWS]->(f)
WHERE f.city = 'Chicago'
RETURN p.name, count(f)
02 GRAPH IR
GraphNodeScan:PersonGraphExpand:KNOWS · bothGraphFiltercity = ChicagoGraphAggregateSQL island 0103 DUCKDB SQL
SELECT p.name, count(f.id) …
FROM person p JOIN knows e …
01 / PREMISE
Graph languages express paths, relationships, and traverser behavior well. Relational engines store and scan the data well. Crabgraph keeps those concerns separate.
Instead of flattening a graph query into one large SQL string, the planner preserves graph semantics in Graph IR. It lowers only the regions that have a correct relational equivalent. The rest stays explicit.
02 / BRING YOUR OWN SCHEMA
Keep data in Iceberg, your warehouse, or ordinary relational tables. DuckDB connects to a Polaris catalog, the Iceberg extension reads its tables, and cache_httpfs caches remote object reads. SQL views define the graph shape.
Cypher and Gremlin use node and edge mappings. SPARQL adds an ontology mapping that resolves classes and predicates to those same graph concepts. Every language reaches the same views, with no graph copy and no second source of truth.
01 EXPOSE EXISTING DATA
INSTALL cache_httpfs FROM community;
LOAD cache_httpfs;
INSTALL iceberg; LOAD iceberg;
ATTACH 'warehouse' AS lake (
TYPE iceberg, ENDPOINT 'https://polaris.example/api/catalog'
);
CREATE VIEW graph_accounts AS
SELECT account_id, owner, risk
FROM lake.prod.accounts;
CREATE VIEW graph_transfers AS
SELECT transfer_id, from_id, to_id, amount
FROM lake.prod.transfers;
02 MAP THE GRAPH SHAPE
[node.Account]
table = "graph_accounts"
id = "account_id"
[node.Account.properties]
resource_id = "account_id"
owner = "owner"
risk = "risk"
[edge.TRANSFERRED_TO]
table = "graph_transfers"
src = "from_id" · dst = "to_id"
# Ontology: vocabulary → graph shape
ex:Account → Account(resource_id)
ex:owner → Account.owner
03 QUERY IT AS A GRAPH
MATCH (a:Account)-[t:TRANSFERRED_TO]->(b:Account)
RETURN a.owner, b.owner, t.amount
↓ SQL PUSHDOWN
SELECT a.owner, b.owner, t.amount
FROM graph_accounts a
JOIN graph_transfers t ON t.from_id = a.account_id
JOIN graph_accounts b ON b.account_id = t.to_id
03 / ARCHITECTURE
Frontends and engines meet at a semantic contract, not at a storage format.
LANGUAGES
SEMANTIC CORE
EXECUTION
Path mode, row multiplicity, optional matches, missing properties, and traverser state survive the frontend.
Scans, filters, expands, joins, projections, aggregates, and other relational regions become SQL islands.
Map node labels and edge types onto relational tables. The graph view does not require a new data store.
If the SQL path cannot preserve a value or operation, it falls back instead of returning an approximate answer.
04 / MEASURED COVERAGE
These are development benchmarks from the checked-in corpus notes. They are not standards certifications.
Cypher DuckDB accuracy
62.3%
3,392 / 5,446 runnable cases executed through the relational path and matched expected output.
Ladybug corpus · full denominator · DuckDB · August 2026 snapshot
Cypher relational lowering
88.4%
4,816 / 5,446 runnable cases lowered into relational work for SQL generation.
Ladybug corpus · full denominator · August 2026 snapshot
Gremlin accuracy
95.0%
1,584 / 1,667 runnable interpreter cases matched expected output. The separate DuckDB path matches 578 / 1,667.
TinkerPop corpus · interpreter · August 2026 snapshot
SPARQL Graph IR planning
96.0%
408 / 425 selected W3C query files reached Graph IR. A mapped 6 / 6 integration matrix also matched expected rows in DuckDB.
W3C RDF tests · query collections · August 2026 snapshot
Accuracy compares an execution result with imported corpus output. Relational lowering counts plans that reach relational work for SQL generation. SPARQL planning counts W3C query files that reach Graph IR after parsing. The mapped SPARQL matrix separately checks expected DuckDB rows. The language review records the current Cypher and Gremlin denominators and reproduction commands. The SPARQL benchmark note pins its corpus commit and execution matrix.
| Layer | Capability | Status | Boundary |
|---|---|---|---|
| Frontend | Cypher parser and planner | Available | Broad read coverage; full conformance remains in progress. |
| Frontend | Gremlin parser and planner | Available | Repeat internals, graph algorithms, sack semantics, and meta-properties have known gaps. |
| Frontend | SPARQL parser and planner | Partial | Parsed query algebra reaches Graph IR. Ontology mappings resolve SPARQL vocabulary to node labels, relationships, and properties before SQL lowering. |
| Semantic core | Shared Graph IR | Available | Models scans, expands, paths, joins, aggregation, branching, repetition, and mutations. |
| Foundation | DataFusion logical planning | Available | Crabgraph is built on DataFusion logical plans, extension nodes, and relational optimization. |
| SQL islands | Read-plan partitioning and fallback | Available | Unsupported regions stay in Graph IR. Hybrid execution remains a migration path. |
| SQL islands | Recursive variable-length paths | Partial | Recursive SQL exists; path rendering and remaining correlation shapes still have release gates. |
| Data | Bring your own relational schema | Available | Map nodes and edges onto existing tables, DuckDB views, SQL queries, and Iceberg-backed views. |
| Engine | DuckDB | Available | Default feature and best-tested SQL target. |
| Engine | Postgres | Partial | Executor is feature-gated; compatibility and corpus gates are unfinished. |
| Writes | SQL mutations and transactions | Planned | Create, merge, set, delete, sequence, and transaction lowering remain outside SQL islands. |
| Language | Broader SPARQL algebra | Partial | Filters, optional patterns, named graphs, values, paths, datasets, services, and all query forms plan. Aggregate and reduced algebra still use explicit extension nodes. |
| Language | GQL and additional graph languages | Planned | Graph IR is designed to admit more frontends behind the same semantic boundary. |
05 / ENGINE POSTURE
Crabgraph is built on DataFusion for logical plans, extension nodes, and relational optimization. DuckDB is the best-developed SQL execution target today. The executor boundary can admit other databases as their dialect and behavior gates mature.
This is not a promise that every SQL engine behaves the same. It is a boundary that keeps engine choice separate from graph-language semantics.
PLANNING FOUNDATION CRABGRAPH IS BUILT ON
Logical plans
Extension nodes
Relational optimization
SQL EXECUTION DATABASE TARGETS
06 / SOURCE
Read the planner, map your schema, run the corpus harnesses, or help define the next SQL target.
git clone https://github.com/henneberger/new-graph.git