mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-10-03 15:55:45 +00:00
Add --source for migration subcommands (#1769)
This commit is contained in:
parent
d3093d0b70
commit
c30a4a5d88
@ -3,9 +3,9 @@
|
|||||||
SQLx's associated command-line utility for managing databases, migrations, and enabling "offline"
|
SQLx's associated command-line utility for managing databases, migrations, and enabling "offline"
|
||||||
mode with `sqlx::query!()` and friends.
|
mode with `sqlx::query!()` and friends.
|
||||||
|
|
||||||
### Install
|
## Install
|
||||||
|
|
||||||
#### With Rust toolchain
|
### With Rust toolchain
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# supports all databases supported by SQLx
|
# supports all databases supported by SQLx
|
||||||
@ -40,21 +40,36 @@ sqlx database create
|
|||||||
sqlx database drop
|
sqlx database drop
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
#### Create and run migrations
|
#### Create and run migrations
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ sqlx migrate add <name>
|
sqlx migrate add <name>
|
||||||
```
|
```
|
||||||
|
|
||||||
Creates a new file in `migrations/<timestamp>-<name>.sql`. Add your database schema changes to
|
Creates a new file in `migrations/<timestamp>-<name>.sql`. Add your database schema changes to
|
||||||
this new file.
|
this new file.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ sqlx migrate run
|
sqlx migrate run
|
||||||
```
|
```
|
||||||
|
|
||||||
Compares the migration history of the running database against the `migrations/` folder and runs
|
Compares the migration history of the running database against the `migrations/` folder and runs
|
||||||
any scripts that are still pending.
|
any scripts that are still pending.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Users can provide the directory for the migration scripts to `sqlx migrate` subcommands with the `--source` flag.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sqlx migrate info --source ../relative/migrations
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
#### Reverting Migrations
|
#### Reverting Migrations
|
||||||
|
|
||||||
If you would like to create _reversible_ migrations with corresponding "up" and "down" scripts, you use the `-r` flag when creating new migrations:
|
If you would like to create _reversible_ migrations with corresponding "up" and "down" scripts, you use the `-r` flag when creating new migrations:
|
||||||
@ -133,6 +148,7 @@ In order for sqlx to be able to find queries behind certain feature flags you ne
|
|||||||
on by passing arguments to rustc.
|
on by passing arguments to rustc.
|
||||||
|
|
||||||
This is how you would turn all targets and features on.
|
This is how you would turn all targets and features on.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo sqlx prepare -- --all-targets --all-features
|
cargo sqlx prepare -- --all-targets --all-features
|
||||||
```
|
```
|
||||||
|
@ -15,35 +15,58 @@ pub async fn run(opt: Opt) -> Result<()> {
|
|||||||
match opt.command {
|
match opt.command {
|
||||||
Command::Migrate(migrate) => match migrate.command {
|
Command::Migrate(migrate) => match migrate.command {
|
||||||
MigrateCommand::Add {
|
MigrateCommand::Add {
|
||||||
|
source,
|
||||||
description,
|
description,
|
||||||
reversible,
|
reversible,
|
||||||
} => migrate::add(&migrate.source, &description, reversible).await?,
|
} => migrate::add(source.resolve(&migrate.source), &description, reversible).await?,
|
||||||
MigrateCommand::Run {
|
MigrateCommand::Run {
|
||||||
|
source,
|
||||||
dry_run,
|
dry_run,
|
||||||
ignore_missing,
|
ignore_missing,
|
||||||
database_url,
|
database_url,
|
||||||
} => migrate::run(&migrate.source, &database_url, dry_run, ignore_missing).await?,
|
} => {
|
||||||
MigrateCommand::Revert {
|
migrate::run(
|
||||||
dry_run,
|
source.resolve(&migrate.source),
|
||||||
ignore_missing,
|
&database_url,
|
||||||
database_url,
|
dry_run,
|
||||||
} => migrate::revert(&migrate.source, &database_url, dry_run, ignore_missing).await?,
|
*ignore_missing,
|
||||||
MigrateCommand::Info { database_url } => {
|
)
|
||||||
migrate::info(&migrate.source, &database_url).await?
|
.await?
|
||||||
|
}
|
||||||
|
MigrateCommand::Revert {
|
||||||
|
source,
|
||||||
|
dry_run,
|
||||||
|
ignore_missing,
|
||||||
|
database_url,
|
||||||
|
} => {
|
||||||
|
migrate::revert(
|
||||||
|
source.resolve(&migrate.source),
|
||||||
|
&database_url,
|
||||||
|
dry_run,
|
||||||
|
*ignore_missing,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
}
|
||||||
|
MigrateCommand::Info {
|
||||||
|
source,
|
||||||
|
database_url,
|
||||||
|
} => migrate::info(source.resolve(&migrate.source), &database_url).await?,
|
||||||
|
MigrateCommand::BuildScript { source, force } => {
|
||||||
|
migrate::build_script(source.resolve(&migrate.source), force)?
|
||||||
}
|
}
|
||||||
MigrateCommand::BuildScript { force } => migrate::build_script(&migrate.source, force)?,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
Command::Database(database) => match database.command {
|
Command::Database(database) => match database.command {
|
||||||
DatabaseCommand::Create { database_url } => database::create(&database_url).await?,
|
DatabaseCommand::Create { database_url } => database::create(&database_url).await?,
|
||||||
DatabaseCommand::Drop { yes, database_url } => {
|
DatabaseCommand::Drop {
|
||||||
database::drop(&database_url, !yes).await?
|
confirmation,
|
||||||
}
|
database_url,
|
||||||
|
} => database::drop(&database_url, !confirmation).await?,
|
||||||
DatabaseCommand::Reset {
|
DatabaseCommand::Reset {
|
||||||
yes,
|
confirmation,
|
||||||
source,
|
source,
|
||||||
database_url,
|
database_url,
|
||||||
} => database::reset(&source, &database_url, !yes).await?,
|
} => database::reset(&source, &database_url, !confirmation).await?,
|
||||||
DatabaseCommand::Setup {
|
DatabaseCommand::Setup {
|
||||||
source,
|
source,
|
||||||
database_url,
|
database_url,
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
use clap::Parser;
|
use std::ops::{Deref, Not};
|
||||||
|
|
||||||
|
use clap::{Args, Parser};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[clap(version, about, author)]
|
#[clap(version, about, author)]
|
||||||
@ -35,9 +37,8 @@ pub enum Command {
|
|||||||
#[clap(last = true)]
|
#[clap(last = true)]
|
||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
|
|
||||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
#[clap(flatten)]
|
||||||
#[clap(long, short = 'D', env)]
|
database_url: DatabaseUrl,
|
||||||
database_url: String,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
#[clap(alias = "mig")]
|
#[clap(alias = "mig")]
|
||||||
@ -55,48 +56,38 @@ pub struct DatabaseOpt {
|
|||||||
pub enum DatabaseCommand {
|
pub enum DatabaseCommand {
|
||||||
/// Creates the database specified in your DATABASE_URL.
|
/// Creates the database specified in your DATABASE_URL.
|
||||||
Create {
|
Create {
|
||||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
#[clap(flatten)]
|
||||||
#[clap(long, short = 'D', env)]
|
database_url: DatabaseUrl,
|
||||||
database_url: String,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Drops the database specified in your DATABASE_URL.
|
/// Drops the database specified in your DATABASE_URL.
|
||||||
Drop {
|
Drop {
|
||||||
/// Automatic confirmation. Without this option, you will be prompted before dropping
|
#[clap(flatten)]
|
||||||
/// your database.
|
confirmation: Confirmation,
|
||||||
#[clap(short)]
|
|
||||||
yes: bool,
|
|
||||||
|
|
||||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
#[clap(flatten)]
|
||||||
#[clap(long, short = 'D', env)]
|
database_url: DatabaseUrl,
|
||||||
database_url: String,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Drops the database specified in your DATABASE_URL, re-creates it, and runs any pending migrations.
|
/// Drops the database specified in your DATABASE_URL, re-creates it, and runs any pending migrations.
|
||||||
Reset {
|
Reset {
|
||||||
/// Automatic confirmation. Without this option, you will be prompted before dropping
|
#[clap(flatten)]
|
||||||
/// your database.
|
confirmation: Confirmation,
|
||||||
#[clap(short)]
|
|
||||||
yes: bool,
|
|
||||||
|
|
||||||
/// Path to folder containing migrations.
|
#[clap(flatten)]
|
||||||
#[clap(long, default_value = "migrations")]
|
source: Source,
|
||||||
source: String,
|
|
||||||
|
|
||||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
#[clap(flatten)]
|
||||||
#[clap(long, short = 'D', env)]
|
database_url: DatabaseUrl,
|
||||||
database_url: String,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Creates the database specified in your DATABASE_URL and runs any pending migrations.
|
/// Creates the database specified in your DATABASE_URL and runs any pending migrations.
|
||||||
Setup {
|
Setup {
|
||||||
/// Path to folder containing migrations.
|
#[clap(flatten)]
|
||||||
#[clap(long, default_value = "migrations")]
|
source: Source,
|
||||||
source: String,
|
|
||||||
|
|
||||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
#[clap(flatten)]
|
||||||
#[clap(long, short = 'D', env)]
|
database_url: DatabaseUrl,
|
||||||
database_url: String,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +95,7 @@ pub enum DatabaseCommand {
|
|||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
pub struct MigrateOpt {
|
pub struct MigrateOpt {
|
||||||
/// Path to folder containing migrations.
|
/// Path to folder containing migrations.
|
||||||
|
/// Warning: deprecated, use <SUBCOMMAND> --source <SOURCE>
|
||||||
#[clap(long, default_value = "migrations")]
|
#[clap(long, default_value = "migrations")]
|
||||||
pub source: String,
|
pub source: String,
|
||||||
|
|
||||||
@ -118,6 +110,9 @@ pub enum MigrateCommand {
|
|||||||
Add {
|
Add {
|
||||||
description: String,
|
description: String,
|
||||||
|
|
||||||
|
#[clap(flatten)]
|
||||||
|
source: SourceOverride,
|
||||||
|
|
||||||
/// If true, creates a pair of up and down migration files with same version
|
/// If true, creates a pair of up and down migration files with same version
|
||||||
/// else creates a single sql file
|
/// else creates a single sql file
|
||||||
#[clap(short)]
|
#[clap(short)]
|
||||||
@ -126,47 +121,156 @@ pub enum MigrateCommand {
|
|||||||
|
|
||||||
/// Run all pending migrations.
|
/// Run all pending migrations.
|
||||||
Run {
|
Run {
|
||||||
|
#[clap(flatten)]
|
||||||
|
source: SourceOverride,
|
||||||
|
|
||||||
/// List all the migrations to be run without applying
|
/// List all the migrations to be run without applying
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
|
|
||||||
/// Ignore applied migrations that missing in the resolved migrations
|
#[clap(flatten)]
|
||||||
#[clap(long)]
|
ignore_missing: IgnoreMissing,
|
||||||
ignore_missing: bool,
|
|
||||||
|
|
||||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
#[clap(flatten)]
|
||||||
#[clap(long, short = 'D', env)]
|
database_url: DatabaseUrl,
|
||||||
database_url: String,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Revert the latest migration with a down file.
|
/// Revert the latest migration with a down file.
|
||||||
Revert {
|
Revert {
|
||||||
|
#[clap(flatten)]
|
||||||
|
source: SourceOverride,
|
||||||
|
|
||||||
/// List the migration to be reverted without applying
|
/// List the migration to be reverted without applying
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
|
|
||||||
/// Ignore applied migrations that missing in the resolved migrations
|
#[clap(flatten)]
|
||||||
#[clap(long)]
|
ignore_missing: IgnoreMissing,
|
||||||
ignore_missing: bool,
|
|
||||||
|
|
||||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
#[clap(flatten)]
|
||||||
#[clap(long, short = 'D', env)]
|
database_url: DatabaseUrl,
|
||||||
database_url: String,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// List all available migrations.
|
/// List all available migrations.
|
||||||
Info {
|
Info {
|
||||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
#[clap(flatten)]
|
||||||
#[clap(long, env)]
|
source: SourceOverride,
|
||||||
database_url: String,
|
|
||||||
|
#[clap(flatten)]
|
||||||
|
database_url: DatabaseUrl,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Generate a `build.rs` to trigger recompilation when a new migration is added.
|
/// Generate a `build.rs` to trigger recompilation when a new migration is added.
|
||||||
///
|
///
|
||||||
/// Must be run in a Cargo project root.
|
/// Must be run in a Cargo project root.
|
||||||
BuildScript {
|
BuildScript {
|
||||||
|
#[clap(flatten)]
|
||||||
|
source: SourceOverride,
|
||||||
|
|
||||||
/// Overwrite the build script if it already exists.
|
/// Overwrite the build script if it already exists.
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
force: bool,
|
force: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Argument for the migration scripts source.
|
||||||
|
#[derive(Args, Debug)]
|
||||||
|
pub struct Source {
|
||||||
|
/// Path to folder containing migrations.
|
||||||
|
#[clap(long, default_value = "migrations")]
|
||||||
|
source: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Source {
|
||||||
|
type Target = String;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Argument for overriding migration scripts source.
|
||||||
|
// Note: once `MigrateOpt.source` is removed, usage can be replaced with `Source`.
|
||||||
|
#[derive(Args, Debug)]
|
||||||
|
pub struct SourceOverride {
|
||||||
|
/// Path to folder containing migrations [default: migrations]
|
||||||
|
#[clap(long)]
|
||||||
|
source: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SourceOverride {
|
||||||
|
/// Override command's `source` flag value with subcommand's
|
||||||
|
/// `source` flag value when provided.
|
||||||
|
#[inline]
|
||||||
|
pub(super) fn resolve<'a>(&'a self, source: &'a str) -> &'a str {
|
||||||
|
match self.source {
|
||||||
|
Some(ref source) => source,
|
||||||
|
None => source,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Argument for the database URL.
|
||||||
|
#[derive(Args, Debug)]
|
||||||
|
pub struct DatabaseUrl {
|
||||||
|
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
||||||
|
#[clap(long, short = 'D', env)]
|
||||||
|
database_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for DatabaseUrl {
|
||||||
|
type Target = String;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.database_url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Argument for automatic confirmantion.
|
||||||
|
#[derive(Args, Copy, Clone, Debug)]
|
||||||
|
pub struct Confirmation {
|
||||||
|
/// Automatic confirmation. Without this option, you will be prompted before dropping
|
||||||
|
/// your database.
|
||||||
|
#[clap(short)]
|
||||||
|
yes: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Confirmation {
|
||||||
|
type Target = bool;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.yes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Not for Confirmation {
|
||||||
|
type Output = bool;
|
||||||
|
|
||||||
|
fn not(self) -> Self::Output {
|
||||||
|
!self.yes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Argument for ignoring applied migrations that were not resolved.
|
||||||
|
#[derive(Args, Copy, Clone, Debug)]
|
||||||
|
pub struct IgnoreMissing {
|
||||||
|
/// Ignore applied migrations that are missing in the resolved migrations
|
||||||
|
#[clap(long)]
|
||||||
|
ignore_missing: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for IgnoreMissing {
|
||||||
|
type Target = bool;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.ignore_missing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Not for IgnoreMissing {
|
||||||
|
type Output = bool;
|
||||||
|
|
||||||
|
fn not(self) -> Self::Output {
|
||||||
|
!self.ignore_missing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user