use std::collections::BTreeMap;
use super::helpers::quote_ident;
use super::types::{BuiltQuery, DatabaseBackend, RawSql};
use crate::error::QueryError;
pub fn build_remap_enum_values(
backend: DatabaseBackend,
table: &str,
column: &str,
mapping: &BTreeMap<i64, i64>,
) -> Result<Vec<BuiltQuery>, QueryError> {
if mapping.is_empty() {
return Ok(vec![]);
}
let qt = quote_ident(table, backend);
let qc = quote_ident(column, backend);
let case_arms: Vec<String> = mapping
.iter()
.map(|(old, new)| format!("WHEN {qc} = {old} THEN {new}"))
.collect();
let in_list: Vec<String> = mapping.keys().map(i64::to_string).collect();
let sql = format!(
"UPDATE {qt} SET {qc} = CASE {arms} END WHERE {qc} IN ({in_list})",
arms = case_arms.join(" "),
in_list = in_list.join(", "),
);
Ok(vec![BuiltQuery::Raw(RawSql::uniform(sql))])
}
#[cfg(test)]
mod tests {
use super::*;
use insta::{assert_snapshot, with_settings};
fn run(backend: DatabaseBackend, mapping: &[(i64, i64)]) -> String {
let map: BTreeMap<i64, i64> = mapping.iter().copied().collect();
build_remap_enum_values(backend, "tickets", "priority", &map)
.expect("supported")
.iter()
.map(|q| q.build(backend))
.collect::<Vec<_>>()
.join(";\n")
}
fn snap(name: &str, sql: &str) {
with_settings!(
{ snapshot_path => "./snapshots", snapshot_suffix => format!("remap_{}", name) },
{ assert_snapshot!(sql); }
);
}
macro_rules! remap_all_backends {
($name:ident, $mapping:expr) => {
#[test]
fn $name() {
for (backend, tag) in [
(DatabaseBackend::Postgres, "postgres"),
(DatabaseBackend::MySql, "mysql"),
(DatabaseBackend::Sqlite, "sqlite"),
] {
let sql = run(backend, $mapping);
snap(&format!("{}_{}", stringify!($name), tag), &sql);
}
}
};
}
remap_all_backends!(single_pair, &[(5_i64, 100_i64)]);
remap_all_backends!(multi_pair, &[(5_i64, 100_i64), (10_i64, 200_i64)]);
remap_all_backends!(value_swap, &[(5_i64, 10_i64), (10_i64, 5_i64)]);
remap_all_backends!(negative_values, &[(-1_i64, 0_i64), (0_i64, 1_i64)]);
#[test]
fn empty_mapping_emits_no_query() {
let queries = build_remap_enum_values(
DatabaseBackend::Postgres,
"tickets",
"priority",
&BTreeMap::new(),
)
.expect("empty mapping is a valid no-op");
assert!(queries.is_empty());
}
}