Skip to content

Commit 12d8355

Browse files
committed
fix: warn before auto-declare when existing tables have synced data
When a 'not declared' error triggers delete+recreate, check if any existing tables are synced. If so, show a yellow warning listing the tables whose data will be lost and prompt for y/N confirmation. In non-interactive mode (CI, piped stdin, --no-input) the command errors out with a clear message instead of silently destroying data.
1 parent 9ead351 commit 12d8355

1 file changed

Lines changed: 40 additions & 0 deletions

File tree

src/databases.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,46 @@ pub fn tables_load(
839839
all_tables.push(new_table_key);
840840
}
841841

842+
// Warn if any existing table has synced data — delete+recreate will lose it.
843+
let synced: Vec<String> = existing
844+
.iter()
845+
.filter(|t| t.synced)
846+
.map(|t| format!("{}.{}", t.schema, t.table))
847+
.collect();
848+
if !synced.is_empty() {
849+
use crossterm::style::Stylize;
850+
let catalog = db.default_catalog.as_deref().or(db.name.as_deref()).unwrap_or(&db.id);
851+
eprintln!(
852+
"{}",
853+
format!(
854+
"warning: declaring '{}' requires recreating the database '{catalog}'. \
855+
The following tables have loaded data that will be lost:\n {}",
856+
table,
857+
synced.join(", ")
858+
)
859+
.yellow()
860+
);
861+
if crate::util::is_interactive() {
862+
use std::io::Write;
863+
eprint!("Proceed and lose this data? [y/N] ");
864+
std::io::stderr().flush().unwrap();
865+
let mut input = String::new();
866+
std::io::stdin().read_line(&mut input).unwrap();
867+
if !input.trim().eq_ignore_ascii_case("y") {
868+
eprintln!("{}", "Aborted.".red());
869+
std::process::exit(1);
870+
}
871+
} else {
872+
eprintln!(
873+
"{}",
874+
"error: cannot auto-declare table in non-interactive mode — existing data would be lost. \
875+
Declare all tables up front with 'databases create --table <name>'."
876+
.red()
877+
);
878+
std::process::exit(1);
879+
}
880+
}
881+
842882
let (del_status, del_body) = api.delete_raw(&format!("/databases/{}", db.id));
843883
if !del_status.is_success() {
844884
eprintln!("{}", crate::util::api_error(del_body).red());

0 commit comments

Comments
 (0)