You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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):
ALTERTABLE`t` DROP CONSTRAINT`fk_parent`-- FOREIGN KEY: OKALTERTABLE`t` DROP CONSTRAINT`uq_email`-- UNIQUE: OKALTERTABLE`t` DROP CONSTRAINT`chk_age`-- CHECK: OKALTERTABLE`t` DROP CONSTRAINT`PRIMARY`-- PRIMARY KEY: OKALTERTABLE`t` DROP CONSTRAINT`idx_name`-- plain INDEX: ERROR 3940: Constraint 'idx_name' does not exist.ALTERTABLE`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)
README "Supported versions": MySQL >= 8.0.19, PHP >= 8.3. State that MariaDB is not tested.
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.
Adapter unit tests asserting exact rendered SQL for dropConstraint(), dropIndex(), dropColumn(), changeColumn() and the table options ENGINE, COMMENT, ALGORITHM (Literal), LOCK (Literal).
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.
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).
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 —
AlterTabledrop paths and table options. One small docs PR in core correctsalter-drop.mdand the "MySQL/MariaDB" wording.Background
AlterTable::dropConstraint($name)rendersDROP CONSTRAINT <name>(AlterTable.php#L74-L78, #L254-L262) and the MySQLAlterTableDecoratorleaves 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):So the rendering is right for the versions we intend to support — but nothing says what those are:
docs/book/index.md:20,docs/book/adapter.md:24).mysql:8.0image (.github/workflows/continuous-integration.yml) via the sharedphpdb-qa-toolsreusable workflow, which takes onedb-imagestring and has no matrix. That image is a late 8.0.4x, so the floor is never exercised.docs/book/sql-ddl/alter-drop.mdshowsDROP CONSTRAINTas universal output and only warns about SQLite (advanced.md).test/unit/Sql/Ddl/AlterTableDecoratorTest.phpcovers 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 rawmysql.sqlfixture.~8.3.0 || ~8.4.0 || ~8.5.0is incomposer.jsonbut not in the README either.Considerations
dropForeignKey(),dropCheck(), ...) are the only way out, and core cannot emitDROP FOREIGN KEYat all today. That is a core follow-up rather than part of this.InvalidQueryExceptioncarries no errno, so a test has to catch the driver exception:mysqli_sql_exception::getCode() === 3940, or for PDOgetCode() === 'HY000'witherrorInfo[1] === 3940.ENGINEandCOMMENTtake quoted strings;ALGORITHMandLOCKonly work when passed as aLiteral(a plain string rendersALGORITHM = 'INPLACE', which MySQL rejects with 1064). The tests pin the genericsetOption()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.mysql:ltsresolves to 9.7 and 8.4 is the previous LTS. Oneuses:job per image, since the reusable workflow only takes one. Untested assumption: a 2020-eramysql:8.0.19image still boots and passes the fixture loader on current GitHub runners.Proposal(s)
mysql:8.0.19(the floor) plusmysql:8.4andmysql:9.7(current LTS releases), as threeuses:jobs.mysql:innovationoptional as an early-removal canary.dropConstraint(),dropIndex(),dropColumn(),changeColumn()and the table optionsENGINE,COMMENT,ALGORITHM(Literal),LOCK(Literal).dropConstraint(); assert success for the first four and driver error 3940 for the plain index; then drop it withdropIndex(). I have run the full scenario throughAlterTableDecoratorand it behaves as described.alter-drop.mdnotes the MySQL floor forDROP CONSTRAINT, points non-unique index drops atdropIndex(), and documents the 3939 clash; same PR drops the "MySQL/MariaDB" wording inindex.mdandadapter.md.Test plan:
8.0.19,8.4and9.7jobs, all green.AlterTableDecoratorTesthas one test per drop kind and per table option, exact-string assertions.alter-drop.md,index.mdandadapter.mdupdated in a separate PR, linked here.Appendix/Additional Info