Skip to content

Conversation

AlexTMjugador
Copy link

@AlexTMjugador AlexTMjugador commented Sep 4, 2025

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|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 implemented for PgConnection's Migrate, 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 the 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.

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-transaction comment 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:

  • Users who needed to execute migrations outside of a transaction in SQLite already had alternative approaches that remain unaffected by this change.
  • It's highly unlikely that someone would accidentally include a -- no-transaction comment 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.

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant