# MemGQL Changelog

## MemGQL v0.12.0 - September 14th, 2026

### ⚠️ Breaking changes

- **`SHOW STATS` is now `SHOW STATS CONNECTORS`,** and its first column is
  `connector` rather than `source`. Bare `SHOW STATS` returns the list of
  targets instead of the per-connector table. `RESET STATS` is unchanged.
- **`SHOW LICENSE` reports only the license.** Its rows are `offering`
  (`community` or `enterprise`), `status` (`valid`, `expired` or
  `unsupported`), `organization`, `valid_until`, `days_left`, `limit.max_cores`,
  `limit.max_connectors` and `limit.max_connections`; numbers come back as integers,
  not strings. The old `mode`, `core_limit`, `max_connectors` and
  `max_connections` keys are renamed as above, `license_type` is dropped, and
  the `compute_*` / `host_cores` rows moved to `SHOW CONFIG` and
  `SHOW STATS COMPUTE`.
- **`SHOW CONNECTORS` gains a `connections` column** — open connections per
  connector — after `graph`.

### 🍃 New features & Improvements

- **License core limit.** A license may carry a core limit. MemGQL then sizes
  its query workers, the embedded DuckDB engine and the native Iceberg runtime
  to it, and at most that many queries do in-process compute at once. When
  every core is busy a query waits up to `MEMGQL_COMPUTE_QUEUE_TIMEOUT_MS` for
  a free one, then fails with `Compute limit reached` and can be retried.
  Community mode is capped at 2 cores. `MEMGQL_COMPUTE_CORES` lowers the
  budget further but never raises it. See
  [Compute](https://memgraph.com/docs/memgraph-zero/memgql/reference#compute).
- **`SHOW CONFIG`.** The server's effective settings as `name`/`value` rows:
  the compute budget (`compute.cores`, `compute.host_cores`,
  `compute.queue_timeout_ms`), server flags (`server.default_language`,
  `server.log_level`, `server.schema_file`, …) and the license inputs, key
  masked.
- **`SHOW STATS COMPUTE`.** Live compute counters — cores busy, queued, peak
  and refused, queries in flight, the server's own CPU time — as typed
  key/value rows, in every connector mode. Bare `SHOW STATS` lists the
  available targets.
- **Composite keys.** `metaFields.id`, `from` and `to` accept a list of
  columns (`"id": ["region", "order_no"]`) on every SQL backend. Edges join column
  by column at the source; `RETURN n`, `WITH n` and `count(DISTINCT n)` treat
  the tuple as one identity. `EXPORT SCHEMA` round-trips the list form. See
  [Schema file](https://memgraph.com/docs/memgraph-zero/memgql/schema-file#edges).
- **SQL Server views across databases.** `mappedTableSource.database` renders a
  three-part `database.schema.object` name, so one connection reaches views in
  other databases of the instance.
- **SQL Server lock hints.** `NoLock=true` in the connection string puts
  `WITH (NOLOCK)` on every table MemGQL reads; `IsolationLevel=<level>` sets the
  session isolation level once. See
  [SQL Server](https://memgraph.com/docs/memgraph-zero/memgql/connect/sqlserver).
- **Memgraph databases from the schema file.** On a `memgraph` or `neo4j`
  connector, `connection.database` selects the Bolt database — the same thing
  `ADD CONNECTOR … GRAPH <db>` selects at runtime — so one Memgraph Enterprise
  instance can back several connectors, one per tenant. `EXPORT SCHEMA` writes
  a runtime `GRAPH` selector back as `database`, so an exported schema
  reconnects to the same database. See
  [Schema file](https://memgraph.com/docs/memgraph-zero/memgql/schema-file#connectors).

### 🐞 Bug fixes

- **SQL Server dates.** `date`, `datetime`, `datetime2`, `smalldatetime` and
  `datetimeoffset` columns come back as ISO-8601 text (`2026-01-12`,
  `2026-01-12T08:05:00-05:00`) instead of an internal representation.
- **Whole-node results with string keys.** `RETURN n` for a node whose key is a
  string column, or a composite key, reaches Bolt clients as a Node with an
  integer id; it used to fail the connection with a wire error on every SQL
  backend.

## MemGQL v0.11.0 - September 2nd, 2026

### 🍃 New features & Improvements

- **Cypher queries.** MemGQL speaks Cypher alongside GQL: per query with the
  Neo4j-style `CYPHER [25]` prefix, per session with
  `SET SESSION LANGUAGE CYPHER`, per connector with `LANGUAGE 'cypher'`, or
  server-wide with `--default-language`. On Memgraph/Neo4j the text executes
  **verbatim** — an existing corpus keeps working unchanged, `CALL`
  subqueries, pattern predicates and all; on every other backend the same
  Cypher runs through the regular plan/translation path. The default stays
  GQL. See [Query languages](https://memgraph.com/docs/memgraph-zero/memgql/reference#query-languages).
- **Read-only graphs.** `"accessMode": "readOnly"` (schema file) or
  `ALTER GRAPH <name> SET READ ONLY` refuses any write to that graph before a
  backend sees it. The flip persists to the boot `--schema` file, so a
  restart cannot quietly reopen a replica. See
  [Access modes](https://memgraph.com/docs/memgraph-zero/memgql/reference#access-modes).
- **Source onboarding through the engine.** `DESCRIBE CONNECTOR` reads a
  source's live catalog — tables, columns, types, keys (PostgreSQL, SAP
  HANA); `GENERATE MAPPING FOR CONNECTOR … [TO '<path>']` turns it into a
  draft mapping (tables → vertices, foreign keys → edges) for review —
  loading stays explicit, and anything unrepresentable is named in
  `_comment`. See
  [Onboarding a source](https://memgraph.com/docs/memgraph-zero/memgql/reference#onboarding-a-source).
- **The schema is a graph.** `SHOW SCHEMA [FOR <graph>] AS GRAPH` returns the
  merged schema as Bolt nodes and relationships (cross-connector join edges
  marked), so agents plan federated queries by navigating it and graph UIs
  draw it. `EXPORT SCHEMA` now round-trips join edges and `accessMode`.

## MemGQL v0.10.0 - August 16th, 2026

### 🍃 New features & Improvements

- **Cross-connector edges.** An edge declared with
  `mappedJoinSource { "fromKey": …, "toKey": … }` links two labels in *different*
  backends, so one pattern traverses the boundary:
  `MATCH (c:Component)-[:MANUFACTURED_BY]->(m:Manufacturer)` reads components from
  PostgreSQL and manufacturers from Memgraph. `RETURN c, r, m` packs real nodes and
  a relationship, so graph clients can draw and expand the result. See
  [Cross-connector edges](https://memgraph.com/docs/memgraph-zero/memgql/schema-file#cross-connector-edges).
- **JSON / JSONB columns are queryable.** An attribute can declare a `path` into a
  document column (`"column": "props", "path": "electrical.voltage", "type": "Double"`),
  giving it its own typed property; or type the column `Json`, which returns it as a
  map and keeps *undeclared* keys reachable as `c.props.rohs`. Both push the
  extraction down to the source, and a declared type keeps comparisons numeric
  rather than lexicographic. PostgreSQL, MySQL, DuckDB, SQL Server, Microsoft
  Fabric and Snowflake. See
  [JSON / JSONB columns](https://memgraph.com/docs/memgraph-zero/memgql/schema-file#json--jsonb-columns).
- **TLS for PostgreSQL connections.** The mode stays in the URI (`sslmode=`, libpq
  semantics); the connector adds `sslRootCert` (PEM bundle to trust instead of the
  system roots) and `trustServerCertificate` (encrypt without verifying the server).
  Built on rustls, so there's no OpenSSL to install. Declaring TLS settings
  alongside `sslmode=disable` is refused rather than silently connecting in
  plaintext. See
  [TLS connections](https://memgraph.com/docs/memgraph-zero/memgql/connect/postgres#tls-connections).
- **`SHOW STATS` reports query load per source.** One row per connector —
  `queries`, `rows`, `errors`, `avg_latency_ms`, `max_latency_ms` — counting what
  the source itself saw, so federation's impact on a production backend can be
  measured. `RESET STATS` zeroes the counters. See
  [Load per source](https://memgraph.com/docs/memgraph-zero/memgql/multiple-graphs#load-per-source).
- **SAP HANA connector.** `ADD CONNECTOR … TYPE hana URI 'hdbsql://host:39017'`
  brings SAP HANA 2.0, HANA Cloud and HANA Express into the federation, reads and
  writes both, over a **pure-Rust** driver — no ODBC, no JDBC, no SAP client
  installation. TLS is chosen by the URL scheme (`hdbsqls://`), so HANA Cloud
  needs nothing beyond the `s`. A mapping written for PostgreSQL works against
  HANA unchanged. See
  [Connect to SAP HANA](https://memgraph.com/docs/memgraph-zero/memgql/connect/hana).

## MemGQL v0.9.0 - August 9th, 2026

### 🍃 New features & Improvements

- **Microsoft Fabric connector.** New `fabric` connector type translates GQL to
  T-SQL over a Fabric Warehouse's SQL endpoint — a pure-Rust driver, so there's no
  ODBC layer to install. The same connector also reaches Lakehouse SQL analytics
  endpoints, SQL databases in Fabric, and mirrored databases, which need no
  connector of their own. It uses the same
  [mapping](https://memgraph.com/docs/memgraph-zero/memgql/reference#mapping-schema) format as every other
  SQL backend, references tables with three-part `item.schema.table` names — so one
  query can join across items in a workspace — and supports **both reads and
  writes**. Authenticate with a Microsoft Entra ID access token or a service
  principal. Variable-length paths are rejected, since Fabric has no recursive
  queries. See the
  [Microsoft Fabric connector page](https://memgraph.com/docs/memgraph-zero/memgql/connect/fabric) for setup.

- **MongoDB connector.** New `mongodb` connector type brings a document store into
  the federation — the first backend that is neither SQL nor Cypher. Queries
  translate to **MongoDB aggregation pipelines** and run server-side: a single hop
  becomes `$lookup`, a variable-length hop `$graphLookup`, so unlike the SQL
  backends the unbounded `*` form works too. Labels map to collections and
  relationship types to their own collections, using the same
  [mapping](https://memgraph.com/docs/memgraph-zero/memgql/reference#mapping-schema) format as every other
  backend, and **both reads and writes** are supported, including `DETACH DELETE`.
  Connect with a standard connection string, so replica sets and MongoDB Atlas work
  as-is; `UNION` and scalar functions inside `RETURN` are the notable gaps. See the
  [MongoDB connector page](https://memgraph.com/docs/memgraph-zero/memgql/connect/mongodb) for setup.

### ⚠️ Behavior changes

- **A vertex's or edge's `metaFields.id` is now exposed as a property.** `RETURN n`
  / `RETURN r` include it, and `n.<id_column>` reads it by name — including after a
  `WITH n` boundary, which previously worked only when the column was called `id`.
- **The cache answers only for properties it holds.** A fragment holds a label's id
  and its declared `attributes`; a query reading anything else misses and reads the
  source, so results never differ from the uncached run. `SHOW GRAPH CACHES` gained
  `hits`, `misses` and `cached_properties` columns. See
  [Caching a graph in Memgraph](https://memgraph.com/docs/memgraph-zero/memgql/multiple-graphs#caching-a-graph-in-memgraph).

### 🐞 Bug fixes

- **ClickHouse returned result columns in alphabetical order** rather than the order
  the query projected them. Names travelled with their values, so most clients were
  unaffected — but anything reading positionally was not.
- **The Memgraph cache returned different rows than its source.** Cached edges
  pointed at the wrong endpoints or were missing, edge properties were never copied,
  and a cache holding only a label's id answered property reads with `NULL`.
- **`count(DISTINCT <node>)` and `count(DISTINCT <relationship>)` produced invalid
  SQL** on relational backends. Counting distinct properties was unaffected.
- **Grouping by a whole element produced invalid SQL** — `WITH n, count(…)` and
  `WITH r, count(…)` on relational backends.
- **A warm table was re-scanned from the source** whenever a newly-touched edge type
  pulled it in as an endpoint.
- **The cache's warm-up log counted rows read from the source**, reporting success
  even when no rows reached the cache.

## MemGQL v0.8.0 - July 19th, 2026

### ⚠️ Breaking changes

- **New graph model: connectors + schema graphs.** A **connector** is now a pure
  connection and a **graph** is a mapping (`vertices` + `edges`) laid over one or
  more connectors. Register a connection with `ADD CONNECTOR`, then define a graph
  with `CREATE GRAPH <name> FROM '<json>'` / `FROM FILE '<path>'`, or boot the
  whole catalog from a single [`--schema`](https://memgraph.com/docs/memgraph-zero/memgql/schema-file) file.
- **New mapping format.** Mappings use `vertices` / `edges` with
  `mappedTableSource` (relational) or `mappedGraphSource` (native), `metaFields`
  (`id` / `from` / `to`), and `attributes`. The legacy `nodes` / `edges` format
  (`id_column`, `source_label`, `rel_type`) is no longer accepted; loading it
  raises an actionable error pointing at the new format.
- **Removed statements.** `ADD GRAPH … ON CONNECTOR`, `UNADD GRAPH`,
  `ALTER GRAPH SET CONNECTOR / GRAPH / MAPPING`, `ADD MAPPING` / `DROP MAPPING`,
  and the connection-scoped `CONNECT … AS`, `DISCONNECT`, `USE CONNECTION`, and
  `SET DEFAULT CONNECTION` are gone. Register connectors + graphs instead and
  query by graph name (`USE <graph>`) or let routing pick the graph.

### ✨ New features & Improvements

- **Query graphs without `USE`.** [Schema-based routing](https://memgraph.com/docs/memgraph-zero/memgql/multiple-graphs#routing)
  infers the target graph from the labels, relationship types, and declared
  properties a query mentions; ambiguity is an actionable error. Explicit
  `USE <graph>` remains the override.
- **Caching engages under routing.** A cache-enabled graph is populated
  and served whether a part is pinned with `USE` or routed by label. Re-issuing
  `ALTER GRAPH … SET CACHE` now drops stale fragments, so re-pointing the cache
  can't serve a stale result.
- **Snowflake connector.** New `snowflake` connector type translates GQL to
  Snowflake SQL over Snowflake's HTTPS SQL API — a pure-Rust driver, so there's
  no ODBC layer or Snowflake client to install. It uses the same
  [mapping](https://memgraph.com/docs/memgraph-zero/memgql/reference#mapping-schema) format as every other
  SQL backend, references tables with three-part `database.schema.table` names,
  and supports **both reads and writes**. Authenticate with a key-pair (JWT), a
  programmatic access token, or a password. Snowflake's native **Time Travel** is
  exposed for point-in-time reads. See the
  [Snowflake connector page](https://memgraph.com/docs/memgraph-zero/memgql/connect/snowflake) for setup.

## MemGQL v0.7.0 - July 5th, 2026

### ⚠️ Behavior changes

- **The `info-queries-only` log level is removed.** `--log-level=info-queries-only`
  now fails at startup with the list of valid levels. Use `--log-level=DEBUG` to see
  queries and their transpiled output; plain `INFO` no longer logs query traffic.
- **The log file now honors `--log-level`.** Previously the `--log-file` mirror
  received every line regardless of the console level; now both destinations get the
  same threshold-filtered stream.

### ✨ New features & Improvements

- **Memgraph as a query-driven cache.** A catalog graph can now be cached in a
  Memgraph instance — aimed at data-warehouse connectors (Iceberg first) where a
  table is too large to materialize wholesale and every federated query otherwise
  re-scans it from object storage. Enable it per graph with a `CACHE CONNECTOR`
  clause:
```gql
ADD CONNECTOR mg TYPE memgraph URI 'memgraph:7687';
ADD GRAPH events ON CONNECTOR ice MAPPING warehouse READ ONLY
    CACHE CONNECTOR mg TTL 3600 MAX_BYTES 8G;
```
  The cache is **populated by query execution itself** (populate-on-read): the
  first read of a scope tees it into Memgraph (cache MISS), and later queries whose
  scans are covered are served entirely from Memgraph (cache HIT) with no source
  I/O. Because the cached data is a real graph in Memgraph, queries over cached
  scopes gain Memgraph's full capability profile — variable-length expand,
  quantified patterns, graph algorithms — even when the source connector can't
  express them. Toggle at runtime with `ALTER GRAPH <g> SET CACHE CONNECTOR …` /
  `ALTER GRAPH <g> REMOVE CACHE`, and inspect with `SHOW GRAPH CACHES`. `TTL` is in
  seconds; `MAX_BYTES` accepts a `K`/`M`/`G`/`T` binary suffix. Currently validated
  with Iceberg sources; the mechanism generalizes to the other warehouse
  connectors. See
  [Multiple Graphs → Caching](https://memgraph.com/docs/memgraph-zero/memgql/multiple-graphs#caching-a-graph-in-memgraph).
- **Cross-backend piping.** Federated queries move far less data. When one side of a
  two-backend query is selective — it carries a literal property filter
  (`{name: 'Memgraph'}`), a `LIMIT`, or a bounded `CALL` — MemGQL runs that side
  first and uses its join keys to fetch only the matching rows from the other
  backend, instead of pulling the whole table and joining locally. Results are
  identical; queries that join a small, filtered set against a large remote table
  get faster. If the selective side matches nothing, the other backend isn't queried
  at all. Piping applies to backends registered as catalog graphs (`ADD GRAPH`) and
  falls back to the previous behavior whenever it can't apply. See
  [Multiple Graphs](https://memgraph.com/docs/memgraph-zero/memgql/multiple-graphs#piping-fetching-only-what-joins).
- **Inline-map references across backends.** A property inside a node's inline map can
  now reference a binding from another `MATCH` part — and it pipes:
```gql
MATCH (e:Employee)
MATCH (i:Invoice {employee_id: e.id})
RETURN e.name, i.total;
```
  Previously this join had to be spelled as `WHERE i.employee_id = e.id`. Works
  without `USE` (each part routes by its own labels) and with multiple keys
  (`{country: o.country, city: o.city}`).
- **SQL Server connector.** New `sqlserver` connector type (aliases: `mssql`,
  `sql_server`, `sql-server`) translates GQL to T-SQL. The driver is
  [tiberius](https://crates.io/crates/tiberius), a pure-Rust TDS
  implementation: no ODBC or driver install needed. It uses the same
  [mapping](https://memgraph.com/docs/memgraph-zero/memgql/reference#mapping-schema) format as every other
  SQL backend and is registered in
  [`multi` mode](https://memgraph.com/docs/memgraph-zero/memgql/multiple-graphs) with an ADO-style
  connection string:
```gql
ADD CONNECTOR mssql TYPE sqlserver
    URI 'Server=localhost,1433;Database=test;User Id=sa;Password=…;TrustServerCertificate=true'
    MAPPING social;
```
  There is no standalone `CONNECTOR_TYPE=sqlserver` environment mode yet — SQL Server
  is multi-mode only. Works today: matching and filters, aggregates
  (incl. `COUNT(DISTINCT …)`), arithmetic, `CASE`, `COALESCE` / `NULLIF`, string
  predicates, `IN`, `OPTIONAL MATCH`, `WITH` pipelines (incl. whole-node carry-through),
  `UNION`, and typed whole-node / whole-relationship projections. See the
  [SQL Server connector page](https://memgraph.com/docs/memgraph-zero/memgql/connect/sqlserver) for setup and
  for what's not there yet (variable-length paths, `collect()`, map projections).
- **`ADD GRAPH IF NOT EXISTS`.** Re-registering an existing graph with the new
  `IF NOT EXISTS` clause succeeds as a no-op instead of erroring — for re-runnable
  setup scripts. Plain `ADD GRAPH` still errors on a duplicate name.
- **Log levels.** `--log-level` now accepts the standard severity ladder:
  `CRITICAL`, `ERROR`, `WARNING`, `INFO` (default), `DEBUG`, `TRACE`
  (case-insensitive). A level also emits everything more severe. Incoming queries and
  the generated Cypher / SQL are logged at `DEBUG`. See
  [Reference](https://memgraph.com/docs/memgraph-zero/memgql/reference#logging).

## MemGQL v0.6.3 - June 21st, 2026

### ✨ New features & Improvements

- **Schema-based routing.** In `multi` mode, queries no
  longer need a `USE <graph>` clause — the engine infers the backend from the
  query's schema signals (labels, rel-types, properties) against a unified schema
  index, built from mappings for SQL backends and live introspection for Cypher
	backends. Routing is strict: exactly one candidate routes, zero or multiple
	hard-error with the fix; explicit `USE` always wins. Routed federated
	`JOIN` and `UNION` work too, and writes route on a unique candidate. Two new
	statements expose the index: **`SHOW SCHEMA [FOR <graph>]`** and **`REFRESH
	SCHEMA`**. Identifier matching is now **exact** engine-wide. **Still gated
	to explicit `USE`:** non-default remote databases (Memgraph multi-tenancy),
	a single `MATCH` pattern spanning two backends, and a label-less `MATCH (n)`
	against a SQL backend.
- **Native Apache Iceberg connector (`iceberg-direct`).** A Trino-free Iceberg
  connector that reads tables directly via the REST catalog and Apache Arrow
  scans from object storage (S3/MinIO) — no SQL engine in the query path, with
  projection and predicate pushdown into the scan. It reuses the **same mapping
  format** as the Trino-backed `iceberg` connector and joins other backends in
  multi-connector federation. Register with `ADD CONNECTOR <name> TYPE
  iceberg-direct URI '<rest-catalog-uri>' MAPPING <mapping>`. **Read-only** —
  writes return an "unsupported" error.

## MemGQL v0.6.2 - June 7th, 2026

### ✨ New features & Improvements

- **Typed projections on every SQL backend.** `RETURN p` now returns a
  structured Bolt **Node** and `RETURN r` a typed Bolt **Relationship** on
  every SQL connector (PostgreSQL, MySQL, DuckDB, ClickHouse, Iceberg, Pinot,
  Oracle) — previously SQL backends returned the underlying column values and a
  map projection (`RETURN p {.id, .name}`) was required. Nodes carry their
  label and mapped properties; relationships carry their type and mapped
  properties. Mixing scalar and whole-element projections in one `RETURN`
  (`RETURN p.name, p`) works too.
- **Connection-less queries (liveness check).** `RETURN 1`, `RETURN 1 + 2 AS x`
  and `WITH 1 AS x RETURN x` now evaluate locally with no connector configured
  and no backend reachable — useful as a Bolt-level health probe.
- **`ORDER BY` by `RETURN` alias in cross-backend queries.** A sort key can
  reference a projected alias (`RETURN fact.tx_count AS tx_count … ORDER BY
  tx_count`), including when the alias is nested inside an arithmetic
  expression (`ORDER BY tx_count + 1`). The post-join sort rewrites the alias
  back to its underlying expression.
- **Delimited (quoted) identifiers** in GQL queries now parse.

### 🐞 Bug fixes

- **PostgreSQL `NUMERIC` columns** now deserialize correctly — whole and
  fractional values arrive at the Bolt driver as Float and `NULL` is
  preserved. Previously `NUMERIC`-typed columns were unsupported.

## MemGQL v0.6.1 - May 31st, 2026

### ✨ New features & Improvements

- **Cross-backend joins (phase 1).** Queries that `USE` two or more
  different graphs in a single statement now execute as a federated
  left-deep hash-join chain inside the Bolt server. `LinearQuery`
  carries `parts: Vec<FocusedPart>`; a multi-`USE` query lowers to a
  `CrossGraphJoin` chain of per-part `RemoteScan`s.
  `dispatch_cross_backend` peels `Limit > Sort > Distinct > Project >
  Filter` into a `FederationPipeline`, dispatches each part via the
  per-backend `BoltHandler::run_plan`, materializes rows to canonical
  scalars, and folds via hash-join (SQL 3VL — `NULL` keys dropped) or
  Cartesian product when there's no equi-predicate. Per-side
  materialization is capped at 1,000,000 rows.
  - **Verified end-to-end:** Memgraph, MySQL, PostgreSQL, DuckDB.
  - **Wired but not yet verified end-to-end:** Neo4j, Oracle, ClickHouse,
    Iceberg, Pinot — the integration is mechanically identical and
    awaits a broader live-backend test harness.
  - Composite (multi-column) equi-joins are supported.
  - Post-join `Filter` / `Sort` / `Limit` / `Distinct` and a federation
    expression evaluator run over the joined wide row, including
    cross-part arithmetic, string functions (`toUpper`, `toLower`,
    `length`, `size`, `trim`), and residual filters (`STARTS WITH`,
    comparisons).
  - Three-backend left-deep chains with skip-level predicates are
    supported.
  - Unsupported shapes return a typed error with an actionable
    headline: whole-node returns across the federation boundary,
    non-literal `LIMIT`/`SKIP`, unrecognized plan nodes above the
    join (`Aggregate`, `Union`), unsupported functions, etc.

### 🚧 Known limitations

- Whole-node `RETURN m` across federation is rejected;
  `CanonicalScalar::Node` modeling is deferred. Reference individual
  properties instead (`m.name`).
- Scalar functions reach the GQL parser catch-all today (the
  evaluator supports them — covered by unit tests — but the e2e path
  waits on a parser extension; aggregates and `COALESCE` / `NULLIF`
  go through the normal `FnCall` path).
- No output-cardinality cap (only per-side input cap of 1,000,000
  rows). Per-side dispatch is sequential; parallel fan-out is a
  follow-up.

## MemGQL v0.6.0 - May 23rd, 2026

### ⚠️ Breaking changes

- **`id_column` is now required on every edge mapping.** Previously optional
  (enforced at query time only for variable-length traversal), it must now
  be present on every edge entry in the mapping JSON. A mapping without
  `id_column` on an edge now fails at registration with
  `Failed to parse mapping JSON: missing field 'id_column' at line N`,
  whether the mapping is supplied via `MAPPING_FILE` at startup or via
  `ADD MAPPING` at runtime. Update existing mappings by adding the edge
  table's primary key column to every edge — see the
  [quick-start](https://memgraph.com/docs/memgraph-zero/memgql/quick-start) and connector examples
  for the new shape.
- **Untyped edge traversal `()-[]->(b)` now errors on SQL backends.**
  Previously this expanded into a `UNION` over candidate rel-type mappings
  and could silently over-count when label-distinct node tables shared
  numeric IDs. The translator now returns an actionable error explaining
  why untyped traversal isn't safe on SQL backends and pointing users at
  either declaring the edge type or running on a Cypher backend (Memgraph,
  Neo4j). Cypher backends still accept `()-[]->()` natively.

### ✨ New features & Improvements

- **Trail semantics for bounded variable-length on SQL backends.** Patterns
  like `(){1,3}` now enforce the GQL `DIFFERENT EDGES` default — no edge
  is reused within a single matched path. The recursive CTE carries an
  `_edges` visited-set whose shape is per-dialect (Postgres `ARRAY`, MySQL
  `JSON_ARRAY`, DuckDB `LIST`). On cyclic graphs this matches Memgraph and
  Neo4j byte-for-byte where previously SQL backends returned extra rows.
- **`COUNT(DISTINCT …)`** works end-to-end on every backend. Previously
  `count(DISTINCT x)` could leak through to backends as the synthetic
  `COUNT_DISTINCT(...)` function (no engine has that). Both Cypher and SQL
  translators now special-case `count_distinct` / `collect_distinct` /
  `collect_list_distinct` to emit the dialect-native `COUNT(DISTINCT …)`.
- **GQL parse errors now surface the actual ANTLR diagnostic** (`line 1:N
  no viable alternative at input '...'`) instead of being swallowed into
  the generic `No statements in GQL query` message.
- **Cypher-style variable-length syntax** (`[:R*]`, `[:R*1..3]`, `[:R*1..]`)
  now produces an actionable hint pointing at the GQL quantified-path-pattern
  form `(-[:R]->()){1,3}` instead of a confusing parse error.
- **Cross-graph parse errors** (multiple `USE <graph>` clauses in one query)
  now return a clear "not yet supported" message instead of the generic
  parse-failure error.

### 🐞 Bug fixes

- `%` (modulo) parses as a proper binary operator, not as a synthetic
  function call.
- `FOR x IN [...]` retains the iterated list and binds `x` correctly
  (new `UnwindClause` AST node; planner emits `LogicalPlan::Unwind`).
  **Execution is Cypher-only today** — SQL backends parse and plan it,
  then return an actionable error. See the
  [reference](https://memgraph.com/docs/memgraph-zero/memgql/reference) limitations for the
  SQL-side status.
- `NEXT` query composition resolves names bound on the left-hand-side
  when the right-hand-side `RETURN` references them.
- Rel-variable reuse across `MATCH` clauses parses without a redeclaration
  error.
- `RETURN 1`'s internal `_dummy` placeholder no longer leaks into Cypher
  queries sent to native backends.

## MemGQL v0.5.0 - May 16th, 2026

### ✨ New features & Improvements

- Added **Oracle** connector (`CONNECTOR_TYPE=oracle`).
- **DuckDB connector** joins as a fifth GQL-over-SQL backend (alongside Memgraph, Neo4j, PostgreSQL, MySQL).
- **`OPTIONAL MATCH`** now works on SQL backends (PostgreSQL, MySQL, DuckDB) — previously Cypher-only.
- **`WITH` pipeline boundary** (GQL scope D) on SQL backends — supports `WITH`, `WITH DISTINCT`, `WITH … ORDER BY … LIMIT N`, chained `WITH … WITH …`, and whole-node `WITH n` carry-through via derived-table SQL.
- **`UNION` / `UNION ALL` / `UNION DISTINCT`** between query statements work
across all five backends. Branches on the same backend translate to that
backend's native combinator; branches on different backends materialize
locally and combine in-memory. - **Map projections** — `RETURN n {.id, .title}
AS info` returns a Bolt Map (Memgraph, Neo4j, PostgreSQL, MySQL, DuckDB).
- **`collect()`** aggregate returns a typed Bolt List (Memgraph, Neo4j, PostgreSQL, MySQL, DuckDB).
- **`IN` list-membership** predicate — `WHERE n.name IN ['Alice', 'Bob']`.
- **`STARTS WITH` / `ENDS WITH` / `CONTAINS`** string predicates portable across all backends.
- **Quantified path patterns `(){m,n}`** on SQL backends emit a recursive CTE.
- **`MATCH p = (…) RETURN p`** path binding works on Cypher backends and bounded-path SQL.
- Unbounded variable-length paths (`()-[*]->()`) on SQL backends now return a clear error pointing at the bounded form (`(){1,5}`) or the Cypher fallback.
- `SHOW MAPPINGS` / `SHOW CONNECTORS` error messages now hint at the correct setup statements (`ADD MAPPING`, `ADD CONNECTOR`).
- Untyped edges `()-[]->(b)` on SQL backends translate via a `UNION ALL` over candidate rel-type mappings.

### 🐞 Bug fixes

- `INSERT (a {…}) RETURN a.name` no longer drops the `RETURN` clause.
- `%` (modulo) operator now recognized in the grammar and routed through every translator.
- `PATH_LENGTH(p)` on Cypher backends returns the integer length, not the relationship list.
- Temporal types (`date(...)`, `LOCAL_DATETIME(...)`, etc.) arrive at the Bolt driver as proper Date / LocalDateTime structs (previously leaked as Rust debug-format strings).
- `RETURN` column headers reflect the source expression text (`n.age`) instead of the literal placeholder `"expr"`.
- `RETURN *` no longer leaks internal Strategy-B `_u` / `_e` placeholders.
- `SKIP` without `LIMIT` is now honored (was silently dropped).
- `NULL` cells are sent as the PackStream `0xC0` byte (previously the string `"NULL"`).
- `NULLIF` and `COALESCE` work end-to-end on every backend.
- `OPTIONAL MATCH` WHERE predicates inside the optional pattern land on the correct `JOIN` clause so unmatched outer rows survive Cypher's semantics.

## MemGQL v0.4.0 - May 7th, 2026

- Added "Federated GQL Across Heterogeneous Backends" use case showing graph queries over ClickHouse and PostgreSQL
- Added vector search capabilities (only Memgraph backend)
- Fixed `SET DEFAULT CONNECTION` handling
- Fixed flaky `USE graph` behavior and corrected `USE graph` routing
- Fixed multi node and edge SQL `INSERT`
- Fixed connection handling
- Improved Trino startup wait
- Fixed all tests under `run_tests.sh`

## MemGQL v0.3.0 - April 26th, 2026

- Added Apache Pinot connector support, including `CONNECTION_TYPE=pinot` single mode and multi-connection mode
- Added MySQL connector support
- Added multi-graph (USE graph ...) and composite queries support

## MemGQL v0.2.1 - April 17th, 2026

- Fixed all required to make the Docker Compose example working as expected

## MemGQL v0.2.0 - April 12th, 2026

- Added MCP server
- Added Clickhouse connector
- Added the structured2graph agent to help generate mappings

## MemGQL v0.1.0 - March 29th, 2026

- GQL parser with ISO/IEC 39075 standard support including quantified path patterns
- Federated Bolt server for querying across Neo4j, Memgraph, PostgreSQL, DuckDB, and Iceberg/Trino
- GQL-to-native query translation (Cypher for graph DBs, SQL for relational)
- Runtime connector management via `ADD CONNECTOR`, `CONNECT`, and `USE` statements
- Shortest path queries with `ALL SHORTEST`, `ANY SHORTEST`, and `SHORTEST k` support
