Skip to content

Add support for setting a default migrator#4326

Open
Kobzol wants to merge 1 commit into
transact-rs:mainfrom
Kobzol:test-default-migrator
Open

Add support for setting a default migrator#4326
Kobzol wants to merge 1 commit into
transact-rs:mainfrom
Kobzol:test-default-migrator

Conversation

@Kobzol

@Kobzol Kobzol commented Jun 30, 2026

Copy link
Copy Markdown

This PR contains an implementation sketch for setting a default migrator for #[sqlx::test] macros, because repeating all the migrations for each such macro can produce a lot of code bloat and slow compilation times (see #4318 and https://kobzol.github.io/rust/2026/06/21/optimizing-sqlx-test-rebuild-time.html for more details).

It is configured in the config:

[migrate]
default-migrator = "crate::MIGRATOR"

When a #[sqlx::test] macro doesn't specify the migrations nor the migrator field, and a default migrator is set, it will load it the migrations from it (via a Rust path), rather than inlining the migrations in the expanded #[sqlx::test] output.

So it turns from

let mut args = ::sqlx::testing::TestArgs::new("foo::foo");
    args . migrator (& :: sqlx :: migrate :: Migrator { migrations : :: std :: borrow :: Cow :: Borrowed (const { & [:: sqlx :: migrate :: Migration { version : 20260630083325i64 , description : :: std :: borrow :: Cow :: Borrowed ("migration-1") , migration_type : :: sqlx :: migrate :: MigrationType :: Simple , sql : :: sqlx :: SqlStr :: from_static ("-- Add migration script here\nCREATE TABLE users\n(\n    id   SERIAL,\n    name TEXT\n);\n") , no_tx : false , checksum : :: std :: borrow :: Cow :: Borrowed (& [119u8 , 109u8 , 53u8 , 188u8 , 84u8 , 113u8 , 67u8 , 160u8 , 82u8 , 175u8 , 115u8 , 185u8 , 158u8 , 182u8 , 47u8 , 152u8 , 38u8 , 62u8 , 17u8 , 118u8 , 9u8 , 171u8 , 33u8 , 240u8 , 65u8 , 122u8 , 28u8 , 220u8 , 134u8 , 210u8 , 109u8 , 200u8 , 153u8 , 114u8 , 45u8 , 248u8 , 16u8 , 243u8 , 46u8 , 141u8 , 77u8 , 117u8 , 201u8 , 65u8 , 160u8 , 30u8 , 50u8 , 195u8]) , }] }) , create_schemas : :: std :: borrow :: Cow :: Borrowed (& []) , table_name : :: std :: borrow :: Cow :: Borrowed ("_sqlx_migrations") , .. :: sqlx :: migrate :: Migrator :: DEFAULT }) ; 

// potentially kilobytes of migrations embedded here

to

let mut args = ::sqlx::testing::TestArgs::new("foo::foo");
args.migrator(&crate::MIGRATOR);

I'm not sure in which config section this makes the most sense, so far I added it to the default migrate section, but maybe it should have a new dedicated test section?

I didn't write tests or document the config option yet, because I first wanted to get a vibe check whether you find the approach reasonable.

TODO:

  • Tests
  • Document the new config
  • Allow specifying a default migrator per crate (?)

Does your PR solve an issue?

Fixes: #4318

Is this a breaking change?

No, it is a new opt-in option in the sqlx TOML config.

@abonander

Copy link
Copy Markdown
Collaborator

If you rebase it should fix the build error.

@Kobzol Kobzol force-pushed the test-default-migrator branch from 2feab2b to f8736f8 Compare July 3, 2026 05:05
@Kobzol

Kobzol commented Jul 3, 2026

Copy link
Copy Markdown
Author

Thanks, done.

@Kobzol Kobzol force-pushed the test-default-migrator branch from f8736f8 to 5d1af39 Compare July 3, 2026 05:11

@abonander abonander left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +119 to +131
/// Default migrator used for tests.
pub default_migrator: Option<DefaultMigrator>,
}

#[derive(Debug)]
#[cfg_attr(
feature = "sqlx-toml",
derive(serde::Deserialize),
serde(rename_all = "kebab-case", deny_unknown_fields, untagged)
)]
pub enum DefaultMigrator {
/// A single path to a migrator, e.g. `crate::foo::MIGRATOR`.
Path(String),

@abonander abonander Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Yeah this should be under test.default-migrator to avoid users thinking this affects sqlx::migrate!()
  2. Why all this instead of a simple Option<String>?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding 2., I wanted to support parsing a dictionary of crate names to map to the migrator path. I didn't realize that sqlx.toml can already be set per crate, so this can all be simplified!

@abonander

abonander commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Allow specifying a default migrator per crate (?)

This should work as-is. You can specify a different sqlx.toml per crate.

Having a different migrator for each test binary could be as simple as using a local path (and a re-export if necessary).

@Kobzol

Kobzol commented Jul 9, 2026

Copy link
Copy Markdown
Author

Is there a way to specify a custom config in tests? I haven't found any mentions of a config in the tests directory, and if I set a sqlx.toml for the whole crate, that seems weird, and would likely affect everything (?).

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.

Allow specifying default migrator for tests

2 participants