GQL (ISO/IEC 39075)

Traverse implements the full GQL standard - the ISO graph query language - alongside openCypher. Select the dialect per query; both run on the same engine, the same data, and return identical result shapes.

Conformance

Traverse 0.8.0 reaches 100% ISO/IEC 39075 conformance: all 40 mandatory features (§24.2) and all 60 optional GQL feature IDs. That includes quantified path patterns, path search prefixes (SHORTEST k, ANY, ALL), path modes (WALK, TRAIL, ACYCLIC), composed queries (NEXT, WHEN / THEN), FILTER / LET / FOR statements, INSERT, typed temporal literals, dynamic union value types, and the standard GQL-status error envelope.

A GQL query

MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
FILTER m.released > 2000
LET decade = (m.released / 10) * 10
RETURN p.name AS actor, decade
ORDER BY actor

GQL and Cypher share most of their surface - MATCH, WHERE, RETURN, expressions - so many queries run unchanged in either dialect. GQL-specific spellings (FILTER, LET, FOR, INSERT, NEXT, IS INTEGER type predicates, || concatenation) parse through the ISO grammar with ISO semantics.

Selecting the dialect

HTTP API

Send the X-Query-Dialect: gql header (or "dialect": "gql" in the JSON body; the header wins when both are present):

POST /api/query
Authorization: Bearer tvs_...
X-Query-Dialect: gql

{"query": "MATCH (n:Person) FILTER n.age > 30 RETURN n.name AS name"}

Studio

The query editor's Dialect picker switches between openCypher and GQL, with GQL syntax highlighting. It appears whenever the connected server (or the in-browser WASM engine) supports GQL.

Embedded SDKs

# Python
tx.execute("MATCH (n:Person) FILTER n.age > 30 RETURN n.name", dialect="gql")

// Node.js
tx.execute("INSERT (n:Person {age: 42})", null, 'gql')

// Java
tx.execute("MATCH (n:Person) FILTER n.age > 30 RETURN n.name", null, "gql");

// Go
res, err := tx.ExecuteGql("MATCH (n:Person) RETURN n.name")

// C# (.NET)
using var res = tx.QueryGql("MATCH (n:Person) FILTER n.age > 30 RETURN n.name");

HTTP clients

Every management client takes a dialect option on its query call - the literal string "gql":

# Python
client.query("MATCH (n) RETURN count(*) AS c", dialect="gql")

// Node.js - query(cypher, parameters, database, dialect)
await client.query("MATCH (n) RETURN count(*) AS c", null, null, "gql")

// Go
res, err := client.QueryDialect("MATCH (n) RETURN count(*) AS c", nil, "", "gql")

// Java - query(cypher, parameters, database, dialect)
client.query("MATCH (n) RETURN count(*) AS c", null, null, "gql");

// C# (.NET)
await client.QueryAsync("MATCH (n) RETURN count(*) AS c", dialect: "gql");

Browser (WASM)

const r = await db.query(query, null, { dialect: 'gql' })

Detecting GQL support

The server advertises compile-time features in GET /api/health:

{"features": {"gql": true, "grpc": true, "tls": true, "mcp": true, "ml": true}}

The gql feature is on by default in release builds. A server built without it answers GQL requests with an error explaining how to rebuild.

Where GQL is not available

  • Bolt - the Bolt protocol has no dialect switch; queries over Bolt (including the third-party Neo4j drivers and the CLI) are openCypher. Use the HTTP API, the embedded SDKs, or Studio for GQL.
  • gRPC - openCypher only in this release.
  • Catalog statements in embedded sessions - CREATE GRAPH / CREATE SCHEMA operate on the server's database registry; in an embedded (single-graph) session they return a clear "not supported" error.

Errors

GQL parse and runtime errors carry the ISO GQL-status envelope (standard error codes), and dialect-specific diagnostics: an invalid GQL query reports the GQL grammar's expectations, so a mis-typed query never falls through to the Cypher parser silently.