-
Notifications
You must be signed in to change notification settings - Fork 1.5k
feat(sqlite): no_tx migration support
#4015
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(sqlite): no_tx migration support
#4015
Conversation
SQLite includes several SQL statements that are useful during migrations but must be executed outside of a transaction to take effect, such as `PRAGMA foreign_keys = ON|OFF` or `VACUUM`. Additionally, advanced migrations may want more precise control over how statements are grouped into transactions or savepoints to achieve the desired atomicity for different parts of the migration. While SQLx already supports marking migrations to run outside explicit transactions through a `-- no-transaction` comment, this feature is currently only available for `PgConnection`'s `Migrate` implementation, leaving SQLite and MySQL without this capability. Although it's possible to work around this limitation by implementing custom migration logic instead of executing `Migrator#run`, this comes at a cost of significantly reduced developer ergonomics: code that relies on the default migration logic, such as `#[sqlx::test]` or `cargo sqlx database setup`, won't support these migrations. These changes extend `SqliteConnection`'s `Migrate` implementation to support `no_tx` migrations in the same way as PostgreSQL, addressing this feature gap. I also considered implementing the same functionality for MySQL, but since I haven't found a practical use case for it yet, and every non-transaction-friendly statement I could think about in MySQL triggers implicit commits anyway, I determined it wasn't necessary at this time and could be considered an overreach.
* chore(sqlx-postgres): fix typo in `migrate.rs` comment * feat(sqlite): support `no_tx` migrations SQLite includes several SQL statements that are useful during migrations but must be executed outside of a transaction to take effect, such as `PRAGMA foreign_keys = ON|OFF` or `VACUUM`. Additionally, advanced migrations may want more precise control over how statements are grouped into transactions or savepoints to achieve the desired atomicity for different parts of the migration. While SQLx already supports marking migrations to run outside explicit transactions through a `-- no-transaction` comment, this feature is currently only available for `PgConnection`'s `Migrate` implementation, leaving SQLite and MySQL without this capability. Although it's possible to work around this limitation by implementing custom migration logic instead of executing `Migrator#run`, this comes at a cost of significantly reduced developer ergonomics: code that relies on the default migration logic, such as `#[sqlx::test]` or `cargo sqlx database setup`, won't support these migrations. These changes extend `SqliteConnection`'s `Migrate` implementation to support `no_tx` migrations in the same way as PostgreSQL, addressing this feature gap. I also considered implementing the same functionality for MySQL, but since I haven't found a practical use case for it yet, and every non-transaction-friendly statement I could think about in MySQL triggers implicit commits anyway, I determined it wasn't necessary at this time and could be considered an overreach. * test(sqlite): add test for `no_tx` migrations * chore(sqlx-sqlite): bring back useful comment * chore(sqlx-sqlite): unify SQL dialect in annotation comments
|
I've updated sqlx in my project to Is a newer version of the CLI necessary to take adavantage of this new feature? Update: It is, and can be installed today using |
* chore(sqlx-postgres): fix typo in `migrate.rs` comment * feat(sqlite): support `no_tx` migrations SQLite includes several SQL statements that are useful during migrations but must be executed outside of a transaction to take effect, such as `PRAGMA foreign_keys = ON|OFF` or `VACUUM`. Additionally, advanced migrations may want more precise control over how statements are grouped into transactions or savepoints to achieve the desired atomicity for different parts of the migration. While SQLx already supports marking migrations to run outside explicit transactions through a `-- no-transaction` comment, this feature is currently only available for `PgConnection`'s `Migrate` implementation, leaving SQLite and MySQL without this capability. Although it's possible to work around this limitation by implementing custom migration logic instead of executing `Migrator#run`, this comes at a cost of significantly reduced developer ergonomics: code that relies on the default migration logic, such as `#[sqlx::test]` or `cargo sqlx database setup`, won't support these migrations. These changes extend `SqliteConnection`'s `Migrate` implementation to support `no_tx` migrations in the same way as PostgreSQL, addressing this feature gap. I also considered implementing the same functionality for MySQL, but since I haven't found a practical use case for it yet, and every non-transaction-friendly statement I could think about in MySQL triggers implicit commits anyway, I determined it wasn't necessary at this time and could be considered an overreach. * test(sqlite): add test for `no_tx` migrations * chore(sqlx-sqlite): bring back useful comment * chore(sqlx-sqlite): unify SQL dialect in annotation comments
Context, problem statement and description
SQLite includes several SQL statements that are useful during migrations but must be executed outside of a transaction to take effect, such as
PRAGMA foreign_keys = ON|OFForVACUUM. Additionally, advanced migrations may want more precise control over how statements are grouped into transactions or savepoints to achieve the desired atomicity for different parts of the migration.While SQLx already supports marking migrations to run outside explicit transactions through a
-- no-transactioncomment, this feature is currently only implemented forPgConnection'sMigrate, leaving SQLite and MySQL without this capability. Although it's possible to work around this limitation by implementing custom migration logic instead of executingMigrator#run, this comes at the cost of significantly reduced developer ergonomics: code that relies on the default migration logic, such as#[sqlx::test]orcargo sqlx database setup, won't support these migrations.These changes extend
SqliteConnection'sMigrateimplementation to supportno_txmigrations in the same way as PostgreSQL, addressing this feature gap. I also considered implementing the same functionality for MySQL, but since I haven't found a practical use case for it yet, and every non-transaction-friendly statement I could think about in MySQL triggers implicit commits anyway, I determined it wasn't necessary at this time and could be considered an overreach.Does your PR solve an issue?
To my knowledge, this PR doesn't directly address any previously reported issue in this repository. I believe I may be the first person that happens to both attempt using SQLx with SQLite migrations containing "advanced" SQL statements and have the motivation to improve things at the source :)
Is this a breaking change?
Technically yes, as SQLite migrations that begin with a
-- no-transactioncomment will now be executed outside of a transaction, which represents a significant behavioral change. However, I doubt this will cause substantial disruption in practice for several reasons:-- no-transactioncomment without intending to disable the automatic migration transaction. Since this functionality didn't work previously, users likely either settled for removing the comment or implementing alternative solutions, as mentioned above. This change could therefore be considered a bug fix, and Hyrum's law is less likely to apply to behaviors not useful to achieve any outcome.