mirror of
https://github.com/launchbadge/sqlx.git
synced 2026-03-24 19:10:22 +00:00
feat: make sqlx-cli aware of database-url-var
This commit is contained in:
@@ -17,14 +17,14 @@ pub async fn create(connect_opts: &ConnectOpts) -> anyhow::Result<()> {
|
||||
std::sync::atomic::Ordering::Release,
|
||||
);
|
||||
|
||||
Any::create_database(connect_opts.required_db_url()?).await?;
|
||||
Any::create_database(connect_opts.expect_db_url()?).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn drop(connect_opts: &ConnectOpts, confirm: bool, force: bool) -> anyhow::Result<()> {
|
||||
if confirm && !ask_to_continue_drop(connect_opts.required_db_url()?) {
|
||||
if confirm && !ask_to_continue_drop(connect_opts.expect_db_url()?) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@ pub async fn drop(connect_opts: &ConnectOpts, confirm: bool, force: bool) -> any
|
||||
|
||||
if exists {
|
||||
if force {
|
||||
Any::force_drop_database(connect_opts.required_db_url()?).await?;
|
||||
Any::force_drop_database(connect_opts.expect_db_url()?).await?;
|
||||
} else {
|
||||
Any::drop_database(connect_opts.required_db_url()?).await?;
|
||||
Any::drop_database(connect_opts.expect_db_url()?).await?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::{Context, Result};
|
||||
use futures::{Future, TryFutureExt};
|
||||
|
||||
use sqlx::{AnyConnection, Connection};
|
||||
@@ -20,7 +21,12 @@ mod prepare;
|
||||
|
||||
pub use crate::opt::Opt;
|
||||
|
||||
pub use sqlx::_unstable::config;
|
||||
use crate::config::Config;
|
||||
|
||||
pub async fn run(opt: Opt) -> Result<()> {
|
||||
let config = config_from_current_dir()?;
|
||||
|
||||
match opt.command {
|
||||
Command::Migrate(migrate) => match migrate.command {
|
||||
MigrateCommand::Add {
|
||||
@@ -34,9 +40,11 @@ pub async fn run(opt: Opt) -> Result<()> {
|
||||
source,
|
||||
dry_run,
|
||||
ignore_missing,
|
||||
connect_opts,
|
||||
mut connect_opts,
|
||||
target_version,
|
||||
} => {
|
||||
connect_opts.populate_db_url(config)?;
|
||||
|
||||
migrate::run(
|
||||
&source,
|
||||
&connect_opts,
|
||||
@@ -50,9 +58,11 @@ pub async fn run(opt: Opt) -> Result<()> {
|
||||
source,
|
||||
dry_run,
|
||||
ignore_missing,
|
||||
connect_opts,
|
||||
mut connect_opts,
|
||||
target_version,
|
||||
} => {
|
||||
connect_opts.populate_db_url(config)?;
|
||||
|
||||
migrate::revert(
|
||||
&source,
|
||||
&connect_opts,
|
||||
@@ -64,37 +74,56 @@ pub async fn run(opt: Opt) -> Result<()> {
|
||||
}
|
||||
MigrateCommand::Info {
|
||||
source,
|
||||
connect_opts,
|
||||
} => migrate::info(&source, &connect_opts).await?,
|
||||
mut connect_opts,
|
||||
} => {
|
||||
connect_opts.populate_db_url(config)?;
|
||||
|
||||
migrate::info(&source, &connect_opts).await?
|
||||
},
|
||||
MigrateCommand::BuildScript { source, force } => migrate::build_script(&source, force)?,
|
||||
},
|
||||
|
||||
Command::Database(database) => match database.command {
|
||||
DatabaseCommand::Create { connect_opts } => database::create(&connect_opts).await?,
|
||||
DatabaseCommand::Create { mut connect_opts } => {
|
||||
connect_opts.populate_db_url(config)?;
|
||||
database::create(&connect_opts).await?
|
||||
},
|
||||
DatabaseCommand::Drop {
|
||||
confirmation,
|
||||
connect_opts,
|
||||
mut connect_opts,
|
||||
force,
|
||||
} => database::drop(&connect_opts, !confirmation.yes, force).await?,
|
||||
} => {
|
||||
connect_opts.populate_db_url(config)?;
|
||||
database::drop(&connect_opts, !confirmation.yes, force).await?
|
||||
},
|
||||
DatabaseCommand::Reset {
|
||||
confirmation,
|
||||
source,
|
||||
connect_opts,
|
||||
mut connect_opts,
|
||||
force,
|
||||
} => database::reset(&source, &connect_opts, !confirmation.yes, force).await?,
|
||||
} => {
|
||||
connect_opts.populate_db_url(config)?;
|
||||
database::reset(&source, &connect_opts, !confirmation.yes, force).await?
|
||||
},
|
||||
DatabaseCommand::Setup {
|
||||
source,
|
||||
connect_opts,
|
||||
} => database::setup(&source, &connect_opts).await?,
|
||||
mut connect_opts,
|
||||
} => {
|
||||
connect_opts.populate_db_url(config)?;
|
||||
database::setup(&source, &connect_opts).await?
|
||||
},
|
||||
},
|
||||
|
||||
Command::Prepare {
|
||||
check,
|
||||
all,
|
||||
workspace,
|
||||
connect_opts,
|
||||
mut connect_opts,
|
||||
args,
|
||||
} => prepare::run(check, all, workspace, connect_opts, args).await?,
|
||||
} => {
|
||||
connect_opts.populate_db_url(config)?;
|
||||
prepare::run(check, all, workspace, connect_opts, args).await?
|
||||
},
|
||||
|
||||
#[cfg(feature = "completions")]
|
||||
Command::Completions { shell } => completions::run(shell),
|
||||
@@ -122,7 +151,7 @@ where
|
||||
{
|
||||
sqlx::any::install_default_drivers();
|
||||
|
||||
let db_url = opts.required_db_url()?;
|
||||
let db_url = opts.expect_db_url()?;
|
||||
|
||||
backoff::future::retry(
|
||||
backoff::ExponentialBackoffBuilder::new()
|
||||
@@ -147,3 +176,18 @@ where
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn config_from_current_dir() -> anyhow::Result<&'static Config> {
|
||||
// Tokio does file I/O on a background task anyway
|
||||
tokio::task::spawn_blocking(|| {
|
||||
let path = PathBuf::from("sqlx.toml");
|
||||
|
||||
if path.exists() {
|
||||
eprintln!("Found `sqlx.toml` in current directory; reading...");
|
||||
}
|
||||
|
||||
Config::read_with_or_default(move || Ok(path))
|
||||
})
|
||||
.await
|
||||
.context("unexpected error loading config")
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use std::env;
|
||||
use std::ops::{Deref, Not};
|
||||
|
||||
use anyhow::Context;
|
||||
use clap::{Args, Parser};
|
||||
#[cfg(feature = "completions")]
|
||||
use clap_complete::Shell;
|
||||
use sqlx::config::Config;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(version, about, author)]
|
||||
@@ -242,7 +244,7 @@ impl Deref for Source {
|
||||
#[derive(Args, Debug)]
|
||||
pub struct ConnectOpts {
|
||||
/// Location of the DB, by default will be read from the DATABASE_URL env var or `.env` files.
|
||||
#[clap(long, short = 'D', env)]
|
||||
#[clap(long, short = 'D')]
|
||||
pub database_url: Option<String>,
|
||||
|
||||
/// The maximum time, in seconds, to try connecting to the database server before
|
||||
@@ -266,12 +268,41 @@ pub struct ConnectOpts {
|
||||
impl ConnectOpts {
|
||||
/// Require a database URL to be provided, otherwise
|
||||
/// return an error.
|
||||
pub fn required_db_url(&self) -> anyhow::Result<&str> {
|
||||
self.database_url.as_deref().ok_or_else(
|
||||
|| anyhow::anyhow!(
|
||||
"the `--database-url` option or the `DATABASE_URL` environment variable must be provided"
|
||||
)
|
||||
)
|
||||
pub fn expect_db_url(&self) -> anyhow::Result<&str> {
|
||||
self.database_url.as_deref().context("BUG: database_url not populated")
|
||||
}
|
||||
|
||||
/// Populate `database_url` from the environment, if not set.
|
||||
pub fn populate_db_url(&mut self, config: &Config) -> anyhow::Result<()> {
|
||||
if self.database_url.is_some() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let var = config.common.database_url_var();
|
||||
|
||||
let context = if var != "DATABASE_URL" {
|
||||
" (`common.database-url-var` in `sqlx.toml`)"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
match env::var(var) {
|
||||
Ok(url) => {
|
||||
if !context.is_empty() {
|
||||
eprintln!("Read database url from `{var}`{context}");
|
||||
}
|
||||
|
||||
self.database_url = Some(url)
|
||||
},
|
||||
Err(env::VarError::NotPresent) => {
|
||||
anyhow::bail!("`--database-url` or `{var}`{context} must be set")
|
||||
}
|
||||
Err(env::VarError::NotUnicode(_)) => {
|
||||
anyhow::bail!("`{var}`{context} is not valid UTF-8");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user