Files
Joseph Doherty 63372e757a feat(sql): MySql provider over MySqlConnector, one shared provider map (lmxopcua#753)
SqlProvider.MySql is now a constructed backend instead of a reserved name.

- MySqlDialect (Driver.Sql.Dialect): MySqlConnector 2.6.2 (MIT, fully managed,
  no vulnerable packages), backtick quoting with MySQL's 64-char / no-trailing-
  space rules, information_schema catalog SQL with the database as the schema
  (system databases excluded, aliases pinned), trailing LIMIT, a type map that
  also reads the reader-side spellings (INT UNSIGNED -> UInt32, BOOL -> Boolean).
- SqlDialects: the one provider -> dialect map. The factory, the Test Connect
  probe and the browse picker each carried their own switch (and drifted once);
  they now all read this, and their refusals list the supported/reserved sets
  from it.
- AdminUI driver form offers MySql.
- Tests: MySqlDialectTests (golden quoting/catalog/type map/planner SQL); the
  provider-gate tests in factory, probe, browser and form now treat MySql as
  supported and Odbc as the reserved control. MySqlReadTests + Docker/mysql
  (throwaway mysql:8.4, SELECT-only login): liveness, KV/wide-row/topByTimestamp,
  INT keys vs authored text, case folding against case-sensitive table names,
  catalog rejection, browse walk, factory+probe, named query with a bound
  parameter, and a writing stored function whose effect the rolled-back
  transaction discards.

(lmxopcua#753)

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
2026-11-09 17:30:31 -05:00

66 lines
2.8 KiB
YAML

# Dedicated, DISPOSABLE MySQL 8 for the Sql driver's MySql live gate (MySqlReadTests, lmxopcua#753).
#
# ── SAFETY ─────────────────────────────────────────────────────────────────────
# This stack owns its OWN container, `otopcua-sql-mysql`, on host port 13306, with
# `restart: "no"` so a killed container stays down. Nothing else on the rig runs MySQL.
# Tear it down when done: docker compose down -v
#
# ── RUN IT (any docker host — a laptop is fine) ────────────────────────────────
# cd tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.IntegrationTests/Docker/mysql
# SQL_MYSQL_PASSWORD=... docker compose up -d # the one-shot seed applies seed-mysql.sql
#
# export SQL_MYSQL_ENDPOINT=127.0.0.1:13306
# export SQL_MYSQL_PASSWORD=... # the value the stack was brought up with
# dotnet test tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.IntegrationTests \
# --filter "FullyQualifiedName~MySqlReadTests"
#
# docker compose down -v
#
# `--log-bin-trust-function-creators=1` lets the seed create `bump_counter()`, a stored function
# that WRITES; the named-query suite calls it through a SELECT to prove the driver's rolled-back
# transaction discards a side effect the read-only guard cannot see.
name: otopcua-sql-mysql
services:
mysql:
image: mysql:8.4
container_name: otopcua-sql-mysql
labels:
project: lmxopcua
restart: "no"
command: ["--log-bin-trust-function-creators=1"]
environment:
# Dev-only sandbox password for a throwaway container; the seed gives the unprivileged
# `otopcua` login the SAME value, which is what the suite reads from SQL_MYSQL_PASSWORD.
MYSQL_ROOT_PASSWORD: "${SQL_MYSQL_PASSWORD:-Sqlmysql_dev_pw1}"
ports:
- "13306:3306"
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p\"$$MYSQL_ROOT_PASSWORD\" --silent"]
interval: 5s
timeout: 5s
retries: 24
start_period: 20s
# One-shot seed: waits for the healthcheck, applies seed-mysql.sql as root, exits.
mysql-seed:
image: mysql:8.4
labels:
project: lmxopcua
restart: "no"
depends_on:
mysql:
condition: service_healthy
environment:
MYSQL_PWD: "${SQL_MYSQL_PASSWORD:-Sqlmysql_dev_pw1}"
APP_PASSWORD: "${SQL_MYSQL_PASSWORD:-Sqlmysql_dev_pw1}"
volumes:
- ./seed-mysql.sql:/seed.sql:ro
entrypoint:
- "/bin/sh"
- "-c"
# The app password is substituted into the seed on the way in (MySQL has no psql-style
# variables); --force is NOT used, so a broken seed fails the service.
- "sed \"s/__APP_PASSWORD__/$${APP_PASSWORD}/g\" /seed.sql | mysql -h mysql -uroot"