From 29a03d43748e61b2541d072bde529e8a3732874e Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Thu, 13 Aug 2026 20:33:02 +0200 Subject: [PATCH 1/3] Add use_case_001 docs --- pages/memgraph-zero/memgql/changelog.mdx | 49 ++++++- .../memgraph-zero/memgql/connect/postgres.mdx | 67 ++++++++++ .../memgraph-zero/memgql/multiple-graphs.mdx | 72 +++++++++- pages/memgraph-zero/memgql/reference.mdx | 27 ++++ pages/memgraph-zero/memgql/schema-file.mdx | 125 +++++++++++++++++- 5 files changed, 334 insertions(+), 6 deletions(-) diff --git a/pages/memgraph-zero/memgql/changelog.mdx b/pages/memgraph-zero/memgql/changelog.mdx index 9a5e80b13..06544150b 100644 --- a/pages/memgraph-zero/memgql/changelog.mdx +++ b/pages/memgraph-zero/memgql/changelog.mdx @@ -5,7 +5,54 @@ description: MemGQL release notes # MemGQL Changelog -## MemGQL v0.1.0 - TODO +## MemGQL v0.10.0 - TODO + +### 🍃 New features & Improvements + +- **Cross-connector edges.** A graph can now declare an edge whose two endpoints + live in *different* backends, with `mappedJoinSource { "fromKey": …, "toKey": … }` + — no backing table on either side; the relationship *is* equality between one + property on each endpoint. A single pattern then traverses the boundary: + `MATCH (c:Component)-[:MANUFACTURED_BY]->(m:Manufacturer)` reads components + from PostgreSQL and manufacturers from Memgraph. This is the only edge form + that works when one endpoint is a native-graph backend, which has no joinable + edge table to point at. `RETURN c, r, m` packs real nodes and a relationship, + so graph clients can draw and expand the result. Under the hood the pattern is + rewritten into the cross-backend join that already ran, so piping, per-part + caching and the local join apply unchanged. See + [Cross-connector edges](/memgraph-zero/memgql/schema-file#cross-connector-edges). +- **JSON / JSONB columns are queryable.** Document columns (PostgreSQL `JSONB`, + MySQL `JSON`, …) map two composable ways. A **declared path** pins a value + inside the document to its own typed property + (`{ "name": "voltage", "column": "props", "path": "electrical.voltage", "type": "Double" }`), + so `WHERE c.voltage > 240` pushes down as an extraction cast to that type — the + cast is what keeps the comparison numeric instead of text, where `'90' > '240'`. + **Passthrough** (`{ "name": "props", "type": "Json" }`) keeps the column a + document: it returns as a map and *undeclared* keys stay reachable as + `c.props.rohs`, each pushed down as an extraction, for heterogeneous blobs that + can't be declared up front. Supported on PostgreSQL, MySQL, DuckDB, SQL Server, + Microsoft Fabric and Snowflake; a mapping declaring a `path` against any other + connector fails to load rather than failing every query. Writing *through* a + path is refused rather than clobbering the surrounding document. See + [JSON / JSONB columns](/memgraph-zero/memgql/schema-file#json--jsonb-columns). +- **TLS for PostgreSQL connections.** The mode stays in the connection URI + (`sslmode=`, libpq semantics), and the connector declares what a URI cannot + express: `sslRootCert` (a PEM bundle to trust instead of the system roots) and + `trustServerCertificate` (encrypt without verifying the server — an escape + hatch for managed instances behind a mismatched certificate, warned about on + every use). Implemented with rustls, so there's no OpenSSL to install. + Declaring TLS settings alongside `sslmode=disable` is refused rather than + silently connecting in plaintext, and the two trust options are mutually + exclusive. Both survive an `EXPORT SCHEMA` round-trip. See + [TLS connections](/memgraph-zero/memgql/connect/postgres#tls-connections). +- **`SHOW STATS` reports query load per source.** One row per connector with + `queries`, `rows`, `errors`, `avg_latency_ms` and `max_latency_ms` — what the + *source* saw, so the load a federated query puts on a production backend can be + estimated before rollout. Latency covers the statement *and* the fetch of its + rows, in fractional milliseconds. `RESET STATS` zeroes the counters, so a single + query can be measured in isolation. Cache efficacy stays in `SHOW GRAPH CACHES`, + which is keyed by graph rather than connector. See + [Load per source](/memgraph-zero/memgql/multiple-graphs#load-per-source). ## MemGQL v0.9.0 - August 9th, 2026 diff --git a/pages/memgraph-zero/memgql/connect/postgres.mdx b/pages/memgraph-zero/memgql/connect/postgres.mdx index bc6b8e4dc..9d98c7032 100644 --- a/pages/memgraph-zero/memgql/connect/postgres.mdx +++ b/pages/memgraph-zero/memgql/connect/postgres.mdx @@ -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 | diff --git a/pages/memgraph-zero/memgql/multiple-graphs.mdx b/pages/memgraph-zero/memgql/multiple-graphs.mdx index 56d929878..df6a81299 100644 --- a/pages/memgraph-zero/memgql/multiple-graphs.mdx +++ b/pages/memgraph-zero/memgql/multiple-graphs.mdx @@ -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). @@ -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. @@ -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 diff --git a/pages/memgraph-zero/memgql/reference.mdx b/pages/memgraph-zero/memgql/reference.mdx index b73db1c90..9c4fd5b00 100644 --- a/pages/memgraph-zero/memgql/reference.mdx +++ b/pages/memgraph-zero/memgql/reference.mdx @@ -174,7 +174,34 @@ SHOW MAPPINGS; -- per-graph mappings SHOW SCHEMA [FOR ]; -- unified routing index: labels, rel-types, properties EXPORT SCHEMA [TO '']; -- 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 diff --git a/pages/memgraph-zero/memgql/schema-file.mdx b/pages/memgraph-zero/memgql/schema-file.mdx index 011413d97..948c5eb4b 100644 --- a/pages/memgraph-zero/memgql/schema-file.mdx +++ b/pages/memgraph-zero/memgql/schema-file.mdx @@ -139,10 +139,17 @@ Every `connection` field is optional; supply what a given backend needs: | `schema` | Middle namespace (PostgreSQL schema, MySQL / ClickHouse database, Iceberg schema). | | `catalog` | Native root for three-level backends (Iceberg catalog, SQL Server database, Fabric warehouse/lakehouse item). | | `path` | File-backed backends (DuckDB). | +| `sslRootCert` | PEM bundle of CA certificates to trust instead of the system roots (PostgreSQL). | +| `trustServerCertificate` | Encrypt without verifying the server's certificate (PostgreSQL). Mutually exclusive with `sslRootCert`. | **Supported `type` values:** `memgraph`, `neo4j`, `postgres` (`postgresql`), `mysql`, `sqlserver`, `oracle`, `duckdb`, `iceberg`, `iceberg-direct`, -`clickhouse`, `pinot`, `fabric`. +`clickhouse`, `pinot`, `snowflake`, `mongodb`, `fabric`. + +For PostgreSQL, the TLS **mode** stays in the URI (`sslmode=`), where libpq +users expect it; `sslRootCert` / `trustServerCertificate` declare what a URI +cannot express. See +[TLS connections](/memgraph-zero/memgql/connect/postgres#tls-connections). ## `graphs` @@ -231,7 +238,9 @@ A vertex maps a **label** to a backend source. Exactly one source kind is set: An edge maps a **relationship type** between two labels. Relational edges name the foreign-key columns via `metaFields.from` / `metaFields.to`; native-graph -edges pass through. +edges pass through; and a `mappedJoinSource` edge links two labels that live in +**different connectors** (see [Cross-connector edges](#cross-connector-edges)). +Exactly one source kind is set. ```json { @@ -280,6 +289,68 @@ A relational edge adds two more `metaFields` on top of `id`: missing. Native-graph edges (`mappedGraphSource`) need only `from` / `to` labels; the traversal is resolved by the backend. +#### Cross-connector edges + +A third source kind, `mappedJoinSource`, declares an edge whose two endpoints +live in **different connectors**. It has no backing table anywhere: the +relationship *is* equality between one property on each endpoint. + +```json +{ + "label": "MANUFACTURED_BY", + "from": "Component", + "to": "Manufacturer", + "mappedJoinSource": { + "fromKey": "manufacturer_code", + "toKey": "code" + } +} +``` + +With `Component` mapped to a PostgreSQL table and `Manufacturer` to a Memgraph +connector, one pattern now traverses the boundary: + +```gql +MATCH (c:Component)-[:MANUFACTURED_BY]->(m:Manufacturer) RETURN c.sku, m.name; +``` + +| `mappedJoinSource` key | Description | +|------------------------|-------------| +| `fromKey` | Property on the `from` vertex. A **GQL property name**, not a raw column; it resolves through that vertex's own mapping. | +| `toKey` | Property on the `to` vertex, resolved the same way. | + +This is the only edge form that works when one endpoint is a native-graph +backend, which has no joinable edge table to point at. Under the hood the +traversal is rewritten into the +[cross-backend join](/memgraph-zero/memgql/multiple-graphs#focused-multi-graph-queries) +that already runs — one part per connector plus the join equality — so piping, +per-part caching and the local join all apply unchanged. + +`RETURN c, r, m` packs real nodes and a relationship, so graph clients such as +Memgraph Lab can draw and expand the result. Element ids are synthesized from +the connector, label and key, so two backends that both number rows from `1` +don't collide. + +**Rules and limits** (each is refused with a message saying what to write +instead): + +- Both endpoints must live in different connectors — within one connector use + `mappedTableSource` with `metaFields.from` / `to`. +- Each key must be a declared `attribute` of its endpoint vertex (native-graph + vertices are exempt, since the query passes through). +- The edge must be traversed **in a direction**: `-[:R]->` or `<-[:R]-`, not + `-[:R]-`. +- No variable-length traversal, no `OPTIONAL MATCH`, and one `MATCH` with one + path pattern per query. +- The edge carries no properties, so it cannot be filtered — filter the + endpoints instead. +- Every node in the pattern needs a label, so each side can be routed. +- Aggregating *across* the join (for example `count()` over both sides) is not + supported yet; return the rows and count client-side. + +A **table-backed** edge whose endpoints sit in different connectors is still +skipped at load time with a warning pointing at `mappedJoinSource`. + ### Attributes `attributes` declare the properties a label exposes. @@ -289,9 +360,57 @@ labels; the traversal is resolved by the backend. | `name` | yes | The GQL property name. | | `column` | no | The backing column (defaults to `name`), e.g. property `name` ← column `full_name`. | | `type` | no | Recorded, not enforced at query time (default `String`). | +| `path` | no | Location inside a JSON document column (see below). | Allowed `type` values: `Boolean`, `Byte`, `Short`, `Int`, `Long`, `HugeInt`, -`Float`, `Double`, `Decimal`, `String`, `Date`, `DateTime`. +`Float`, `Double`, `Decimal`, `String`, `Date`, `DateTime`, `Json`. + +#### JSON / JSONB columns + +A document column (PostgreSQL `JSONB`, MySQL `JSON`, …) can be mapped two ways, +and they compose — use both on the same column. + +**Declared path.** Pin a value inside the document to its own typed property. +`column` names the document column, `path` the location inside it, and `type` +the type of the value found there: + +```json +{ + "name": "voltage", + "column": "props", + "path": "electrical.voltage", + "type": "Double" +} +``` + +```gql +MATCH (c:Component) WHERE c.voltage > 240 RETURN c.voltage; +``` + +pushes down to the source as an extraction cast to the declared type. The cast +is what makes the comparison numeric — without it the database compares text, +where `'90' > '240'`. `path` is a dotted string; for keys that themselves +contain a dot, write an explicit segment list: `"path": ["spec.v2", "voltage"]`. + +**Passthrough.** Mark the column `Json` and it stays a document: `RETURN +c.props` returns a map, and **undeclared** keys are reachable with ordinary +property syntax — `c.props.rohs`, `c.props.electrical.voltage` — each pushed +down as an extraction on the source. This is the option for heterogeneous blobs +where declaring every key up front isn't possible. An undeclared key carries no +declared type, so the comparison supplies one: compared against a number it is +cast like a declared numeric path, compared against a string it stays text. A +key the document doesn't have reads as `null` rather than failing the query. + +```json +{ "name": "props", "type": "Json" } +``` + +**Limits.** `path` attributes are read-only — an `INSERT` through a JSON path is +rejected rather than clobbering the surrounding document. JSON path support is +per backend: PostgreSQL, MySQL, DuckDB, SQL Server, Microsoft Fabric and +Snowflake. A mapping that declares a `path` against any other connector fails to +load, so the mismatch surfaces at boot / `CREATE GRAPH` rather than on every +query. `attributes` are optional and need not be exhaustive: a property you don't list still resolves to a same-named column at query time (`p.sku` → column `sku`). From ee4bed55f8ed0f2babafc36c3e9f676a008262f3 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Thu, 13 Aug 2026 20:35:27 +0200 Subject: [PATCH 2/3] Adjust the changelog --- pages/memgraph-zero/memgql/changelog.mdx | 63 +++++++++--------------- 1 file changed, 23 insertions(+), 40 deletions(-) diff --git a/pages/memgraph-zero/memgql/changelog.mdx b/pages/memgraph-zero/memgql/changelog.mdx index 06544150b..a5abc6d78 100644 --- a/pages/memgraph-zero/memgql/changelog.mdx +++ b/pages/memgraph-zero/memgql/changelog.mdx @@ -9,49 +9,32 @@ description: MemGQL release notes ### 🍃 New features & Improvements -- **Cross-connector edges.** A graph can now declare an edge whose two endpoints - live in *different* backends, with `mappedJoinSource { "fromKey": …, "toKey": … }` - — no backing table on either side; the relationship *is* equality between one - property on each endpoint. A single pattern then traverses the boundary: - `MATCH (c:Component)-[:MANUFACTURED_BY]->(m:Manufacturer)` reads components - from PostgreSQL and manufacturers from Memgraph. This is the only edge form - that works when one endpoint is a native-graph backend, which has no joinable - edge table to point at. `RETURN c, r, m` packs real nodes and a relationship, - so graph clients can draw and expand the result. Under the hood the pattern is - rewritten into the cross-backend join that already ran, so piping, per-part - caching and the local join apply unchanged. See +- **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.** Document columns (PostgreSQL `JSONB`, - MySQL `JSON`, …) map two composable ways. A **declared path** pins a value - inside the document to its own typed property - (`{ "name": "voltage", "column": "props", "path": "electrical.voltage", "type": "Double" }`), - so `WHERE c.voltage > 240` pushes down as an extraction cast to that type — the - cast is what keeps the comparison numeric instead of text, where `'90' > '240'`. - **Passthrough** (`{ "name": "props", "type": "Json" }`) keeps the column a - document: it returns as a map and *undeclared* keys stay reachable as - `c.props.rohs`, each pushed down as an extraction, for heterogeneous blobs that - can't be declared up front. Supported on PostgreSQL, MySQL, DuckDB, SQL Server, - Microsoft Fabric and Snowflake; a mapping declaring a `path` against any other - connector fails to load rather than failing every query. Writing *through* a - path is refused rather than clobbering the surrounding document. See +- **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 connection URI - (`sslmode=`, libpq semantics), and the connector declares what a URI cannot - express: `sslRootCert` (a PEM bundle to trust instead of the system roots) and - `trustServerCertificate` (encrypt without verifying the server — an escape - hatch for managed instances behind a mismatched certificate, warned about on - every use). Implemented with rustls, so there's no OpenSSL to install. - Declaring TLS settings alongside `sslmode=disable` is refused rather than - silently connecting in plaintext, and the two trust options are mutually - exclusive. Both survive an `EXPORT SCHEMA` round-trip. See +- **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 with - `queries`, `rows`, `errors`, `avg_latency_ms` and `max_latency_ms` — what the - *source* saw, so the load a federated query puts on a production backend can be - estimated before rollout. Latency covers the statement *and* the fetch of its - rows, in fractional milliseconds. `RESET STATS` zeroes the counters, so a single - query can be measured in isolation. Cache efficacy stays in `SHOW GRAPH CACHES`, - which is keyed by graph rather than connector. See +- **`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 From 636518a078b628640768099664b52480cd24e773 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Sun, 16 Aug 2026 17:02:10 +0200 Subject: [PATCH 3/3] Add a note --- pages/memgraph-zero/memgql/schema-file.mdx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pages/memgraph-zero/memgql/schema-file.mdx b/pages/memgraph-zero/memgql/schema-file.mdx index 948c5eb4b..2644be1c8 100644 --- a/pages/memgraph-zero/memgql/schema-file.mdx +++ b/pages/memgraph-zero/memgql/schema-file.mdx @@ -399,7 +399,10 @@ down as an extraction on the source. This is the option for heterogeneous blobs where declaring every key up front isn't possible. An undeclared key carries no declared type, so the comparison supplies one: compared against a number it is cast like a declared numeric path, compared against a string it stays text. A -key the document doesn't have reads as `null` rather than failing the query. +key the document doesn't have reads as `null` rather than failing the query, and +so does one whose parent is missing or isn't an object +(`c.props.nosuch.deeper`). Filtering on an absent key matches no rows — +including a numeric comparison, where the cast applies to nothing. ```json { "name": "props", "type": "Json" }