|
|
|
@ -272,13 +272,32 @@ impl DbConnType { |
|
|
|
#[cfg(not(postgresql))] |
|
|
|
err!("`DATABASE_URL` is a PostgreSQL URL, but the 'postgresql' feature is not enabled") |
|
|
|
|
|
|
|
//Sqlite
|
|
|
|
// Sqlite (explicit)
|
|
|
|
} else if url.len() > 7 && &url[..7] == "sqlite:" { |
|
|
|
#[cfg(sqlite)] |
|
|
|
return Ok(DbConnType::Sqlite); |
|
|
|
|
|
|
|
#[cfg(not(sqlite))] |
|
|
|
err!("`DATABASE_URL` is a SQLite URL, but the 'sqlite' feature is not enabled") |
|
|
|
|
|
|
|
// No recognized scheme — assume legacy bare-path SQLite, but the database file must already exist.
|
|
|
|
// This prevents misconfigured URLs (typos, quoted strings) from silently creating a new empty SQLite database.
|
|
|
|
} else { |
|
|
|
#[cfg(sqlite)] |
|
|
|
{ |
|
|
|
if std::path::Path::new(url).exists() { |
|
|
|
return Ok(DbConnType::Sqlite); |
|
|
|
} |
|
|
|
err!(format!( |
|
|
|
"`DATABASE_URL` does not match any known database scheme (mysql://, postgresql://, sqlite://) \
|
|
|
|
and no existing SQLite database was found at '{url}'. \ |
|
|
|
If you intend to use SQLite, use an explicit `sqlite://` scheme in your `DATABASE_URL`. \
|
|
|
|
Otherwise, check your DATABASE_URL for typos or quoting issues." |
|
|
|
)) |
|
|
|
} |
|
|
|
|
|
|
|
#[cfg(not(sqlite))] |
|
|
|
err!("`DATABASE_URL` looks like a SQLite URL, but 'sqlite' feature is not enabled") |
|
|
|
err!("`DATABASE_URL` does not match any known database scheme (mysql://, postgresql://, sqlite://)") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -390,11 +409,12 @@ pub fn backup_sqlite() -> Result<String, Error> { |
|
|
|
|
|
|
|
let db_url = CONFIG.database_url(); |
|
|
|
if DbConnType::from_url(&CONFIG.database_url()).map(|t| t == DbConnType::Sqlite).unwrap_or(false) { |
|
|
|
// Since we do not allow any schema for sqlite database_url's like `file:` or `sqlite:` to be set, we can assume here it isn't
|
|
|
|
// This way we can set a readonly flag on the opening mode without issues.
|
|
|
|
let mut conn = diesel::sqlite::SqliteConnection::establish(&format!("sqlite://{db_url}?mode=ro"))?; |
|
|
|
// Strip the sqlite:// prefix if present to get the raw file path
|
|
|
|
let file_path = db_url.strip_prefix("sqlite://").unwrap_or(&db_url); |
|
|
|
// Open a read-only connection for the backup
|
|
|
|
let mut conn = diesel::sqlite::SqliteConnection::establish(&format!("sqlite://{file_path}?mode=ro"))?; |
|
|
|
|
|
|
|
let db_path = std::path::Path::new(&db_url).parent().unwrap(); |
|
|
|
let db_path = std::path::Path::new(file_path).parent().unwrap(); |
|
|
|
let backup_file = db_path |
|
|
|
.join(format!("db_{}.sqlite3", chrono::Utc::now().format("%Y%m%d_%H%M%S"))) |
|
|
|
.to_string_lossy() |
|
|
|
|