Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion pages/memgraph-zero/memgql/changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,37 @@ description: MemGQL release notes

# MemGQL Changelog

## MemGQL v0.1.0 - TODO
## MemGQL v0.10.0 - TODO

### 🍃 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](/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](/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](/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](/memgraph-zero/memgql/multiple-graphs#load-per-source).

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

Expand Down
67 changes: 67 additions & 0 deletions pages/memgraph-zero/memgql/connect/postgres.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,73 @@ MATCH (a:Person)-[:KNOWS]->(b:Person) RETURN a.name, b.name;

For environment variables, see [Reference](../reference.mdx#postgresql-postgres).

## TLS connections

For a cloud-hosted PostgreSQL, the connection **mode** goes in the connection
string as libpq's `sslmode=`, and the connector declares what a URI cannot
express — which certificates to trust:

```json
{
"name": "pg",
"type": "postgres",
"connection": {
"uri": "postgresql://user:pass@db.example.com:5432/app?sslmode=require",
"sslRootCert": "/etc/ssl/certs/customer-ca.pem",
"trustServerCertificate": false
}
}
```

| Field | Description |
|-------|-------------|
| `sslmode=` (in `uri`) | libpq semantics, including the default: `disable` never attempts TLS, `prefer` uses it when it works, `require` makes it mandatory. |
| `sslRootCert` | Path to a PEM bundle of CA certificates to trust **instead of** the system roots. Omit it to use the system trust store. |
| `trustServerCertificate` | Encrypt without verifying the server's identity. |

TLS is implemented with [rustls](https://github.com/rustls/rustls), so there is
no OpenSSL or other C library to install.

`trustServerCertificate` protects against passive eavesdropping but **not**
against an active man-in-the-middle, and it logs a warning on every use. It
exists because managed instances are routinely fronted by a certificate that
doesn't match the hostname you dial; prefer `sslRootCert` where you can. The two
are mutually exclusive — a CA bundle plus "trust anything" is a contradiction
and is rejected.

Two more guardrails:

- Declaring TLS settings alongside `sslmode=disable` is **refused** rather than
silently connecting in plaintext.
- Under `sslmode=prefer`, a failed handshake retries in plaintext and warns — so
enabling TLS support doesn't strand a connector pointed at a server whose
certificate you have no reason to trust. A connector that *declared*
`sslRootCert` or `trustServerCertificate` never falls back; it named a trust
anchor, so the failure is an error. Under `require` it is always an error.

These fields round-trip through `EXPORT SCHEMA`, so a dumped and reloaded
catalog reconnects with the same trust settings.

## JSONB columns

A `JSONB` column can be mapped as typed properties at fixed paths, or passed
through as a document whose undeclared keys stay queryable:

```json
"attributes": [
{ "name": "voltage", "column": "props", "path": "electrical.voltage", "type": "Double" },
{ "name": "props", "type": "Json" }
]
```

```gql
MATCH (c:Component) WHERE c.voltage > 100 RETURN c.sku, c.props.rohs;
```

Both forms push the extraction down to PostgreSQL, and a declared `type` makes
the comparison numeric instead of lexicographic. See
[Schema File → JSON / JSONB columns](/memgraph-zero/memgql/schema-file#json--jsonb-columns).

## Supported GQL features

| Feature | Postgres |
Expand Down
72 changes: 70 additions & 2 deletions pages/memgraph-zero/memgql/multiple-graphs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,10 @@ follow-up read routes without needing a `REFRESH SCHEMA`.
- A graph bound to a **non-default remote database** (Memgraph multi-tenancy) is
fenced to explicit `USE`; per-tenant introspection isn't wired up yet.
- A **single `MATCH` pattern that spans two backends** errors with guidance to
split it into one `MATCH` clause per graph; auto-splitting one pattern is out
of scope.
split it into one `MATCH` clause per graph — unless the link between them is
declared as a
[cross-connector edge](#traversing-across-backends-with-an-edge), which is
split automatically.
- A label-less `MATCH (n)` against a SQL backend still surfaces a raw backend
error (there's nothing to route or translate by).

Expand Down Expand Up @@ -255,6 +257,46 @@ or without it. It engages for backends registered as catalog graphs
locally. If the selective side matches nothing, the other backend is never
queried.

### Traversing across backends with an edge

The joins above are written as predicates over two query parts. A graph can
instead declare the link as a **cross-connector edge**, so the same join is
traversed as one pattern:

```json
{
"label": "MANUFACTURED_BY",
"from": "Component",
"to": "Manufacturer",
"mappedJoinSource": { "fromKey": "manufacturer_code", "toKey": "code" }
}
```

With `Component` mapped to PostgreSQL and `Manufacturer` to Memgraph, one
`MATCH` now spans both:

```gql
-- Instead of: USE pg_graph MATCH (c:Component) USE mg_graph MATCH (m:Manufacturer)
-- WHERE c.manufacturer_code = m.code
MATCH (c:Component)-[:MANUFACTURED_BY]->(m:Manufacturer)
WHERE c.voltage > 100
RETURN c.sku, m.name;
```

MemGQL rewrites the pattern into the federated join described above — one part
per connector plus the join equality — so piping, per-part caching and the local
join all apply unchanged. Returning whole elements works too, which is what a
graph client needs to draw and expand the result:

```gql
MATCH (c:Component)-[r:MANUFACTURED_BY]->(m:Manufacturer) RETURN c, r, m;
```

The edge must be traversed in a direction, matched by a single `MATCH` with one
path pattern, and carries no properties of its own. See
[Schema File → Cross-connector edges](/memgraph-zero/memgql/schema-file#cross-connector-edges)
for the full rules.

## Composite Queries Across Graphs

The GQL standard defines composite expressions combining query branches with `UNION`, `INTERSECT`, and `EXCEPT`. Each branch can target a different graph.
Expand Down Expand Up @@ -367,6 +409,32 @@ SHOW GRAPH social;
mode). To see what each one actually *defines* (the labels, relationship types,
and properties used for routing), use [`SHOW SCHEMA`](#schema-discovery).

### Load per source

Federated queries fan out to several backends, so it helps to know how much each
one is actually being asked to do. `SHOW STATS` reports that per connector:

```gql
RESET STATS;
MATCH (c:Component)-[:MANUFACTURED_BY]->(m:Manufacturer) RETURN c.sku, m.name;
SHOW STATS;
```

```
+--------+---------+------+--------+----------------+----------------+
| source | queries | rows | errors | avg_latency_ms | max_latency_ms |
+--------+---------+------+--------+----------------+----------------+
| mg | 1 | 2 | 0 | 6.42 | 6.42 |
| pg | 1 | 4 | 0 | 9.18 | 9.18 |
+--------+---------+------+--------+----------------+----------------+
```

Counts are what each **source** saw: statements dispatched to it and rows it
returned. `RESET STATS` zeroes the counters, so one query's cost on a production
backend can be measured in isolation. Cache hits and misses are keyed by graph
rather than connector and live in
[`SHOW GRAPH CACHES`](#caching-a-graph-in-memgraph).

## Graph Lifecycle Management

### Creating graphs
Expand Down
27 changes: 27 additions & 0 deletions pages/memgraph-zero/memgql/reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,34 @@ SHOW MAPPINGS; -- per-graph mappings
SHOW SCHEMA [FOR <graph>]; -- unified routing index: labels, rel-types, properties
EXPORT SCHEMA [TO '<path>']; -- merged catalog as canonical schema JSON (round-trippable)
REFRESH SCHEMA; -- re-introspect live Cypher connections (Memgraph/Neo4j)

-- Query load per source
SHOW STATS; -- source, queries, rows, errors, avg_latency_ms, max_latency_ms
RESET STATS; -- zero the counters
```

`SHOW STATS` reports what each **source** saw — statements MemGQL dispatched to
it and rows it returned — so the load federation puts on a production backend
can be measured before rollout:

```
+--------+---------+------+--------+----------------+----------------+
| source | queries | rows | errors | avg_latency_ms | max_latency_ms |
+--------+---------+------+--------+----------------+----------------+
| mg | 3 | 6 | 0 | 6.42 | 11.03 |
| pg | 3 | 12 | 0 | 9.18 | 18.55 |
+--------+---------+------+--------+----------------+----------------+
```

Latency covers a whole query — the statement *and* the fetch of its rows — and
is reported in fractional milliseconds, since a healthy local source answers in
hundreds of microseconds. `max_latency_ms` sits next to the average because an
average hides the tail that shows up as a load problem. `RESET STATS` zeroes the
counters, so a single query's cost can be measured in isolation.

Counters are keyed by connector. **Cache** efficacy is keyed by graph and lives
in [`SHOW GRAPH CACHES`](/memgraph-zero/memgql/multiple-graphs#caching-a-graph-in-memgraph)
(hits, misses, resident fragments).

```
-- Single graph
Expand Down
Loading