Supported subset
NamiDB’s query layer implements a strict subset of Cypher 25 / openCypher 9 / GQL ISO/IEC 39075:2024, scoped to make LDBC SNB Interactive Complex Read IC01–IC14 parse, plan and run end to end. The subset is deliberately smaller than Neo4j Community 5.x or Kùzu; the trade is “what the parser accepts runs or returns a typed error — never a silent warning that changes semantics.”
When in doubt, an unsupported feature produces an explicit
UnsupportedFeature error pointing at the RFC where it will land.
Standard reference
- Base standard: GQL ISO/IEC 39075:2024 plus openCypher 9.
- Cypher 25 (Neo4j) is used as a naming reference but no
Neo4j-exclusive features are implemented (no
db.*functions, no APOC). - When GQL and openCypher disagree, GQL wins.
See RFC-004 for the full scoping document.
Clauses
| Clause | Supported | Notes |
|---|---|---|
MATCH | yes | Fixed and variable-length patterns. |
OPTIONAL MATCH | yes | Left-outer-join semantics. |
WHERE | yes | Arbitrary predicates over the visible scope. |
RETURN | yes | Projection list with AS aliases. DISTINCT supported. |
RETURN * | yes | All bound aliases. |
WITH | yes | Pipe that re-opens scope. Supports inline WHERE and AS. |
WITH * | yes | All bound aliases (pipeline pass-through). |
ORDER BY | yes | Multi-key ASC / DESC. |
SKIP / LIMIT | yes | Literals or $param; no expressions. |
UNWIND | yes | List → rows. |
CREATE | yes | Nodes and edges with literal or $param properties. |
MERGE | yes | With ON CREATE SET / ON MATCH SET. Single pattern part per MERGE (no multi-label). |
SET | yes | Property assign, property replace (=), property merge (+=), label add. |
DELETE / DETACH DELETE | yes | Single binding per delete. DELETE without DETACH fails if the node has edges. |
REMOVE | yes | Property remove, label remove. |
UNION / UNION ALL | yes | Same arity and same aliases on each side. |
shortestPath(...) | yes | Wrapped form MATCH p = shortestPath((a)-[*..N]-(b)). Path binding required, single hop, finite upper bound. |
allShortestPaths(...) | yes | Same shape as shortestPath; emits every distinct path of the minimum length. |
Patterns
| Element | Supported | Notes |
|---|---|---|
(a:Label {prop: val}) | yes | Multi-label (a:A:B). Inline map property filter. |
-[r:TYPE]-> | yes | Directions -->, <--, --. |
Relationship type alternation -[r:A|B|C]-> | yes | Union over the listed types (RFC-024). |
Variable-length -[r:KNOWS*1..3]-> | yes | Finite bounds required. *..M is shorthand for *1..M. |
Pattern chain (a)-[]-(b)-[]-(c) | yes | |
Multi-part pattern MATCH (a), (b) | yes | |
Anonymous variable (), [] | yes |
Expressions
| Category | Supported |
|---|---|
Literals: int, float, string, bool, null, list [1,2,3], map {k: v} | yes |
Parameters $name | yes |
Variable reference a, property access a.prop | yes |
Arithmetic + - * / % ^ | yes |
String + (concat), =~ (regex) | yes |
Boolean AND OR NOT XOR | yes |
Comparison = <> < > <= >= | yes |
IS NULL / IS NOT NULL | yes |
IN (list membership) | yes |
STARTS WITH, ENDS WITH, CONTAINS | yes |
CASE WHEN … THEN … ELSE END (simple and multi-branch) | yes |
List comprehension [x IN list WHERE pred | expr] | yes |
Pattern comprehension [(a)-[]->(b) | b.name] | yes |
Pattern predicate WHERE (a)-[]->(b) / EXISTS { ... } | yes |
Types
INTEGER (64-bit signed), FLOAT (64-bit), STRING, BOOLEAN,
NULL, LIST<T> (heterogeneous allowed, typecheck at runtime),
MAP<STRING, T>, NODE, RELATIONSHIP, PATH, DATE, DATETIME
(UTC, microseconds), DURATION, VECTOR(Vec<f32>).
Out of scope in v0: BYTES, POINT, LOCALDATETIME,
ZONEDDATETIME, LOCALTIME, TIME.
NULL semantics
Three-valued logic:
NULL = NULL→NULL(nottrue).NULL AND false→false;NULL AND true→NULL.WHERErejects rows whose predicate evaluates toNULL(treated asfalse).IS NULL/IS NOT NULLare the only forms that test forNULL.
LDBC SNB Interactive Complex coverage
| Query | v0 |
|---|---|
| IC1 — Friends by name (transitive) | yes |
| IC2 — Recent messages by friends | yes |
| IC3 — Friends in two countries | yes |
| IC4 — New topics on friend posts | yes |
| IC5 — New groups (membership count) | yes |
| IC6 — Tag co-occurrence | yes |
| IC7 — Recent likers | yes |
| IC8 — Recent replies | yes |
| IC9 — Recent messages by friends-of-friends | yes |
| IC10 — Friend recommendation | yes |
| IC11 — Job referral | yes |
| IC12 — Expert search by tag class | yes |
| IC13 — Single shortest path | yes (RFC-023) |
| IC14 — All shortest paths weighted | yes (RFC-023) |
All 14 IC queries parse, lower and run end to end on the current main branch.
Out of scope (v0)
Anything not listed above is explicitly out of scope and produces a typed parse / lower error. Notable exclusions:
| Feature | Why it’s out | Where it lands |
|---|---|---|
CALL { ... } (subqueries) | Subquery scoping is subtle; not needed for LDBC IC. | Future RFC |
CALL procedure.name(...) | No procedure registry. APOC explicitly excluded. | Future RFC |
FOREACH | Imperative; rarely useful in practice. | Future RFC |
USE database | Cross-database queries; single namespace per session. | RFC for Cloud |
LOAD CSV | Bulk-load happens through WriterSession / merge_nodes. | Never via Cypher in v0. |
CREATE INDEX / CREATE CONSTRAINT | DDL handled by the schema API, not Cypher. | Future RFC |
EXPLAIN / PROFILE (as Cypher prefix) | Available via the CLI namidb explain. | Future RFC |
Explicit transactions (BEGIN/COMMIT/ROLLBACK in Cypher) | Auto-commit per query in v0. | Never via Cypher in v0. |
Variable-length without an upper bound (*1..) | Blowup not bounded; rejected explicitly. | Possible with WCOJ. |
Zero-length patterns (*0..n) | Semantics around auto-loops not finalised. | Future RFC |
MATCH p = (a)-[*]->(b) RETURN p (var-length path bindings) | Path materialisation deferred. | Future RFC |
POINT, TIME, ZONEDDATETIME types | Not needed for LDBC SNB Interactive. | Future RFC |
db.* / apoc.* namespaces | Vendor-specific Neo4j; non-portable. | Never |
Read-your-own-writes
In v0, a single query that writes then reads does not see its own writes. Example:
CREATE (a:Person {name: 'Ada'})MATCH (p:Person) RETURN p.nameThe MATCH sees the snapshot pinned before the CREATE ran. The new
Ada appears in the next query. Workaround: run writes and reads in two
separate statements (or two separate Client.cypher calls — Cypher
writes auto-commit at the end of each statement).
See RFC-009 for the rationale.
What’s next
- Reading data — read clauses with examples.
- Writing data — write clauses and the auto-commit model.
- Operators & functions — the full operator and built-in function catalog.