Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
162 commits
Select commit Hold shift + click to select a range
529d21f
Native wire protocol, M1: constants, bounded codecs, framing, phase m…
quinnj Aug 22, 2026
5040339
Native wire protocol, M2a: authentication plugins, RSA-OAEP, STARTTLS
quinnj Aug 22, 2026
23e1342
Native wire protocol, M2b: MySQL.Native connect, options, reaper, liv…
quinnj Aug 22, 2026
e59d8f2
Native backend review pass: key lifetime, password hygiene, TLS close…
quinnj Aug 22, 2026
af3e196
Harden result metadata length validation
quinnj Aug 22, 2026
bd07d53
Enforce announced authentication protocol
quinnj Aug 22, 2026
aaf8c22
Correct native option resolution
quinnj Aug 22, 2026
8e3c359
Negotiate database selection capability
quinnj Aug 22, 2026
3996d35
Honor outbound bind addresses
quinnj Aug 22, 2026
20a8b95
Fault sessions when TLS setup fails
quinnj Aug 22, 2026
0459ca6
Bound LOCAL INFILE upload failures
quinnj Aug 22, 2026
b58d97e
Close reaper ownership race
quinnj Aug 22, 2026
426a821
Reject pre-TLS bytes from coalescing peers
quinnj Aug 22, 2026
77ff3a7
Reject malformed packet tails and oversized writes
quinnj Aug 22, 2026
104ae24
Close auth failures and wipe handshake copies
quinnj Aug 22, 2026
2efcfb9
Map resolver deadlines to native timeouts
quinnj Aug 22, 2026
524e6f5
Correct reaper lifecycle notes
quinnj Aug 22, 2026
1b14d89
Preserve timeout phase diagnostics
quinnj Aug 22, 2026
82374e7
Reject reserved codes in initial errors
quinnj Aug 22, 2026
b407a65
Cover result-stream deadline closure
quinnj Aug 22, 2026
dbffcdc
Complete macOS Julia test matrix
quinnj Aug 22, 2026
3c8626b
Honor option-file transport selection
quinnj Aug 22, 2026
2ea5aeb
Preserve optional legacy keyword defaults
quinnj Aug 22, 2026
4e850e8
Apply auth byte limits before allocation
quinnj Aug 22, 2026
712dc8c
Apply metadata limits before allocation
quinnj Aug 22, 2026
187a369
Reject excess result sets before reading
quinnj Aug 22, 2026
510c44a
Serialize reaper initialization
quinnj Aug 22, 2026
b8032c6
Bound outbound bind resolution
quinnj Aug 22, 2026
07efd08
Require a final charset bootstrap response
quinnj Aug 22, 2026
3b7d2d7
Propagate late init command errors
quinnj Aug 22, 2026
a9e6a1f
Parse standard option file escapes
quinnj Aug 22, 2026
0aeccdf
Reject conflicting preferred TLS enforcement
quinnj Aug 22, 2026
bbfae92
Reject optional include directives
quinnj Aug 22, 2026
49e57c5
Preserve init command timeout errors
quinnj Aug 22, 2026
b30b8b1
Fault malformed auth continuations
quinnj Aug 22, 2026
1920fcc
Fault malformed charset tracking data
quinnj Aug 22, 2026
6aaa798
Match bind addresses to remote families
quinnj Aug 22, 2026
b1a8360
Enforce authentication completion state
quinnj Aug 22, 2026
3f821cf
Parse UTF-8 option file fields safely
quinnj Aug 22, 2026
9c9d752
Respect TLS keyword source precedence
quinnj Aug 22, 2026
6c0e168
Expose connection-phase resource limits
quinnj Aug 22, 2026
e046e1f
Reject post-completion auth switches
quinnj Aug 22, 2026
e494e8f
Reject unavailable empty-host transport
quinnj Aug 22, 2026
8976b72
Accept MariaDB SET_OPTION EOF responses
quinnj Aug 22, 2026
07ffc35
Track active command response kinds
quinnj Aug 22, 2026
782a26c
Cover SET_OPTION vendor interop
quinnj Aug 22, 2026
f244258
Cover MariaDB 12.3 version normalization
quinnj Aug 22, 2026
1a29089
Cover TLS transport reaping
quinnj Aug 22, 2026
4a86b59
Cover expired-password sandbox handling
quinnj Aug 22, 2026
d88ad71
Parse SET_OPTION OK-as-EOF responses
quinnj Aug 22, 2026
1091cf7
Keep the default-plugin fallback when the server announces an unknown…
quinnj Aug 22, 2026
8f7451a
Protocol: cursor-owned row buffers, wire-type unsigned-ness, capabili…
quinnj Aug 22, 2026
192553e
Native: text-protocol value decoding and result options
quinnj Aug 22, 2026
8b53d30
Native: DBInterface connection and text-protocol cursors (M3)
quinnj Aug 22, 2026
dc7a88e
Executable compatibility manifest (text rows), live-lane wiring, M3 n…
quinnj Aug 22, 2026
1a217f4
fix(native): validate text temporal values
quinnj Aug 22, 2026
8aa64c9
fix(native): validate rows before retention
quinnj Aug 22, 2026
e786d7f
fix(native): complete local infile states
quinnj Aug 22, 2026
791e79c
fix(native): enforce connection ownership
quinnj Aug 22, 2026
94177de
fix(native): isolate cursor result lifetimes
quinnj Aug 22, 2026
d8d58b7
fix(protocol): recover before local infile data
quinnj Aug 22, 2026
3b706db
test(native): cover text result transitions
quinnj Aug 22, 2026
d61d949
fix(native): reject signed unsigned text values
quinnj Aug 22, 2026
954021f
fix(native): retain result warning snapshots
quinnj Aug 22, 2026
6291ddc
fix(native): preserve DML cursor length
quinnj Aug 22, 2026
fa587ab
fix(native): retain local infile error context
quinnj Aug 22, 2026
d997204
fix(native): preserve temporal compatibility
quinnj Aug 22, 2026
8bf44af
fix(native): preserve outer transaction ownership
quinnj Aug 22, 2026
fdf23e9
docs: record M3 cross-review
quinnj Aug 22, 2026
8f75fe7
feat(protocol): frame the prepared-statement commands and binary rows
quinnj Aug 22, 2026
64b00c4
feat(native): binary-protocol value codecs and parameter encoding
quinnj Aug 22, 2026
7d13472
feat(native): prepared statements and a protocol-generic cursor
quinnj Aug 22, 2026
78d7e02
test(native): binary-protocol fake-peer tests, manifest rows, and notes
quinnj Aug 22, 2026
9dbf8af
fix(protocol): validate prepare response headers
quinnj Aug 22, 2026
7a583c6
fix(protocol): validate binary row spans
quinnj Aug 22, 2026
4eef48d
fix(native): harden binary value decoding
quinnj Aug 22, 2026
58e0700
fix(native): preserve effective parameter wire types
quinnj Aug 22, 2026
e9b02a1
fix(protocol): preserve prepared error hierarchy
quinnj Aug 22, 2026
564ab12
fix(native): make statement parking lossless
quinnj Aug 22, 2026
60104fc
fix(native): close superseded statement ids
quinnj Aug 22, 2026
f3fe225
fix(native): preserve prepared API contracts
quinnj Aug 22, 2026
4726c5c
fix(native): charge binary cursor type storage
quinnj Aug 22, 2026
195b6d0
fix(native): apply refreshed prepared metadata options
quinnj Aug 22, 2026
d435f98
fix(native): close the statement reaper lifecycle
quinnj Aug 22, 2026
2f120f9
fix(native): revalidate parameters after reprepare
quinnj Aug 22, 2026
8aef1e6
test(native): cover prepared protocol contracts
quinnj Aug 22, 2026
6d1a47b
test(native): exercise every prepared parameter family
quinnj Aug 22, 2026
99dd0ea
fix(native): validate all binary date fields
quinnj Aug 22, 2026
6716259
test(protocol): cover prepared reset state
quinnj Aug 22, 2026
e8967a1
test(protocol): cover execute framing and spans
quinnj Aug 22, 2026
512bd95
fix(native): refresh execute-time metadata
quinnj Aug 22, 2026
327d797
fix(native): replay prepared long data
quinnj Aug 22, 2026
41b5b27
test(native): cover binary policy manifest
quinnj Aug 22, 2026
e2146c8
fix(native): isolate cached result metadata
quinnj Aug 22, 2026
9dc3aa0
test(native): reject invalid long-data binds
quinnj Aug 22, 2026
d1f0eaf
docs(native): describe prepared DBInterface surface
quinnj Aug 22, 2026
c5525b7
fix(protocol): scan legacy NEWDATE values
quinnj Aug 22, 2026
e774338
fix(native): preserve one-shot metadata options
quinnj Aug 22, 2026
ad1a454
test(native): exercise prepared CALL live
quinnj Aug 22, 2026
64446e1
docs: record M4 cross-review
quinnj Aug 22, 2026
10c7e59
fix(protocol): keep malformed-input failures inside MySQLError
quinnj Aug 22, 2026
964e0e9
test(fuzz): add the deterministic mutation fuzzer (plan §8.4)
quinnj Aug 22, 2026
7293b1d
perf(native): make the per-row hot path allocation-free
quinnj Aug 22, 2026
42e13a1
perf(protocol): batch command-phase reads through a read buffer
quinnj Aug 22, 2026
5cb8148
test(perf): add the §8.9 performance/allocation gates
quinnj Aug 22, 2026
a98728d
test(native): add the §8.10 leak/lifecycle soak
quinnj Aug 22, 2026
596e762
docs: add the migration guide and record the M5 decisions
quinnj Aug 22, 2026
29dc9d1
test: declare test-only stdlibs for Pkg.test and add reaper-flake dia…
quinnj Aug 22, 2026
08af1bb
fix(native): close reaped transports in the latest world
quinnj Aug 23, 2026
4846d6d
test(perf): run the timing gates with production bounds semantics
quinnj Aug 23, 2026
3ccb876
test(fuzz): enforce bounded reproducible coverage
quinnj Aug 23, 2026
08710df
test(perf): compare matched transport modes
quinnj Aug 23, 2026
7095cb8
test(native): finalize statements during active streams
quinnj Aug 23, 2026
04c68aa
docs: record matched M5 hardening evidence
quinnj Aug 23, 2026
806a66c
test(native): require abandoned cursor collection
quinnj Aug 23, 2026
d27d795
fix(protocol): harden version parsing, oversized auth, per-op timeout…
quinnj Aug 23, 2026
2d5f6e5
fix(native): per-op timeouts, retryable reconnect, option-file db, re…
quinnj Aug 23, 2026
b2134ec
fix(native): treat year 0000 as a legal date; big-endian BIT parameters
quinnj Aug 23, 2026
dab4f2c
ci,docs: gate perf timing on CI, bump to 1.7.0, pin Reseau 1.4.1, doc…
quinnj Aug 23, 2026
e2ea8bc
test: regressions for the review fixes and CI portability
quinnj Aug 23, 2026
20ed4ed
fix(protocol): match ASCII-only version digits (round-2 review)
quinnj Aug 23, 2026
eb0959f
fix(protocol): close abandoned prepared statement ids
quinnj Aug 23, 2026
4475dd4
fix(protocol): validate structured response metadata
quinnj Aug 23, 2026
8457940
fix(native): honor deterministic transport selection
quinnj Aug 23, 2026
20080d2
fix(native): secure load identifiers and debug logs
quinnj Aug 23, 2026
bf9133b
fix(native): make finalizer enqueue allocation-free
quinnj Aug 23, 2026
e7585df
fix(protocol): avoid response counter overflow
quinnj Aug 23, 2026
540a410
fix(native): accept callable infile handlers
quinnj Aug 23, 2026
33ea6b3
fix(protocol): validate GTID state encoding
quinnj Aug 23, 2026
d6cf94a
fix(native): enforce streaming response ownership
quinnj Aug 23, 2026
c3c71c4
fix(protocol): defer metadata allocation until validated
quinnj Aug 23, 2026
85a36b2
fix(protocol): reject empty system-variable state
quinnj Aug 23, 2026
885648f
style(native): follow repository function conventions
quinnj Aug 23, 2026
dd85d5e
ci: enforce native source and coverage gates
quinnj Aug 23, 2026
728a68b
docs: correct timeout and reaper contracts
quinnj Aug 23, 2026
f243d75
test: complete the native compatibility manifest
quinnj Aug 23, 2026
6dc35a9
fix(native): bound numeric connection options
quinnj Aug 23, 2026
d4e5529
fix(native): keep multi-result streams task-owned
quinnj Aug 23, 2026
cd8446b
fix(protocol): wipe authentication scratch buffers
quinnj Aug 23, 2026
25db2de
fix(protocol): accept short set-option EOF
quinnj Aug 23, 2026
a3c4e39
fix(protocol): reject invalid DATE lengths
quinnj Aug 23, 2026
54bbffa
fix(protocol): reject deferred VECTOR columns
quinnj Aug 23, 2026
8ffc698
fix(native): accept omitted named-pipe option
quinnj Aug 23, 2026
981a40b
fix(native): discard invalid long data
quinnj Aug 23, 2026
986ef20
fix(native): secure prequoted load identifiers
quinnj Aug 23, 2026
5b3f552
fix(native): honor infile handlers during init
quinnj Aug 23, 2026
e93a9a7
fix(protocol): reject invalid UTF-8 metadata
quinnj Aug 23, 2026
73e5e50
docs: record M6 cross-review verdict
quinnj Aug 23, 2026
95b582d
fix(ci): keep performance correctness gates active
quinnj Aug 23, 2026
4b52cd5
docs: add final performance-gate finding
quinnj Aug 23, 2026
48ac6ff
docs: note the localhost/protocol=:tcp rule; file the M6 cross-review
quinnj Aug 23, 2026
5a5b48b
test: fix Windows portability (Clong width, Docker skip)
quinnj Aug 23, 2026
2b06898
ci: run §8.9 scale gates only in the perf job, raise test timeout
quinnj Aug 23, 2026
919ecb0
ci: decouple coverage from the test matrix into a fast serverless job
quinnj Aug 24, 2026
48b7b60
ci: split Docker integration into its own Linux/1.10 job; keep the ma…
quinnj Aug 24, 2026
666a327
docs: drop the cross-review records from the repo
quinnj Aug 24, 2026
ace0bce
feat!: MySQL.jl 2.0 — the native wire protocol is the only backend
quinnj Aug 24, 2026
1cb7b9f
test: JuliaC --trim=safe workload and compile harness
quinnj Aug 24, 2026
76d53ac
bench: cross-driver benchmark harness
quinnj Aug 24, 2026
ddb28d6
perf: near-zero-alloc per-command send and cursor paths (§8.9 round-t…
quinnj Aug 24, 2026
e059b2d
fix(trim): runtime callbacks actually run in trimmed executables
quinnj Aug 24, 2026
8fcb7fe
feat: direct_wait_ms connect option (bounded direct polling)
quinnj Aug 24, 2026
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
122 changes: 122 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,26 @@ on:
branches: [main]
tags: ["*"]
pull_request:
schedule:
# nightly deterministic fuzz budget (plan §8.4); the smoke batch runs in every test job
- cron: "17 6 * * *"
workflow_dispatch:
jobs:
cleanroom:
name: Native clean-room source check
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: julia-actions/setup-julia@v2
with:
version: "1.10"
- run: julia --startup-file=no scripts/check_native_cleanroom.jl
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
if: github.event_name != 'schedule'
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
Expand All @@ -17,25 +33,131 @@ jobs:
- nightly
os:
- ubuntu-latest
- macOS-latest
- windows-latest
arch:
- x64
exclude:
- os: macOS-latest
arch: x64
include:
- os: macOS-latest
arch: aarch64
version: "1.10"
- os: macOS-latest
arch: aarch64
version: 1
- os: macOS-latest
arch: aarch64
version: nightly
steps:
- uses: actions/checkout@v5
# The wire-protocol tests need no server; the server integration tests run only
# where Docker is available (Linux runners).
- run: docker info
if: runner.os == 'Linux'
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
# The cross-platform matrix runs the serverless protocol suite only (MYSQL_INTEGRATION=0):
# it is fast, needs no server, and the Docker integration (live lanes + leak soak +
# the server integration tests) runs in the dedicated `integration` job instead.
# Coverage is measured by the `coverage` job.
- uses: julia-actions/julia-runtest@v1
with:
coverage: false
env:
MYSQL_INTEGRATION: "0"
integration:
# Live lanes (mysql:8.4, mariadb:11.4), the golden behavior manifest, the leak/lifecycle
# soak, and the server integration tests, all against real servers via Harbor. Linux-only
# (Docker) and pinned to Julia 1.10, whose GC is stable under the soak's GC-thrash (1.12+
# can hang on shared runners).
name: Integration (Docker)
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@v5
- run: docker info
- uses: julia-actions/setup-julia@v2
with:
version: "1.10"
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
with:
coverage: false
coverage:
# Line-coverage gate (plan §8.15). The serverless fake-peer suite alone covers ~96% of
# src/, so the gate needs neither Docker nor the leak soak and stays fast; it also
# feeds codecov.
name: Native coverage
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v5
- uses: julia-actions/setup-julia@v2
with:
version: "1"
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- run: julia --project=. --code-coverage=@src --startup-file=no -e 'include("test/protocol/runtests.jl")'
- uses: julia-actions/julia-processcoverage@v1
- run: julia --startup-file=no scripts/check_native_coverage.jl lcov.info 0.85
- uses: codecov/codecov-action@v5
with:
files: lcov.info
token: ${{ secrets.CODECOV_TOKEN }}
fuzz:
# Budgeted mutation fuzzing in isolated worker processes (test/protocol/fuzz.jl via
# scripts/fuzz.jl); scheduled nightly, or run on demand with workflow_dispatch.
name: Nightly fuzz
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v5
- uses: julia-actions/setup-julia@v2
with:
version: "1"
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- run: julia --project=. scripts/fuzz.jl --minutes 30 --seed $(date +%Y%m%d)000000 --out fuzz_failures
- uses: actions/upload-artifact@v4
if: failure()
with:
name: fuzz-failures
path: fuzz_failures/
perf:
# §8.9 gates (correctness/allocation) plus the wall-clock timing report. They are too
# heavy for the shared PR test lanes, so they run here on the nightly schedule and on
# demand (MYSQL_PERF_GATES=1), with coverage off. Cross-driver comparisons (MySQL.jl 1.x,
# other clients) live in bench/, outside CI.
name: Performance gates (§8.9)
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v5
- run: docker info
- uses: julia-actions/setup-julia@v2
with:
version: "1"
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
with:
coverage: false
env:
MYSQL_PERF_GATES: "1"
docs:
name: Documentation
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@ deps/build.log
Manifest.toml

.vscode/

# Documentation build and native-backend artifacts
docs/build/
fuzz_failures/
*.cov
19 changes: 12 additions & 7 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
name = "MySQL"
uuid = "39abe10b-433b-5dbd-92d4-e302a9df00cd"
author = ["quinnj"]
version = "1.6.0"
version = "2.0.0"

[deps]
DBInterface = "a10d1c49-ce27-4219-8d33-6db1a4562965"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd"
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
MariaDB_Connector_C_jll = "aabc7e14-95f1-5e66-9f32-aea603782360"
OpenSSL_jll = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
Parsers = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Reseau = "802f3686-a58f-41ce-bb0c-3c43c75bba36"
SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce"
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"

[compat]
Chairmarks = "1.3"
DBInterface = "2.5"
DecFP = "0.4.9, 0.4.10, 1"
Harbor = "1.0.3"
MariaDB_Connector_C_jll = "3.1.12"
OpenSSL_jll = "3"
Parsers = "0.3, 1, 2"
Parsers = "2"
Random = "1"
Reseau = "1.4.1"
SHA = "0.7.0, 1"
Tables = "1"
julia = "1.10"

[extras]
Chairmarks = "0ca39b1e-fe0b-4e98-acfc-b1656634c4de"
Harbor = "af79dbb9-1a80-47ad-8928-192a4af69376"
Sockets = "6462fe0b-24de-5631-8697-dd941f90decc"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Harbor", "Sockets", "Test"]
test = ["Chairmarks", "Harbor", "Logging", "Printf", "Test"]
56 changes: 38 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,41 @@

# MySQL

[![docs](https://img.shields.io/badge/docs-latest-blue&logo=julia)](https://mysql.juliadatabases.org/dev/)
[![CI](https://github.com/JuliaDatabases/MySQL.jl/workflows/CI/badge.svg)](https://github.com/JuliaDatabases/MySQL.jl/actions?query=workflow%3ACI)
[![codecov](https://codecov.io/gh/JuliaDatabases/MySQL.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaDatabases/MySQL.jl)

[![deps](https://juliahub.com/docs/MySQL/deps.svg)](https://juliahub.com/ui/Packages/MySQL/xeTdU?t=2)
[![version](https://juliahub.com/docs/MySQL/version.svg)](https://juliahub.com/ui/Packages/MySQL/xeTdU)
[![pkgeval](https://juliahub.com/docs/MySQL/pkgeval.svg)](https://juliahub.com/ui/Packages/MySQL/xeTdU)

Package for interfacing with MySQL databases from Julia via the MariaDB C connector library, version 3.1.6.

## Documentation

[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://mysql.juliadatabases.org/stable)
[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://mysql.juliadatabases.org/dev)


# MySQL

[![docs](https://img.shields.io/badge/docs-latest-blue&logo=julia)](https://mysql.juliadatabases.org/dev/)
[![CI](https://github.com/JuliaDatabases/MySQL.jl/workflows/CI/badge.svg)](https://github.com/JuliaDatabases/MySQL.jl/actions?query=workflow%3ACI)
[![codecov](https://codecov.io/gh/JuliaDatabases/MySQL.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaDatabases/MySQL.jl)

[![deps](https://juliahub.com/docs/MySQL/deps.svg)](https://juliahub.com/ui/Packages/MySQL/xeTdU?t=2)
[![version](https://juliahub.com/docs/MySQL/version.svg)](https://juliahub.com/ui/Packages/MySQL/xeTdU)
[![pkgeval](https://juliahub.com/docs/MySQL/pkgeval.svg)](https://juliahub.com/ui/Packages/MySQL/xeTdU)

Package for interfacing with MySQL databases from Julia.

Since 2.0, MySQL.jl implements the MySQL client/server wire protocol natively in Julia
(built on [Reseau.jl](https://github.com/JuliaServices/Reseau.jl) for TCP/TLS) — no C
client library. 1.x used the MariaDB Connector/C library; see the
[migration guide](https://mysql.juliadatabases.org/dev/migration/) for the differences.

## Documentation

[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://mysql.juliadatabases.org/stable)
[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://mysql.juliadatabases.org/dev)

## Usage

```julia
conn = DBInterface.connect(MySQL.Connection, host, user, passwd; db="mydb", port=3306)
cursor = DBInterface.execute(conn, "SELECT * FROM mytable") # a Tables.jl-compatible cursor
stmt = DBInterface.prepare(conn, "INSERT INTO mytable (a, b) VALUES (?, ?)")
DBInterface.execute(stmt, (1, "two"))
DBInterface.close!(conn)
```

`DBInterface.execute`/`prepare`/`executemany`/`executemultiple`, Tables.jl cursors,
`MySQL.load`, and transactions are all supported; see the
[documentation](https://mysql.juliadatabases.org/dev/). The transport is TCP or TLS
(no Unix sockets, named pipes, or compression yet — these raise clear errors).

## Contributing

The test suite manages its own temporary MySQL container via Harbor.jl. The only prerequisite is a working Docker daemon:
Expand Down
40 changes: 40 additions & 0 deletions bench/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Cross-driver benchmarks

Before 2.0, `test/perf/perf_gates.jl` asserted native-vs-Connector/C timing ratios inside
`Pkg.test`. Those ratio gates retired with the C backend; the in-repo §8.9 gates now assert
correctness, allocation budgets, and buffer limits, and print a wall-clock timing report.

This directory keeps the cross-driver comparison repeatable:

```sh
julia --project=. bench/run.jl
```

builds two temp environments — the current checkout (native) and `MySQL@1` (MariaDB
Connector/C) from the registry — starts the same Docker fixture servers the §8.9 gates use
(`mysql:8.4`, `--max-allowed-packet=128M`, TLS disabled), runs `bench/child.jl` once per
environment, and prints per-benchmark seconds plus the mysql@1/native ratio (>1x means the
native client is faster).

Reference numbers (macOS ARM, Docker, Julia 1.12, this harness after the 2.0 round-trip
perf round; ratio is mysql@1 time / native time, >1x = native faster):

| benchmark | native | mysql@1 (Connector/C) | speed |
|---|---|---|---|
| 100k executemany | 16.97s | 23.46s | 1.38x |
| 1M-row text scan | 0.4512s | 0.5098s | 1.13x |
| 1M tiny/NULL rows | 0.1780s | 0.2018s | 1.13x |
| 1M-row binary (prepared) scan | 0.2866s | 0.2978s | 1.04x |
| 64 MiB blob fetch | 0.0591s | 0.0551s | 0.93x |
| 10k round trips (plain) | 2.701s | 2.292s | 0.85x |

Per-command costs after the round: COM_PING 3 allocs, buffered `SELECT 1` 35 allocs,
repeated prepared execute 22 allocs (framed directly into the output buffer, cached
statement schema, lazy name lookup). The remaining round-trip gap vs the C client is
task-wakeup latency in the transport layer (a blocking `recv` wakes the C client directly;
the native client parks on the poller and pays a second thread wake ≈17µs). The
`direct_wait_ms` connect option (with a Reseau newer than 1.4.1, see Reseau PR #152)
removes that second wake by blocking the waiting task's own OS thread in a bounded
`poll(2)`: measured ~10-15µs less per round trip against Docker (COM_PING ~150 → ~135µs,
20k-row executemany −13%) at the cost of other tasks on that thread waiting up to the
budget.
Loading
Loading