Skip to content

[RFC]: Document the MySQL >= 8.0.19 / PHP >= 8.3 support floor and cover ALTER TABLE drop paths with MySQL tests #80

Description

@simon-mundy

Proposed Version

Docs: 0.4.1 (0.4.x). CI and tests: 0.5.0 (0.5.x).

Basic Information

State a support floor of MySQL >= 8.0.19 and PHP >= 8.3, exercise the floor and the current LTS releases in CI, and add the adapter's first DDL tests — AlterTable drop paths and table options. One small docs PR in core corrects alter-drop.md and the "MySQL/MariaDB" wording.

Background

AlterTable::dropConstraint($name) renders DROP CONSTRAINT <name> (AlterTable.php#L74-L78, #L254-L262) and the MySQL AlterTableDecorator leaves it alone. MySQL supports that general form from 8.0.19 for any named constraint. Verified on 8.4.10 (reproduced on 8.0.46):

ALTER TABLE `t` DROP CONSTRAINT `fk_parent`   -- FOREIGN KEY: OK
ALTER TABLE `t` DROP CONSTRAINT `uq_email`    -- UNIQUE:      OK
ALTER TABLE `t` DROP CONSTRAINT `chk_age`     -- CHECK:       OK
ALTER TABLE `t` DROP CONSTRAINT `PRIMARY`     -- PRIMARY KEY: OK
ALTER TABLE `t` DROP CONSTRAINT `idx_name`    -- plain INDEX: ERROR 3940: Constraint 'idx_name' does not exist.
ALTER TABLE `t` DROP INDEX `idx_name`         -- via dropIndex(): OK

So the rendering is right for the versions we intend to support — but nothing says what those are:

  • No MySQL version statement in the README or docs. Core docs go the other way and advertise "MySQL/MariaDB" (docs/book/index.md:20, docs/book/adapter.md:24).
  • CI runs the floating mysql:8.0 image (.github/workflows/continuous-integration.yml) via the shared phpdb-qa-tools reusable workflow, which takes one db-image string and has no matrix. That image is a late 8.0.4x, so the floor is never exercised.
  • Core docs/book/sql-ddl/alter-drop.md shows DROP CONSTRAINT as universal output and only warns about SQLite (advanced.md).
  • test/unit/Sql/Ddl/AlterTableDecoratorTest.php covers column options only. dropConstraint(), dropIndex(), dropColumn() and table options have no adapter test, and there are no DDL integration tests at all — tables come from the raw mysql.sql fixture.
  • PHP ~8.3.0 || ~8.4.0 || ~8.5.0 is in composer.json but not in the README either.

Considerations

  • Name clashes. MySQL raises ERROR 3939 ("Table has multiple constraints with the name ... Please use constraint specific DROP clause") when a FOREIGN KEY shares its name with another constraint — UNIQUE or CHECK. A same-named plain index is not a conflict; MySQL drops the FK and leaves its auto-created index behind. In the 3939 case typed helpers (dropForeignKey(), dropCheck(), ...) are the only way out, and core cannot emit DROP FOREIGN KEY at all today. That is a core follow-up rather than part of this.
  • Error assertions. InvalidQueryException carries no errno, so a test has to catch the driver exception: mysqli_sql_exception::getCode() === 3940, or for PDO getCode() === 'HY000' with errorInfo[1] === 3940.
  • Table options. ENGINE and COMMENT take quoted strings; ALGORITHM and LOCK only work when passed as a Literal (a plain string renders ALGORITHM = 'INPLACE', which MySQL rejects with 1064). The tests pin the generic setOption() mechanism as it stands; typed keyword options are proposed in the core statements umbrella, [RFC]: DDL standalone index, view, rename and truncate statements, and typed table options phpdb#179.
  • Images. As of September 2026 mysql:lts resolves to 9.7 and 8.4 is the previous LTS. One uses: job per image, since the reusable workflow only takes one. Untested assumption: a 2020-era mysql:8.0.19 image still boots and passes the fixture loader on current GitHub runners.
  • MariaDB is out of scope and should be stated as untested.

Proposal(s)

  1. README "Supported versions": MySQL >= 8.0.19, PHP >= 8.3. State that MariaDB is not tested.
  2. CI: mysql:8.0.19 (the floor) plus mysql:8.4 and mysql:9.7 (current LTS releases), as three uses: jobs. mysql:innovation optional as an early-removal canary.
  3. Adapter unit tests asserting exact rendered SQL for dropConstraint(), dropIndex(), dropColumn(), changeColumn() and the table options ENGINE, COMMENT, ALGORITHM (Literal), LOCK (Literal).
  4. Integration test — the adapter's first for DDL: create a table with a FK, a UNIQUE, a CHECK, a PK and a plain index; drop each through dropConstraint(); assert success for the first four and driver error 3940 for the plain index; then drop it with dropIndex(). I have run the full scenario through AlterTableDecorator and it behaves as described.
  5. Core docs PR: alter-drop.md notes the MySQL floor for DROP CONSTRAINT, points non-unique index drops at dropIndex(), and documents the 3939 clash; same PR drops the "MySQL/MariaDB" wording in index.md and adapter.md.

Test plan:

  • README states the floor; CI has 8.0.19, 8.4 and 9.7 jobs, all green.
  • AlterTableDecoratorTest has one test per drop kind and per table option, exact-string assertions.
  • The integration test above passes on every CI image.
  • Core alter-drop.md, index.md and adapter.md updated in a separate PR, linked here.

Appendix/Additional Info

  • MySQL reference manual, ALTER TABLE: "As of MySQL 8.0.19, ALTER TABLE permits more general (and SQL standard) syntax for dropping and altering existing constraints of any type".
  • From an internal DDL audit (not published — the SQL verification above is the relevant part).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions