mirror of
https://github.com/launchbadge/sqlx
synced 2024-11-10 06:24:16 +00:00
Add --source for migration subcommands (#1769)
This commit is contained in:
parent
d3093d0b70
commit
c30a4a5d88
3 changed files with 207 additions and 64 deletions
|
@ -3,9 +3,9 @@
|
|||
SQLx's associated command-line utility for managing databases, migrations, and enabling "offline"
|
||||
mode with `sqlx::query!()` and friends.
|
||||
|
||||
### Install
|
||||
## Install
|
||||
|
||||
#### With Rust toolchain
|
||||
### With Rust toolchain
|
||||
|
||||
```bash
|
||||
# supports all databases supported by SQLx
|
||||
|
@ -40,21 +40,36 @@ sqlx database create
|
|||
sqlx database drop
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Create and run migrations
|
||||
|
||||
```bash
|
||||
$ sqlx migrate add <name>
|
||||
sqlx migrate add <name>
|
||||
```
|
||||
|
||||
Creates a new file in `migrations/<timestamp>-<name>.sql`. Add your database schema changes to
|
||||
this new file.
|
||||
|
||||
---
|
||||
|
||||
```bash
|
||||
$ sqlx migrate run
|
||||
sqlx migrate run
|
||||
```
|
||||
|
||||
Compares the migration history of the running database against the `migrations/` folder and runs
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
This is how you would turn all targets and features on.
|
||||
|
||||
```bash
|
||||
cargo sqlx prepare -- --all-targets --all-features
|
||||
```
|
||||
|
|
|
@ -15,35 +15,58 @@ pub async fn run(opt: Opt) -> Result<()> {
|
|||
match opt.command {
|
||||
Command::Migrate(migrate) => match migrate.command {
|
||||
MigrateCommand::Add {
|
||||
source,
|
||||
description,
|
||||
reversible,
|
||||
} => migrate::add(&migrate.source, &description, reversible).await?,
|
||||
} => migrate::add(source.resolve(&migrate.source), &description, reversible).await?,
|
||||
MigrateCommand::Run {
|
||||
source,
|
||||
dry_run,
|
||||
ignore_missing,
|
||||
database_url,
|
||||
} => migrate::run(&migrate.source, &database_url, dry_run, ignore_missing).await?,
|
||||
MigrateCommand::Revert {
|
||||
dry_run,
|
||||
ignore_missing,
|
||||
database_url,
|
||||
} => migrate::revert(&migrate.source, &database_url, dry_run, ignore_missing).await?,
|
||||
MigrateCommand::Info { database_url } => {
|
||||
migrate::info(&migrate.source, &database_url).await?
|
||||
} => {
|
||||
migrate::run(
|
||||
source.resolve(&migrate.source),
|
||||
&database_url,
|
||||
dry_run,
|
||||
*ignore_missing,
|
||||
)
|
||||
.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 {
|
||||
DatabaseCommand::Create { database_url } => database::create(&database_url).await?,
|
||||
DatabaseCommand::Drop { yes, database_url } => {
|
||||
database::drop(&database_url, !yes).await?
|
||||
}
|
||||
DatabaseCommand::Drop {
|
||||
confirmation,
|
||||
database_url,
|
||||
} => database::drop(&database_url, !confirmation).await?,
|
||||
DatabaseCommand::Reset {
|
||||
yes,
|
||||
confirmation,
|
||||
source,
|
||||
database_url,
|
||||
} => database::reset(&source, &database_url, !yes).await?,
|
||||
} => database::reset(&source, &database_url, !confirmation).await?,
|
||||
DatabaseCommand::Setup {
|
||||
source,
|
||||
database_url,
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use clap::Parser;
|
||||
use std::ops::{Deref, Not};
|
||||
|
||||
use clap::{Args, Parser};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(version, about, author)]
|
||||
|
@ -35,9 +37,8 @@ pub enum Command {
|
|||
#[clap(last = true)]
|
||||
args: Vec<String>,
|
||||
|
||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
||||
#[clap(long, short = 'D', env)]
|
||||
database_url: String,
|
||||
#[clap(flatten)]
|
||||
database_url: DatabaseUrl,
|
||||
},
|
||||
|
||||
#[clap(alias = "mig")]
|
||||
|
@ -55,48 +56,38 @@ pub struct DatabaseOpt {
|
|||
pub enum DatabaseCommand {
|
||||
/// Creates the database specified in your DATABASE_URL.
|
||||
Create {
|
||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
||||
#[clap(long, short = 'D', env)]
|
||||
database_url: String,
|
||||
#[clap(flatten)]
|
||||
database_url: DatabaseUrl,
|
||||
},
|
||||
|
||||
/// Drops the database specified in your DATABASE_URL.
|
||||
Drop {
|
||||
/// Automatic confirmation. Without this option, you will be prompted before dropping
|
||||
/// your database.
|
||||
#[clap(short)]
|
||||
yes: bool,
|
||||
#[clap(flatten)]
|
||||
confirmation: Confirmation,
|
||||
|
||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
||||
#[clap(long, short = 'D', env)]
|
||||
database_url: String,
|
||||
#[clap(flatten)]
|
||||
database_url: DatabaseUrl,
|
||||
},
|
||||
|
||||
/// Drops the database specified in your DATABASE_URL, re-creates it, and runs any pending migrations.
|
||||
Reset {
|
||||
/// Automatic confirmation. Without this option, you will be prompted before dropping
|
||||
/// your database.
|
||||
#[clap(short)]
|
||||
yes: bool,
|
||||
#[clap(flatten)]
|
||||
confirmation: Confirmation,
|
||||
|
||||
/// Path to folder containing migrations.
|
||||
#[clap(long, default_value = "migrations")]
|
||||
source: String,
|
||||
#[clap(flatten)]
|
||||
source: Source,
|
||||
|
||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
||||
#[clap(long, short = 'D', env)]
|
||||
database_url: String,
|
||||
#[clap(flatten)]
|
||||
database_url: DatabaseUrl,
|
||||
},
|
||||
|
||||
/// Creates the database specified in your DATABASE_URL and runs any pending migrations.
|
||||
Setup {
|
||||
/// Path to folder containing migrations.
|
||||
#[clap(long, default_value = "migrations")]
|
||||
source: String,
|
||||
#[clap(flatten)]
|
||||
source: Source,
|
||||
|
||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
||||
#[clap(long, short = 'D', env)]
|
||||
database_url: String,
|
||||
#[clap(flatten)]
|
||||
database_url: DatabaseUrl,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -104,6 +95,7 @@ pub enum DatabaseCommand {
|
|||
#[derive(Parser, Debug)]
|
||||
pub struct MigrateOpt {
|
||||
/// Path to folder containing migrations.
|
||||
/// Warning: deprecated, use <SUBCOMMAND> --source <SOURCE>
|
||||
#[clap(long, default_value = "migrations")]
|
||||
pub source: String,
|
||||
|
||||
|
@ -118,6 +110,9 @@ pub enum MigrateCommand {
|
|||
Add {
|
||||
description: String,
|
||||
|
||||
#[clap(flatten)]
|
||||
source: SourceOverride,
|
||||
|
||||
/// If true, creates a pair of up and down migration files with same version
|
||||
/// else creates a single sql file
|
||||
#[clap(short)]
|
||||
|
@ -126,47 +121,156 @@ pub enum MigrateCommand {
|
|||
|
||||
/// Run all pending migrations.
|
||||
Run {
|
||||
#[clap(flatten)]
|
||||
source: SourceOverride,
|
||||
|
||||
/// List all the migrations to be run without applying
|
||||
#[clap(long)]
|
||||
dry_run: bool,
|
||||
|
||||
/// Ignore applied migrations that missing in the resolved migrations
|
||||
#[clap(long)]
|
||||
ignore_missing: bool,
|
||||
#[clap(flatten)]
|
||||
ignore_missing: IgnoreMissing,
|
||||
|
||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
||||
#[clap(long, short = 'D', env)]
|
||||
database_url: String,
|
||||
#[clap(flatten)]
|
||||
database_url: DatabaseUrl,
|
||||
},
|
||||
|
||||
/// Revert the latest migration with a down file.
|
||||
Revert {
|
||||
#[clap(flatten)]
|
||||
source: SourceOverride,
|
||||
|
||||
/// List the migration to be reverted without applying
|
||||
#[clap(long)]
|
||||
dry_run: bool,
|
||||
|
||||
/// Ignore applied migrations that missing in the resolved migrations
|
||||
#[clap(long)]
|
||||
ignore_missing: bool,
|
||||
#[clap(flatten)]
|
||||
ignore_missing: IgnoreMissing,
|
||||
|
||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
||||
#[clap(long, short = 'D', env)]
|
||||
database_url: String,
|
||||
#[clap(flatten)]
|
||||
database_url: DatabaseUrl,
|
||||
},
|
||||
|
||||
/// List all available migrations.
|
||||
Info {
|
||||
/// Location of the DB, by default will be read from the DATABASE_URL env var
|
||||
#[clap(long, env)]
|
||||
database_url: String,
|
||||
#[clap(flatten)]
|
||||
source: SourceOverride,
|
||||
|
||||
#[clap(flatten)]
|
||||
database_url: DatabaseUrl,
|
||||
},
|
||||
|
||||
/// Generate a `build.rs` to trigger recompilation when a new migration is added.
|
||||
///
|
||||
/// Must be run in a Cargo project root.
|
||||
BuildScript {
|
||||
#[clap(flatten)]
|
||||
source: SourceOverride,
|
||||
|
||||
/// Overwrite the build script if it already exists.
|
||||
#[clap(long)]
|
||||
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…
Reference in a new issue