Add MySQL backend - #872
Draft
phdoerfler wants to merge 1 commit into
Draft
Conversation
Draft
phdoerfler
marked this pull request as ready for review
July 14, 2026 19:57
phdoerfler
force-pushed
the
topic/mysql-backend
branch
2 times, most recently
from
July 17, 2026 20:49
9942895 to
69012fd
Compare
phdoerfler
force-pushed
the
topic/mysql-backend
branch
4 times, most recently
from
August 20, 2026 10:44
c183e02 to
051fa24
Compare
Member
|
This will need rebasing. |
phdoerfler
force-pushed
the
topic/mysql-backend
branch
from
August 30, 2026 00:34
051fa24 to
616bf17
Compare
phdoerfler
marked this pull request as draft
August 30, 2026 07:50
phdoerfler
force-pushed
the
topic/mysql-backend
branch
4 times, most recently
from
August 30, 2026 22:09
19645fc to
93f95c5
Compare
Member
|
Needs to be set "Ready for review" (assuming that it is 😄 ). |
Member
|
Actually, I could do with some clarification on the "Known follow-up" section of the description ... is this still accurate? |
phdoerfler
force-pushed
the
topic/mysql-backend
branch
from
August 31, 2026 09:32
93f95c5 to
66b96d9
Compare
phdoerfler
force-pushed
the
topic/mysql-backend
branch
from
August 31, 2026 17:19
66b96d9 to
6ea775b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This adds MySQL as a backend, same procedure as the SQLite (#864) and H2 (#866) PRs.
The mysql-connector-j driver is GPLv2 with the Universal FOSS Exception. It is added as a plain compile dependency (similar to the Oracle backend).
The first supported version of MySQL is 8.0.14+ (the first version with support for
LATERALjoins). The CI tests against a newer version but the old one has been tested separately, too. In particular: the tests pass for 8.0.14, 8.0.46, and 8.4 (current LTS), via aMYSQL_VERSIONoverride on the docker-compose service. It is reproducible withMYSQL_VERSION=8.0.14 sbt doobiemysql/test.Dialect notes
NULLS FIRST/LAST; its default is nulls-low (NULLs sort first under ASC, last under DESC). Emulated with aCASE WHEN col IS NULL THEN 1 ELSE 0 ENDsort-key prefix, added only where the requested placement differs from the default. Covered by the sharedSqlNullOrderingSuite, which needed amysql.sqlfor thenull-orderingdataset and is wired here now. It orders and limits so the SQL-level placement is observable: grackle re-sorts fetched rows in memory, so a whole-response comparison cannot catch a dialect ordering bug, only a LIMIT cut can.OFFSETis illegal withoutLIMIT, same as SQLite, so it reuses SQLite's comma-form rendering (LIMIT offset, limit) and the samenormalizeOffsetLimitmechanism. MySQL has noLIMIT -1idiom, so an offset-without-limit query getsInt.MaxValueas a practical "unbounded" sentinel instead.*_cicollations make plainLIKEcase-insensitive already, so it's the case-sensitive branch that needs an explicitCOLLATE(now an overridablebinaryCollationmember, defaultutf8mb4_bin, for mappings over a non-default charset/collation).DISTINCT+ theFirstValueColumnwindow-function strategy already used by the MSSQL backend.CASTonly accepts a small fixed set of target names, not arbitrary column types — mapped explicitly; anything without a safe CAST target (e.g.FLOAT/DOUBLE, sinceCAST(... AS DOUBLE)needs 8.0.17, above this backend's 8.0.14 floor) renders a bareNULLinstead, which is safe since an ascribed NULL is only ever an inference hint.ORDER BY/LIMIT/OFFSETare legal, so no derived-table encapsulation is needed (unlike SQLite, which forbids this entirely).INSERT ... RETURNING, no sequences.AUTO_INCREMENT+ JDBC generated-keys (withUniqueGeneratedKeys), same pattern as the Oracle backend.Schema-qualified tables
The
qualified-namesandunion-orderdatasets put their tables in a schema. In MySQL a schema is a database, soCREATE SCHEMA qualifiedworks, but the image grants the test user rights on its own database only and every query against the new one comes backSELECT command denied. The dataset'smysql.sqltherefore grants them.Test infrastructure
The official
mysqldocker image'sdocker-entrypoint-initdb.dfixture loader negotiates alatin1client handshake by default, which double-encodes the UTF-8 fixture literals (accented city/country names).--skip-character-set-client-handshakewas removed in MySQL 8.3+, and a bind-mountedmy.cnfisn't reliable in every dev environment (some setups force bind-mounted files world-writable, whichmysqlrefuses to read). Worked around with a smallentrypoint.shthat writes a[client] default-character-set=utf8mb4config file fresh inside the container before handing off to the stock entrypoint.Disclaimer
This work was made in conjunction with an LLM.