Files
sqlx/sqlx-cli/src/database.rs
2025-01-15 10:31:03 -08:00

86 lines
2.7 KiB
Rust

use crate::{migrate, Config};
use crate::opt::{ConnectOpts, MigrationSourceOpt};
use console::style;
use promptly::{prompt, ReadlineError};
use sqlx::any::Any;
use sqlx::migrate::MigrateDatabase;
pub async fn create(connect_opts: &ConnectOpts) -> anyhow::Result<()> {
// NOTE: only retry the idempotent action.
// We're assuming that if this succeeds, then any following operations should also succeed.
let exists = crate::retry_connect_errors(connect_opts, Any::database_exists).await?;
if !exists {
#[cfg(feature = "_sqlite")]
sqlx::sqlite::CREATE_DB_WAL.store(
connect_opts.sqlite_create_db_wal,
std::sync::atomic::Ordering::Release,
);
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.expect_db_url()?) {
return Ok(());
}
// NOTE: only retry the idempotent action.
// We're assuming that if this succeeds, then any following operations should also succeed.
let exists = crate::retry_connect_errors(connect_opts, Any::database_exists).await?;
if exists {
if force {
Any::force_drop_database(connect_opts.expect_db_url()?).await?;
} else {
Any::drop_database(connect_opts.expect_db_url()?).await?;
}
}
Ok(())
}
pub async fn reset(
config: &Config,
migration_source: &MigrationSourceOpt,
connect_opts: &ConnectOpts,
confirm: bool,
force: bool,
) -> anyhow::Result<()> {
drop(connect_opts, confirm, force).await?;
setup(config, migration_source, connect_opts).await
}
pub async fn setup(config: &Config, migration_source: &MigrationSourceOpt, connect_opts: &ConnectOpts) -> anyhow::Result<()> {
create(connect_opts).await?;
migrate::run(config, migration_source, connect_opts, false, false, None).await
}
fn ask_to_continue_drop(db_url: &str) -> bool {
loop {
let r: Result<String, ReadlineError> =
prompt(format!("Drop database at {}? (y/n)", style(db_url).cyan()));
match r {
Ok(response) => {
if response == "n" || response == "N" {
return false;
} else if response == "y" || response == "Y" {
return true;
} else {
println!(
"Response not recognized: {}\nPlease type 'y' or 'n' and press enter.",
response
);
}
}
Err(e) => {
println!("{e}");
return false;
}
}
}
}