> For the complete documentation index, see [llms.txt](https://docs.prestd.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.prestd.com/releases/v2.5.0.md).

# v2.5.0

pREST v2.5.0 — MySQL 8 adapter, JOIN access-control fixes, middleware plugin builds, and Go plus Studio dependency bumps.

Released: October 7, 2026

[GitHub tag](https://github.com/prest/prest/releases/tag/v2.5.0) · [Compare v2.4.2...v2.5.0](https://github.com/prest/prest/compare/v2.4.2...v2.5.0)

**v2.5.0** adds a **MySQL 8** dialect adapter ([#1048](https://github.com/prest/prest/pull/1048)), fixes restricted JOINs so joined columns follow table access control ([#1032](https://github.com/prest/prest/pull/1032), [#1033](https://github.com/prest/prest/pull/1033)), and fixes middleware plugin builds ([#1039](https://github.com/prest/prest/pull/1039)). Go and Studio dependency bumps ship in the same tag ([#1055](https://github.com/prest/prest/pull/1055)).

* **Docker:** `prest/prest:v2.5.0`
* **Go install:** `go install github.com/prest/prest/v2/cmd/prestd@v2.5.0`

Upgrading from [v2.4.2](/releases/v2.4.2.md) is a drop-in pin change unless you turn on MySQL. PostgreSQL stays the default engine.

***

## Highlights

### MySQL 8 adapter ([#1048](https://github.com/prest/prest/pull/1048))

pREST selects MySQL only when you set `engine = "mysql"` on the root config or a `[[databases]]` entry. An empty `engine` stays PostgreSQL, including Timescale detection. Connection URLs are not probed to guess the engine.

`mysql://` is applied only when `engine` is `mysql`. The port defaults to **3306** when unset. Postgres defaults (user `postgres`, database `prest`, port 5432) are not copied. A missing user or database fails startup.

Environment variables: `PREST_DB_*` is read first, then the legacy `PREST_PG_*` names (and `PREST_AUTH_SCHEMA`).

TLS modes are `disable`, `require`, and `skip-verify`. Setting a client cert, key, or root certificate **fails startup** — custom TLS config is not in this release.

Routes stay `/{database}/{schema}/{table}`:

* `{database}` selects the connection pool (the alias, or the configured database on a single connection).
* `{schema}` is the MySQL database. MySQL treats database and schema as the same thing.
* System schemas `mysql`, `information_schema`, `performance_schema`, and `sys` are hidden from listings. `/databases` and `/schemas` both list user databases.

The floor is **MySQL 8.0.19+** (the upsert row alias). CI runs `mysql:8.0`, `mysql:8.4`, and `mysql:latest`. **MariaDB is out of scope.** TiDB and Aurora MySQL are not certified on this adapter.

Writes do not use SQL `RETURNING`. An insert runs, then `SELECT *` in the same transaction. `AUTO_INCREMENT` uses `LastInsertId()`. `UPDATE` and `DELETE` without `_returning` return `{"rows_affected": n}`. With `_returning`, that suffix is stripped and not sent to MySQL: update selects the post-image, delete selects the pre-image then deletes, both in one `REPEATABLE READ` transaction.

`Prest-Batch-Method: copy` is a transactional multi-row `INSERT`, not `LOAD DATA`.

These operators error on MySQL: `$all`, ltree, `$tsquery`, `vecdist`, and `FULL` join. `$ilike` becomes `LIKE` (the column collation decides case; pREST does not inject `LOWER()`). A JSON filter `col:jsonb` with `field->>attr` maps to `` `col`->>'$.attr' ``.

A missing table (MySQL error 1146) returns **404**, the same as a missing Postgres relation. Health responses name the active engine. `HAVING` filter values are bound on both engines.

**MCP is not part of this adapter.** `/_mcp` stays on the PostgreSQL family. That limit is **v2.5.0 only** and is lifted in [v2.5.1](/releases/v2.5.1.md). See [MySQL](/databases/mysql.md).

### JOIN access control ([#1032](https://github.com/prest/prest/pull/1032), [#1033](https://github.com/prest/prest/pull/1033))

Fixes [#364](https://github.com/prest/prest/issues/364) on the **PostgreSQL** adapter. With `restrict=true`, the SELECT list used to come only from the main table, so joined columns were dropped or could leak.

* A joined table adds only columns permitted for that operation and user, qualified with the joined table name. No read permission means no columns from that table.
* Main-table columns are qualified when a join is present, so names do not become ambiguous.
* `_select` accepts qualified fields and a validated `table.*`.

[#1033](https://github.com/prest/prest/pull/1033) also rejects duplicate and self-join targets (including schema-qualified names), rejects a malformed join before a partial result, and keeps multiple `_join` parameters in order.

### Middleware plugins ([#1039](https://github.com/prest/prest/pull/1039))

Fixes [#948](https://github.com/prest/prest/issues/948). The Docker image includes Go module files and the vendor directory so a plugin build shares the server’s module identity. `go-build.sh` builds `.so` middleware with vendor-aware flags. The loader accepts a factory and a direct handler. A missing plugin falls back to no-op middleware instead of failing the request path.

See [Middleware Plugin](/plugins/middleware-plugin.md).

### Dependency bumps ([#1055](https://github.com/prest/prest/pull/1055))

No API change. Direct bumps include:

| Module                                | From            | To         |
| ------------------------------------- | --------------- | ---------- |
| `github.com/go-jose/go-jose/v4`       | 4.1.4           | 4.1.5      |
| `github.com/lestrrat-go/jwx/v3`       | 3.2.0           | 3.3.0      |
| `github.com/go-sql-driver/mysql`      | 1.9.3           | 1.10.1     |
| OpenTelemetry (traces, metrics, logs) | 1.44 / log 0.20 | **1.47.0** |
| `google.golang.org/grpc`              | 1.82.1          | 1.83.2     |
| `golang.org/x/crypto`                 | 0.54.0          | 0.57.0     |

Studio dependencies were bumped and `internal/studio/dist` rebuilt. The notable major is `@tanstack/react-table` 8 → 9, with React 19.2 → 19.3. No new Studio routes.

The MySQL driver bump is not the adapter. The adapter is [#1048](https://github.com/prest/prest/pull/1048).

***

## Changes since v2.4.2

| PR                                                | Summary                                                                                              |
| ------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| [#1048](https://github.com/prest/prest/pull/1048) | MySQL 8 dialect adapter (`engine = "mysql"`), catalog, CRUD, ACL, stored queries                     |
| [#1032](https://github.com/prest/prest/pull/1032) | JOIN columns honour `restrict` table permissions ([#364](https://github.com/prest/prest/issues/364)) |
| [#1033](https://github.com/prest/prest/pull/1033) | Reject duplicate, self, and malformed joins; multiple `_join` values keep order                      |
| [#1039](https://github.com/prest/prest/pull/1039) | Middleware plugin build and load ([#948](https://github.com/prest/prest/issues/948))                 |
| [#1055](https://github.com/prest/prest/pull/1055) | Go and Studio dependency bumps; Studio dist rebuild                                                  |

Full detail: [compare v2.4.2...v2.5.0](https://github.com/prest/prest/compare/v2.4.2...v2.5.0). Commit list: [Changes since v2.4.2](/releases/main-since-v2.4.2.md).

***

## Upgrading from v2.4.2

1. Deploy `prest/prest:v2.5.0`, the matching binary, or `go install github.com/prest/prest/v2/cmd/prestd@v2.5.0`.
2. Leave `engine` unset to stay on PostgreSQL. Set `engine = "mysql"` only for a MySQL 8.0.19+ server. Do not point this adapter at MariaDB.
3. If you skipped [v2.4.2](/releases/v2.4.2.md), check `jwt.key` length first. A short HMAC key does not stop startup — it disables `/auth`. See [v2.4.2 — Upgrading](/releases/v2.4.2.md#upgrading-from-v241).

***

## Related

* [MySQL](/databases/mysql.md)
* [Databases](/databases.md)
* [Middleware Plugin](/plugins/middleware-plugin.md)
* [v2.4.2 release notes](/releases/v2.4.2.md)
* [Acronyms](/readme/acronyms.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.prestd.com/releases/v2.5.0.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
