Summary
#269 made the modified-column path of the migration generator dialect-aware. The rest of the same
generator still emits one shape for everyone, so the same defect class survives one path over: the
transaction wrapper, ADD COLUMN, DROP COLUMN, and the newer type ids that #269 classified as unable
to express DDL at all.
Found while implementing #269 (recorded there as deliberately out of scope, per the loop's one-task
rule).
1. The transaction wrapper is only correct for PostgreSQL and MySQL
src/lib/schema-diff/migration-generator.ts:290-293 and :324
if (dialect !== "sqlite") {
sections.push("BEGIN;");
...
sections.push("COMMIT;");
Every dialect except SQLite gets a bare BEGIN; / COMMIT; pair:
- MSSQL —
BEGIN; alone opens a statement block that expects a matching END; the transaction
spelling is BEGIN TRANSACTION. The script cannot parse.
- Oracle —
BEGIN opens a PL/SQL block and also needs END;. Oracle additionally auto-commits
DDL, so the wrapper is meaningless even when spelled right.
- ClickHouse, Druid, Couchbase, MongoDB, Redis, embedded
libredb — no transactional DDL to wrap
at all. Druid has no DDL, and the last three are not SQL.
So the wrapper is valid for exactly two of the eleven type ids, and actively invalid for two more.
2. Added and removed columns still emit one shape for everyone
:130-135 — added columns:
lines.push(`ALTER TABLE ${id} ADD COLUMN ${generateColumnDef(col, dialect)};`);
No dialect branch at all. ADD COLUMN is not valid T-SQL (ALTER TABLE t ADD c INT) and not valid in
Oracle (ALTER TABLE t ADD (c NUMBER)), and the type ids that #269 just classified as unable to modify
a column get a bare ALTER TABLE ... ADD COLUMN here rather than the honest comment that path now
emits.
:137-146 — removed columns branch for SQLite only, with the same consequence for everyone else.
3. Index and FK paths are partially aware
:238-247 does branch (mysql vs the rest), but the fallback is DROP INDEX IF EXISTS <name>;, which
Oracle does not accept (IF EXISTS is not Oracle syntax) and MSSQL requires an ON <table> for. Worth
auditing in the same pass rather than filed separately.
Suggested shape
Whatever #269 established for the modified-column path, applied to the rest of the generator: a branch
where a dialect genuinely differs, and the honest "this dialect cannot express it" comment where it
cannot. The dialect table in tests/unit/schema-diff/migration-generator.test.ts is now
Record<DatabaseType, ...>, so a new provider fails typecheck until it is classified — extend that
mechanism to whichever paths this work touches instead of adding prose guards.
Engine-syntax claims above come from each dialect's documented grammar, not from a live probe against
the containers in docker-compose. Worth confirming against a live MSSQL and Oracle before settling on
the emitted forms, the way #264 and #265 did.
Summary
#269 made the modified-column path of the migration generator dialect-aware. The rest of the same
generator still emits one shape for everyone, so the same defect class survives one path over: the
transaction wrapper,
ADD COLUMN,DROP COLUMN, and the newer type ids that #269 classified as unableto express DDL at all.
Found while implementing #269 (recorded there as deliberately out of scope, per the loop's one-task
rule).
1. The transaction wrapper is only correct for PostgreSQL and MySQL
src/lib/schema-diff/migration-generator.ts:290-293and:324Every dialect except SQLite gets a bare
BEGIN;/COMMIT;pair:BEGIN;alone opens a statement block that expects a matchingEND; the transactionspelling is
BEGIN TRANSACTION. The script cannot parse.BEGINopens a PL/SQL block and also needsEND;. Oracle additionally auto-commitsDDL, so the wrapper is meaningless even when spelled right.
libredb— no transactional DDL to wrapat all. Druid has no DDL, and the last three are not SQL.
So the wrapper is valid for exactly two of the eleven type ids, and actively invalid for two more.
2. Added and removed columns still emit one shape for everyone
:130-135— added columns:No dialect branch at all.
ADD COLUMNis not valid T-SQL (ALTER TABLE t ADD c INT) and not valid inOracle (
ALTER TABLE t ADD (c NUMBER)), and the type ids that #269 just classified as unable to modifya column get a bare
ALTER TABLE ... ADD COLUMNhere rather than the honest comment that path nowemits.
:137-146— removed columns branch for SQLite only, with the same consequence for everyone else.3. Index and FK paths are partially aware
:238-247does branch (mysqlvs the rest), but the fallback isDROP INDEX IF EXISTS <name>;, whichOracle does not accept (
IF EXISTSis not Oracle syntax) and MSSQL requires anON <table>for. Worthauditing in the same pass rather than filed separately.
Suggested shape
Whatever #269 established for the modified-column path, applied to the rest of the generator: a branch
where a dialect genuinely differs, and the honest "this dialect cannot express it" comment where it
cannot. The dialect table in
tests/unit/schema-diff/migration-generator.test.tsis nowRecord<DatabaseType, ...>, so a new provider fails typecheck until it is classified — extend thatmechanism to whichever paths this work touches instead of adding prose guards.
Engine-syntax claims above come from each dialect's documented grammar, not from a live probe against
the containers in
docker-compose. Worth confirming against a live MSSQL and Oracle before settling onthe emitted forms, the way #264 and #265 did.