Revision history for DBIO-MySQL

0.900001  2026-07-12
    * Storage
        - Add DBIO::MySQL::Storage::Async and DBIO::MySQL::Storage::MariaDB::Async,
          the real future_io async adapter. It drives whichever DBD the DSN
          named: the base class carries DBD::mysql's async binding (async /
          mysql_fd / mysql_async_ready / mysql_async_result / mysql_insertid),
          and the MariaDB subclass overrides five DBD-specific primitives with
          DBD::MariaDB's mariadb_* binding -- mirroring the sync mysql_insertid /
          mariadb_insertid split, so a dbi:mysql: connection uses DBD::mysql's
          async and a dbi:MariaDB: connection uses DBD::MariaDB's. Subclasses
          DBIO::Async::Storage and fills only the DB-specific seams
          (_submit_query / _collect_result, socket fd, insertid folded onto the
          autoinc PK in place of RETURNING); Model-B orchestration is inherited.
          Convention-resolved off the leaf driver storage (ADR 0030) — no
          registration. Pipeline is unsupported (one async query per connection).
        - Register the 'ev' async mode (core ADR 0030): connect(..., { async => 'ev' })
          now resolves DBIO::MySQL::EV::Storage via the core mode registry;
          this shadows the generic modes registered on DBIO::Storage::DBI
          and replaces the obsolete async_backend() / load_components('MySQL::EV')
          opt-ins. Requires the optional dbio-mysql-ev dist at first use;
          absent → the canonical "install DBIO::MySQL::EV::Storage" croak (ADR 0030).
        - Reference-driver compliance for the storage-layer composition model
          (karr #22, core #70): storage_type is written at exactly two sites,
          both driver Schema components (DBIO::MySQL -> DBIO::MySQL::Storage,
          DBIO::MySQL::MariaDB -> DBIO::MySQL::Storage::MariaDB) -- the
          driver's job; extensions register plain storage LAYERS instead of
          subclassing storage_type. Inherits transport_capabilities =>
          (on_connect_replay); MySQL/MariaDB have no LISTEN/NOTIFY/COPY
          (documented), pipelining stays on the ev backend. The driver was
          already future_io-compliant -- MySQL keeps '?' natively, so
          _transform_sql is identity, run once inside the inherited
          DBIO::Async::Storage transport (no double-shaping). No behavioural
          change -- POD/comments + driver-level structural tests only.

    * Documentation
        - Add docs/adr/0030-async-mode-registration.md — per-repo operationalisation
          of the core async mode registry mechanism for the MySQL driver
        - Add docs/adr/0007-async-transport-mirrors-the-sync-dbd-split.md —
          records why the future_io adapter mirrors the sync mysql_*/mariadb_*
          DBD split (one base class plus a MariaDB-flavoured subclass) instead
          of a single generic transport

    * Security
        - Add SECURITY.md following the CPAN Security Group's Guidelines for
          Adding a Security Policy to Perl Distributions (v1.5.0): email-first
          private reporting to the maintainer

    * Bugfixes
        - Diff: suppress the standalone DROP INDEX that collided with DROP TABLE
          in a full-schema sync (karr #23). When a whole table is removed in the
          same diff pass, DROP TABLE already drops that table's own indexes;
          as_sql runs tables before indexes, so the later DROP INDEX ... ON
          <table> targeted an already-gone table and failed on a real server.
          DBIO::MySQL::Diff now threads the source/target tables sections into
          Diff::Index->diff (as it already does for Diff::Column /
          Diff::ForeignKey), and Diff::Index skips the drop for any index whose
          owning table is itself being dropped. Indexes removed from a surviving
          table are unaffected. Backward compatible: absent table args -> no
          suppression.
        - Fix the native introspect->diff round-trip against a real MySQL 8
          server, which produced phantom diffs (every column reported as a
          spurious add) and a zero-date write failure: information_schema
          result columns come back UPPERCASE on MySQL 8, so Columns/
          ForeignKeys/Indexes now force NAME_lc on their fetches; MySQL
          8.0.17+ drops the integer display width in information_schema
          (bigint(20) -> bigint), now normalised on both sides in
          Diff::Column (tinyint(1) and the semantic decimal/char widths stay
          untouched); target_from_compiled no longer synthesises a literal
          'NULL' default for nullable no-default columns (information_schema
          reports SQL NULL as undef, not the string); and a new
          connect_call_set_zero_date_permissive on_connect seam relaxes
          strict sql_mode on every (re)connect, not just the deploy-time
          handle, so zero-date writes survive reconnects
        - Remove t/30-versioning.t and its DBIOVersion_v1/v2/v3 fixtures; the
          test exercised DBIO::Schema::Versioned, which core retired (its
          upgrade path depended on the hard-deprecated create_ddl_dir, with
          no native replacement -- core karr #74)
        - Remove t/01-access-broker-api.t, which required the undeclared and
          since-removed DBIO::AccessBroker::Credentials and broke the test
          suite on a clean install (Codeberg #1)
        - Make the table-name assertions in t/50-introspect-contract.t
          quote-agnostic; the code generator emits double-quoted strings via
          B::perlstring

    * Dependencies
        - Require DBIO 0.900001 (central private-attr strip in
          DBIO::Storage::Async::connect_info, on which both the sync and the
          future_io path rely)
        - DBIO::Async, the shared future_io backend base the async adapter
          subclasses, is deliberately NOT declared in cpanfile: it is
          optional and convention-resolved at runtime (ADR 0030), only
          pulled when { async => 'future_io' } is used, so a sync-only
          install never drags in the async stack. Core's future_io resolver
          now names the missing module and the distribution that provides
          it when the adapter can't load (core karr #78), so a separate
          recommends pointer is no longer needed.
        - Add a runtime suggests on DBD::mysql alongside the recommended
          DBD::MariaDB, so both supported DBD drivers are advertised in the
          metadata (DBD::MariaDB stays the default, DBD::mysql the alternative)
        - Drop a stray test-phase recommends on Kubernetes::REST, an unused
          copy-paste leftover from another distribution

    * Tests
        - Add maint/docker/ (karr #21): a Docker test image for a buildable,
          live DBD::mysql -- ubuntu:24.04's libmysqlclient-dev is still the
          genuine Oracle MySQL client (Debian switched its default provider to
          MariaDB, and the MySQL APT repo's own signing key has expired),
          sidestepping both the wrong-flavour and wrong-signature roadblocks.
          Live-verified the mysql_* future_io transport (t/55) against a real
          mysql:8.0 server -- non-blocking select/insert/select_single,
          mysql_insertid folded onto the autoinc PK, txn_do_async commit and
          rollback, and the high-level create_async/all_async API -- mirroring
          the already-live mariadb_* subclass

0.900000  2026-06-23
    First release. MySQL and MariaDB driver for DBIO, with native schema
    deployment, introspection, diffing and DDL generation.

    * Driver
        - MySQL/MariaDB storage with autodetection of dbi:mysql: DSNs via
          the DBIO driver registry
        - DBIO::MySQL schema component and -mysql shortcut
        - DBIO::MySQL::Storage and DBIO::MySQL::Storage::MariaDB
        - DateTime::Format::MySQL datetime parsing

    * SQLMaker
        - DBIO::MySQL::SQLMaker with apply_limit() (LIMIT ?, ? syntax) and
          FOR SHARE locking
        - DBIO::MySQL::SQLMaker::MariaDB maps FOR SHARE to LOCK IN SHARE
          MODE for MariaDB

    * Schema management
        - DBIO::MySQL::Introspect (Tables, Columns, Indexes, ForeignKeys)
          via information_schema
        - DBIO::MySQL::DDL generator from Result classes with
          ENGINE/CHARSET/COLLATE handling, view and shared-table handling
        - DBIO::MySQL::Diff (Table, Column, Index, ForeignKey) with inlined
          columns on CREATE TABLE and full MODIFY COLUMN support
        - DBIO::MySQL::Deploy: install/diff/apply/upgrade via test-deploy-
          and-compare against a temporary database
        - Storage routes DBIO::Schema->deploy() through DBIO::MySQL::Deploy

    * Result component
        - DBIO::MySQL::Result with mysql_engine, mysql_charset,
          mysql_collate and mysql_index declarations consumed by the DDL
          generator
