use hyperdb_api::Error;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ErrorClass {
MissingTable(String),
MissingColumn(String),
SyntaxError(String),
Other(String),
}
pub fn classify(err: &Error) -> ErrorClass {
match err.sqlstate() {
Some("42P01") => {
ErrorClass::MissingTable(extract_quoted_identifier(&format!("{err}"), "table"))
}
Some("42703") => {
ErrorClass::MissingColumn(extract_quoted_identifier(&format!("{err}"), "column"))
}
Some("42601") => ErrorClass::SyntaxError(format!("{err}")),
_ => ErrorClass::Other(format!("{err}")),
}
}
fn extract_quoted_identifier(message: &str, _kind: &str) -> String {
if let Some(name) = extract_between(message, '"', '"') {
return name;
}
if let Some(name) = extract_between(message, '\'', '\'') {
return name;
}
message.to_owned()
}
fn extract_between(s: &str, open: char, close: char) -> Option<String> {
let start = s.find(open)? + open.len_utf8();
let end = s[start..].find(close)? + start;
Some(s[start..end].to_owned())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn extract_double_quoted() {
let msg = r#"ERROR: table "ghosts" does not exist (42P01)"#;
assert_eq!(extract_quoted_identifier(msg, "table"), "ghosts");
}
#[test]
fn extract_single_quoted() {
let msg = "ERROR: unknown column 'ema1l' (42703)";
assert_eq!(extract_quoted_identifier(msg, "column"), "ema1l");
}
#[test]
fn extract_falls_back_to_full_message() {
let msg = "ERROR: something unquoted happened";
let result = extract_quoted_identifier(msg, "table");
assert_eq!(result, msg);
}
}