Skip to content

Commit 0973e12

Browse files
committed
Add MemGQL v0.13.0 release docs
1 parent 86841b5 commit 0973e12

2 files changed

Lines changed: 83 additions & 14 deletions

File tree

‎pages/memgraph-zero/memgql/changelog.mdx‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,38 @@ description: MemGQL release notes
55

66
# MemGQL Changelog
77

8+
## MemGQL v0.13.0 - unreleased
9+
10+
### 🍃 New features & Improvements
11+
12+
- **Multi-label vertex mappings.** A vertex may declare
13+
`"labels": ["Cat", "Animal"]` instead of a single `label`. The first label
14+
identifies the mapping; the others may be shared with other mappings. A
15+
pattern on a shared label (`MATCH (a:Animal)`) reads every table that
16+
carries it as one `UNION` inside the connector, resolving shared property
17+
names through each table's own columns and returning `null` for a property
18+
only some of them declare. Returned nodes carry all of their labels. See
19+
[Vertices](/memgraph-zero/memgql/schema-file#vertices).
20+
- **Join edges within one connector.** `mappedJoinSource` now also links two
21+
tables in the same relational connector — the case where a row carries the
22+
target's *business key* rather than a foreign key into its `metaFields.id`,
23+
which a table-backed edge cannot express. The traversal is pushed down as a
24+
single `JOIN`, so aggregates across it work and no federated join is
25+
involved. See
26+
[Cross-connector edges](/memgraph-zero/memgql/schema-file#cross-connector-edges).
27+
28+
### ⚠️ Behavior changes
29+
30+
- **A label the mapping does not declare now matches nothing.**
31+
`MATCH (p:Person&Vip)` (GQL; `(p:Person:Vip)` in Cypher) on a `Person` table
32+
that does not carry `Vip` returns no rows. Previously the second label was
33+
ignored and every `Person` came back.
34+
35+
### 🐞 Bug fixes
36+
37+
- `SHOW STATS CONNECTORS` missed queries that routed by label to a single
38+
connector; only federated and `USE`-qualified queries were counted.
39+
840
## MemGQL v0.12.0 - September 14th, 2026
941

1042
### ⚠️ Breaking changes

‎pages/memgraph-zero/memgql/schema-file.mdx‎

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,40 @@ A vertex maps a **label** to a backend source. Exactly one source kind is set:
245245
}
246246
```
247247

248+
A table whose rows should carry **more than one label** lists them under
249+
`labels` instead of `label`. The first label identifies the mapping and must be
250+
unique in the graph; the others may be shared with other mappings:
251+
252+
```json
253+
{
254+
"labels": ["Cat", "Animal"],
255+
"mappedTableSource": {
256+
"connector": "pg",
257+
"table": "cats",
258+
"metaFields": { "id": "cat_id" }
259+
},
260+
"attributes": [
261+
{ "name": "id", "column": "cat_id" },
262+
{ "name": "name" }
263+
]
264+
}
265+
```
266+
267+
With a second mapping `["Dog", "Animal"]` over a `dogs` table keyed by
268+
`dog_id`, `MATCH (a:Cat)` reads one table, `MATCH (a:Dog&Animal)` the other
269+
(GQL writes a label conjunction as `:A&B`; in Cypher it is `:Dog:Animal`),
270+
and `MATCH (a:Animal)` both — as one `UNION` statement inside the connector.
271+
Shared property names resolve through each table's own columns, a property
272+
only one table declares is `null` on the other's rows, and returned nodes
273+
carry all of their labels (`(:Cat:Animal)`). Attributes that two carriers of a shared
274+
label both declare must have the same `type`. A traversal or an `INSERT` has to
275+
start from one table, so on a shared label both are refused with a pointer to
276+
the identifying label. A label no mapping carries together with the others
277+
matches nothing.
278+
248279
| Field | Source kind | Description |
249280
|-------|-------------|-------------|
281+
| `label` / `labels` | both | The node label, or a list of labels whose first entry identifies the mapping (unique per graph) and whose others may be shared with other mappings. |
250282
| `mappedTableSource.connector` | relational | Connector name (alias `catalog`). |
251283
| `mappedTableSource.schema` | relational | Optional middle namespace (PostgreSQL schema, etc.). |
252284
| `mappedTableSource.database` | relational | Optional outer namespace for backends with three-part names; on SQL Server it renders `database.schema.table`, so one connection can reach views in other databases. |
@@ -318,9 +350,11 @@ labels; the traversal is resolved by the backend.
318350

319351
#### Cross-connector edges
320352

321-
A third source kind, `mappedJoinSource`, declares an edge whose two endpoints
322-
live in **different connectors**. It has no backing table anywhere: the
323-
relationship *is* equality between one property on each endpoint.
353+
A third source kind, `mappedJoinSource`, declares an edge with **no backing
354+
table anywhere**: the relationship *is* equality between one property on each
355+
endpoint. It is how a traversal crosses into a **different connector**, and
356+
also how two tables in the **same** connector are linked by a business key
357+
rather than by a foreign key into the target's `metaFields.id`.
324358

325359
```json
326360
{
@@ -361,19 +395,22 @@ don't collide.
361395
**Rules and limits** (each is refused with a message saying what to write
362396
instead):
363397

364-
- Both endpoints must live in different connectors — within one connector use
365-
`mappedTableSource` with `metaFields.from` / `to`.
366-
- Each key must be a declared `attribute` of its endpoint vertex (native-graph
367-
vertices are exempt, since the query passes through).
368-
- The edge must be traversed **in a direction**: `-[:R]->` or `<-[:R]-`, not
369-
`-[:R]-`.
370-
- No variable-length traversal, no `OPTIONAL MATCH`, and one `MATCH` with one
371-
path pattern per query.
398+
- Each key must be a declared `attribute` of its endpoint vertex, backed by a
399+
plain scalar column (native-graph vertices are exempt, since the query passes
400+
through). The edge declares no `attributes`.
372401
- The edge carries no properties, so it cannot be filtered — filter the
373402
endpoints instead.
374-
- Every node in the pattern needs a label, so each side can be routed.
375-
- Aggregating *across* the join (for example `count()` over both sides) is not
376-
supported yet; return the rows and count client-side.
403+
- Across connectors: the edge must be traversed **in a direction** (`-[:R]->`
404+
or `<-[:R]-`, not `-[:R]-`); no variable-length traversal, no
405+
`OPTIONAL MATCH`, one `MATCH` with one path pattern per query; every node in
406+
the pattern needs a label, so each side can be routed; aggregating *across*
407+
the join (`count()` over both sides) is not supported yet.
408+
- Within one relational connector the edge is pushed down as a single `JOIN`
409+
on the two key columns, so those limits do not apply: aggregates work, and an
410+
undirected step is accepted when the two endpoint labels differ. A
411+
variable-length step over it is refused. Both endpoints on a Memgraph or
412+
Neo4j connector are refused — that backend stores its own relationships, so
413+
declare `mappedGraphSource`.
377414

378415
A **table-backed** edge whose endpoints sit in different connectors is still
379416
skipped at load time with a warning pointing at `mappedJoinSource`.

0 commit comments

Comments
 (0)