Add --source for migration subcommands (#1769)

This commit is contained in:
Pedro de Matos Fedricci 2022-04-01 16:19:51 -03:00 committed by GitHub
parent d3093d0b70
commit c30a4a5d88
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 207 additions and 64 deletions

View file

@ -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
```

View file

@ -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,

View file

@ -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
}
}