Macro sqlx::migrate

source · []
macro_rules! migrate {
    ($dir:literal) => { ... };
    () => { ... };
}
Expand description

Embeds migrations into the binary by expanding to a static instance of Migrator.

ⓘ
sqlx::migrate!("db/migrations")
    .run(&pool)
    .await?;
ⓘ
use sqlx::migrate::Migrator;

static MIGRATOR: Migrator = sqlx::migrate!(); // defaults to "./migrations"

The directory must be relative to the project root (the directory containing Cargo.toml), unlike include_str!() which uses compiler internals to get the path of the file where it was invoked.

See MigrationSource for details on structure of the ./migrations directory.

Triggering Recompilation on Migration Changes

In some cases when making changes to embedded migrations, such as adding a new migration without changing any Rust source files, you might find that cargo build doesn’t actually do anything, or when you do cargo run your application isn’t applying new migrations on startup.

This is because our ability to tell the compiler to watch external files for changes from a proc-macro is very limited. The compiler by default only re-runs proc macros when one ore more source files have changed, because normally it shouldn’t have to otherwise. SQLx is just weird in that external factors can change the output of proc macros, much to the chagrin of the compiler team and IDE plugin authors.

As of 0.5.6, we emit include_str!() with an absolute path for each migration, but that only works to get the compiler to watch existing migration files for changes.

Our only options for telling it to watch the whole migrations/ directory are either via the user creating a Cargo build script in their project, or using an unstable API on nightly governed by a cfg-flag.

Stable Rust: Cargo Build Script

The only solution on stable Rust right now is to create a Cargo build script in your project and have it print cargo:rerun-if-changed=migrations:

build.rs

fn main() {
    println!("cargo:rerun-if-changed=migrations");
}

You can run sqlx migrate build-script to generate this file automatically.

See: The Cargo Book: 3.8 Build Scripts; Outputs of the Build Script

Nightly Rust: cfg Flag

The migrate!() macro also listens to --cfg sqlx_macros_unstable, which will enable the track_path feature to directly tell the compiler to watch the migrations/ directory:

$ env RUSTFLAGS='--cfg sqlx_macros_unstable' cargo build

Note that this unfortunately will trigger a fully recompile of your dependency tree, at least for the first time you use it. It also, of course, requires using a nightly compiler.

You can also set it in build.rustflags in .cargo/config.toml:

[build]
rustflags = ["--cfg sqlx_macros_unstable"]

And then continue building and running your project normally.

If you’re building on nightly anyways, it would be extremely helpful to help us test this feature and find any bugs in it.

Subscribe to the track_path tracking issue for discussion and the future stabilization of this feature.

For brevity and because it involves the same commitment to unstable features in proc_macro, if you’re using --cfg procmacro2_semver_exempt it will also enable this feature (see proc-macro2 docs / Unstable Features).