diff --git a/src/domain/postgres/backup.rs b/src/domain/postgres/backup.rs index 906cfd9..b2afdcf 100644 --- a/src/domain/postgres/backup.rs +++ b/src/domain/postgres/backup.rs @@ -151,3 +151,25 @@ pub async fn run( }) .await? } + +/// `--exclude-table=` / `--exclude-schema=` args from `options`, plus the keys +/// whose value was not a list of strings (ignored, caller warns). +pub(crate) fn exclude_args(cfg: &DatabaseConfig) -> (Vec, Vec<&'static str>) { + let mut args = Vec::new(); + let mut invalid = Vec::new(); + for (key, flag) in [("exclude_tables", "--exclude-table"), ("exclude_schemas", "--exclude-schema")] { + match cfg.options.get(key).map(|v| v.as_array()) { + None => {} + Some(Some(items)) => args.extend( + items + .iter() + .filter_map(|v| v.as_str()) + .map(str::trim) + .filter(|p| !p.is_empty()) + .map(|p| format!("{flag}={p}")), + ), + Some(None) => invalid.push(key), + } + } + (args, invalid) +} diff --git a/src/tests/domain/postgres.rs b/src/tests/domain/postgres.rs index ce33325..559bffc 100644 --- a/src/tests/domain/postgres.rs +++ b/src/tests/domain/postgres.rs @@ -924,6 +924,61 @@ mod clean_mode_tests { } } +mod exclude_args_tests { + use crate::domain::postgres::backup::exclude_args; + use crate::services::config::DatabaseConfig; + use serde_json::json; + + fn cfg(options: serde_json::Value) -> DatabaseConfig { + serde_json::from_value(json!({ + "name": "t", "database": "testdb", "type": "postgresql", + "username": "u", "password": "p", "port": 5432, "host": "localhost", + "generated_id": "00000000-0000-0000-0000-000000000000", + "path": "", "max_packet_size": "", "volume_name": "", + "options": options + })) + .unwrap() + } + + #[test] + fn no_options_yields_nothing() { + assert_eq!(exclude_args(&cfg(json!({}))), (vec![], vec![])); + assert_eq!( + exclude_args(&cfg(json!({"exclude_tables": [], "exclude_schemas": []}))), + (vec![], vec![]) + ); + } + + #[test] + fn lists_map_to_single_arg_flags_in_order() { + let (args, invalid) = exclude_args(&cfg(json!({ + "exclude_schemas": ["metabase_tmp"], + "exclude_tables": ["public.search_index__*", " audit.tmp_* ", "", " ", 42, "-f/tmp/x", "\"MyTable\""] + }))); + assert_eq!( + args, + vec![ + "--exclude-table=public.search_index__*", + "--exclude-table=audit.tmp_*", + "--exclude-table=-f/tmp/x", + "--exclude-table=\"MyTable\"", + "--exclude-schema=metabase_tmp", + ] + ); + assert!(invalid.is_empty()); + } + + #[test] + fn non_list_values_are_reported_and_ignored() { + let (args, invalid) = exclude_args(&cfg(json!({ + "exclude_tables": "public.search_index__*", + "exclude_schemas": {"a": 1} + }))); + assert!(args.is_empty()); + assert_eq!(invalid, vec!["exclude_tables", "exclude_schemas"]); + } +} + mod toc_tests { use crate::domain::postgres::restore::toc_creates_public_schema;