mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-12-30 21:31:22 +00:00
* use direct blocking calls for SQLite in `sqlx_macros`
* this also ensures the database is closed properly, cleaning up tempfiles
* don't send `PRAGMA journal_mode` unless set
* this previously defaulted to WAL mode which is a permanent setting
on databases which doesn't necessarily apply to all use-cases
* changing into or out of WAL mode acquires an exclusive lock on the database
that can't be waited on by `sqlite3_busy_timeout()`
* for consistency, `sqlx-cli` commands that create databases will still
create SQLite databases in WAL mode; added a flag to disable this.
* in general, don't send `PRAGMA`s unless different than default
* we were sending a bunch of `PRAGMA`s with their default values just to enforce
an execution order on them, but we can also do this by inserting empty slots
for their keys into the `IndexMap`
* add error code to `SqliteError` printout
* document why `u64` is not supported
82 lines
2.4 KiB
Rust
82 lines
2.4 KiB
Rust
use crate::migrate;
|
|
use crate::opt::ConnectOpts;
|
|
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.database_url).await?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn drop(connect_opts: &ConnectOpts, confirm: bool) -> anyhow::Result<()> {
|
|
if confirm && !ask_to_continue(connect_opts) {
|
|
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 {
|
|
Any::drop_database(&connect_opts.database_url).await?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn reset(
|
|
migration_source: &str,
|
|
connect_opts: &ConnectOpts,
|
|
confirm: bool,
|
|
) -> anyhow::Result<()> {
|
|
drop(connect_opts, confirm).await?;
|
|
setup(migration_source, connect_opts).await
|
|
}
|
|
|
|
pub async fn setup(migration_source: &str, connect_opts: &ConnectOpts) -> anyhow::Result<()> {
|
|
create(connect_opts).await?;
|
|
migrate::run(migration_source, connect_opts, false, false).await
|
|
}
|
|
|
|
fn ask_to_continue(connect_opts: &ConnectOpts) -> bool {
|
|
loop {
|
|
let r: Result<String, ReadlineError> = prompt(format!(
|
|
"Drop database at {}? (y/n)",
|
|
style(&connect_opts.database_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;
|
|
}
|
|
}
|
|
}
|
|
}
|