Cypher, GQL and SQL#

AgensGraph answers questions in three languages. They are not three products, three modes or three connections. There is one parser, one planner, one set of tables, and one wire protocol, and you choose per statement — or mix two in one statement.

Cypher is the graph language, and the most complete surface. Everything the graph can do is reachable from Cypher.

GQL is ISO/IEC 39075, the standard graph query language. In AgensGraph it is not a separate dialect. The GQL statements are accepted wherever a Cypher statement is accepted: LET, NEXT, FILTER, FINISH, INSERT, FOR, CALL { }, and the subquery value expressions EXISTS { } and VALUE { }. There is no switch to flip and no separate parser. GQL conformance records which parts of the standard are in.

SQL is PostgreSQL’s, unchanged. Every table, view, function, extension, role and transaction you know from PostgreSQL is here, and a graph is visible to SQL as ordinary tables.

Choosing#

Pick by the shape of the question, not by preference:

  • Following relationships — how a person connects to a film, how far apart two films are, what is reachable in three hops — is what a graph pattern is for. A join chain in SQL says the same thing at several times the length, and cannot express “any number of hops” at all.

  • Aggregating, windowing, set operations, joining against ordinary tables, and anything administrative is SQL’s, and Cypher does not try to replace it.

  • GQL where you want the standard’s spelling, or where you are writing against more than one graph database and want the portable form. INSERT and CREATE do the same work; FILTER and WHERE do the same work.

You do not have to choose once. Combining SQL and Cypher is a full page on the crossing points, and it is the most useful thing in this manual for a reader who already knows SQL.

If you know SQL#

The vocabularies line up more closely than the syntax suggests, because a graph is a schema and a label is a table:

SQL

Cypher

Note

CREATE SCHEMA s

CREATE GRAPH s

The graph is the schema.

CREATE TABLE t

CREATE VLABEL t

A vertex label. CREATE ELABEL for edges.

INSERT INTO t VALUES (…)

CREATE (:t {…})

INSERT (:t {…}) is the GQL spelling.

SELECT … FROM t WHERE …

MATCH (n:t) WHERE … RETURN …

RETURN is the projection, and it comes last.

SELECT … FROM a JOIN b ON …

MATCH (a)-[:e]->(b)

A pattern is a join along an edge.

LEFT JOIN

OPTIONAL MATCH

Unmatched rows come back with nulls.

UPDATE t SET c = …

MATCH (n:t) SET n.c = …

Find first, then write.

DELETE FROM t WHERE …

MATCH (n:t) WHERE … DELETE n

DETACH DELETE removes the edges too.

WITH cte AS (…)

WITH … / NEXT

Cypher’s WITH divides a pipeline; it is not a CTE.

ORDER BY / LIMIT / OFFSET

ORDER BY / LIMIT / SKIP

SKIP and OFFSET are synonyms.

CREATE INDEX ON t ((c))

CREATE PROPERTY INDEX ON t (c)

Becomes an expression index.

count(*), sum, avg

the same

Aggregates are PostgreSQL’s.

information_schema, pg_catalog

ag_graph, ag_label

See System catalogs.

Three differences catch SQL users early, and all three are silent rather than loud:

A property read returns jsonb, not text. RETURN m.title prints "The Matrix" with the quotes, and casting inside the query does not change it. To get a plain scalar, unwrap it outside: SELECT t #>> '{}' FROM (MATCH (m:movie) RETURN m.title AS t) q.

ORDER BY 2 does not mean “the second column”. In Cypher the 2 is a constant, so every row compares equal and nothing sorts. Order by the alias or the expression.

n.id is not the id. id(n) returns the graphid; n.id looks for a property called id and returns nothing if there isn’t one.

One statement, two languages#

A Cypher query can appear where SQL expects a table:

SELECT q.title #>> '{}' AS film, r.score
FROM (MATCH (:person {name: 'Christopher Nolan'})-[:directed]->(m:movie)
      RETURN m.title AS title) q
JOIN rating r ON r.title = q.title #>> '{}'
WHERE r.source = 'critics'
ORDER BY r.score DESC;
     film     | score
--------------+-------
 Inception    |   8.8
 Interstellar |   8.7

And SQL can appear where Cypher expects a value:

MATCH (m:movie)
WHERE m.title = (SELECT to_jsonb(title) FROM rating
                 WHERE source = 'critics' ORDER BY score DESC LIMIT 1)
RETURN m.title AS best;
    best
-------------
 "Inception"

Both of those run against the example dataset.

What “GQL support” means in this release#

GQL arrived in AgensGraph as added statements on the existing grammar rather than as a second language, which has two consequences worth stating plainly.

A GQL statement can be mixed with Cypher in one query — MATCH … LET … RETURN is a valid statement, and so is MATCH … FILTER … NEXT RETURN …. Nothing marks a query as “GQL”.

And conformance is partial, by feature rather than by mode. GQL conformance lists it feature by feature against the subclauses of ISO/IEC 39075:2024, and each clause page in the reference repeats the same statement for that clause under its own Compatibility heading.