Skip to content

fix(sql): MySQL DROP FOREIGN KEY, FK ordering, default/index normalization#170

Merged
jasdeepkhalsa merged 2 commits intomasterfrom
fix/additional-bug-fixes
Apr 3, 2026
Merged

fix(sql): MySQL DROP FOREIGN KEY, FK ordering, default/index normalization#170
jasdeepkhalsa merged 2 commits intomasterfrom
fix/additional-bug-fixes

Conversation

@jasdeepkhalsa
Copy link
Copy Markdown
Member

Summary

Fixes 5 bugs related to constraint SQL generation, FK dependency ordering, and MySQL schema normalization.

Bug #17 — MySQL DROP FOREIGN KEY syntax

MySQL doesn't support DROP CONSTRAINT for foreign keys — it requires DROP FOREIGN KEY. Added dropConstraint($table, $name, $schema) to SQLDialectInterface:

  • MySQLDialect: detects FOREIGN KEY in schema DDL → emits DROP FOREIGN KEY; falls back to DROP CONSTRAINT for CHECK/UNIQUE
  • Postgres/SQLite: always use standard DROP CONSTRAINT
  • Updated all 3 constraint SQL generators to use the new dialect method

Bug #41 — FK dependency ordering

DiffSorter reordered so:

  • UP: AlterTableDropConstraint runs before DropTable (drop FKs before dropping referenced tables)
  • DOWN: constraints are correctly positioned relative to table creation/deletion

Bug #66 — Default value normalization

Added MySQLAdapter::normalizeColumnDef():

  • Strips integer display widths (int(11)int, tinyint(4)tinyint, etc.) — removed in MySQL 8.0.17+, their presence varies between versions
  • Canonicalises CURRENT_TIMESTAMP variants (case, empty parens, ON UPDATE clause)

Bug #61 — Index false positives

Added MySQLAdapter::normalizeKeyDef():

  • Strips trailing USING BTREE — default index type whose inclusion varies between MySQL versions, causing phantom diffs

Bug #91 — Index SQL generation (PRIMARY KEY)

  • MySQLAdapter::getTableSchema() now stores PRIMARY KEY lines under key name 'PRIMARY' instead of extracting the first column name
  • MySQLDialect::dropIndex() emits ALTER TABLE t DROP PRIMARY KEY; when key is 'PRIMARY'

Tests

  • 52 new/updated unit tests across 4 test classes
  • 570 total tests pass (Podman, PHP 8.4)
  • New test files:
    • DiffSorterConstraintOrderTest.php — 4 tests for FK ordering
    • MySQLAdapterNormalizationTest.php — 25 data-driven tests for column/key normalization
    • IndexSQLGenerationTest.php — 13 tests for index SQL across all 3 dialects
    • Updated AlterTableDropConstraintSQLTest.php — expanded from 4 to 14 tests

Files Changed (12)

Source (9):

  • src/SQLGen/Dialect/SQLDialectInterface.php — new dropConstraint() method
  • src/SQLGen/Dialect/MySQLDialect.phpdropConstraint() + dropIndex('PRIMARY') support
  • src/SQLGen/Dialect/AbstractAnsiDialect.phpdropConstraint() default implementation
  • src/SQLGen/DiffToSQL/AlterTableDropConstraintSQL.php — uses dialect->dropConstraint()
  • src/SQLGen/DiffToSQL/AlterTableAddConstraintSQL.php — uses dialect->dropConstraint()
  • src/SQLGen/DiffToSQL/AlterTableChangeConstraintSQL.php — uses dialect->dropConstraint()
  • src/SQLGen/DiffSorter.php — reordered constraint operations
  • src/DB/Adapters/MySQLAdapter.php — normalization methods + PRIMARY KEY parsing

Tests (3 new + 1 updated):

  • tests/Unit/AlterTableDropConstraintSQLTest.php
  • tests/Unit/DiffSorterConstraintOrderTest.php
  • tests/Unit/IndexSQLGenerationTest.php
  • tests/Unit/MySQLAdapterNormalizationTest.php

@github-actions github-actions bot added bug mysql Related to Mysql php Pull requests that update php code postgres Related to Postgres sqlite Related to Sqlite labels Apr 3, 2026
…ation

- #17: Add dialect->dropConstraint() — MySQL emits DROP FOREIGN KEY for FK
  constraints, DROP CONSTRAINT for others (Postgres/SQLite use standard syntax)
- #41: Reorder DiffSorter so DROP CONSTRAINT runs before DROP TABLE (UP)
  and ADD CONSTRAINT runs after ADD TABLE (UP)
- #66: Normalize integer display widths (int(11)→int) and CURRENT_TIMESTAMP
  variants in MySQLAdapter::normalizeColumnDef()
- #61: Strip trailing USING BTREE from index DDL in normalizeKeyDef()
- #91: Store PRIMARY KEY under key name 'PRIMARY'; MySQLDialect::dropIndex()
  emits DROP PRIMARY KEY when key is 'PRIMARY'

Tests: 52 new/updated unit tests across 4 test classes (570 total pass)
Re-record E2E expected outputs to match corrected SQL generation:
- MySQL/Dolt: DROP PRIMARY KEY instead of DROP INDEX for PKs (#91)
- MySQL/Dolt: DROP FOREIGN KEY instead of DROP CONSTRAINT for FKs (#17)
- All dialects: constraint DROPs now sorted before table ops (#41)

Verified locally via Podman: MySQL 8.0, PostgreSQL 16, SQLite — all pass.
@jasdeepkhalsa jasdeepkhalsa force-pushed the fix/additional-bug-fixes branch from aa82a65 to bb67b6b Compare April 3, 2026 19:13
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 3, 2026

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

Labels

bug mysql Related to Mysql php Pull requests that update php code postgres Related to Postgres sqlite Related to Sqlite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant