51 lines
2.1 KiB
Rust
51 lines
2.1 KiB
Rust
// src/utils/data_converter.rs
|
|
|
|
use common::proto::komp_ac::table_structure::TableStructureResponse;
|
|
use prost_types::{value::Kind, NullValue, Value};
|
|
use std::collections::HashMap;
|
|
|
|
pub fn convert_and_validate_data(
|
|
data: &HashMap<String, String>,
|
|
schema: &TableStructureResponse,
|
|
) -> Result<HashMap<String, Value>, String> {
|
|
let type_map: HashMap<_, _> = schema
|
|
.columns
|
|
.iter()
|
|
.map(|col| (col.name.as_str(), col.data_type.as_str()))
|
|
.collect();
|
|
|
|
data.iter()
|
|
.map(|(key, str_value)| {
|
|
let expected_type = type_map.get(key.as_str()).unwrap_or(&"TEXT");
|
|
|
|
let kind = if str_value.is_empty() {
|
|
// TODO: Use the correct enum variant
|
|
Kind::NullValue(NullValue::NullValue.into())
|
|
} else {
|
|
// Attempt to parse the string based on the expected type
|
|
match *expected_type {
|
|
"BOOL" => match str_value.to_lowercase().parse::<bool>() {
|
|
Ok(v) => Kind::BoolValue(v),
|
|
Err(_) => return Err(format!("Invalid boolean for '{}': must be 'true' or 'false'", key)),
|
|
},
|
|
"INT8" | "INT4" | "INT2" | "SERIAL" | "BIGSERIAL" => {
|
|
match str_value.parse::<f64>() {
|
|
Ok(v) => Kind::NumberValue(v),
|
|
Err(_) => return Err(format!("Invalid number for '{}': must be a whole number", key)),
|
|
}
|
|
}
|
|
"NUMERIC" | "FLOAT4" | "FLOAT8" => match str_value.parse::<f64>() {
|
|
Ok(v) => Kind::NumberValue(v),
|
|
Err(_) => return Err(format!("Invalid decimal for '{}': must be a number", key)),
|
|
},
|
|
"TIMESTAMPTZ" | "DATE" | "TIME" | "TEXT" | "VARCHAR" | "UUID" => {
|
|
Kind::StringValue(str_value.clone())
|
|
}
|
|
_ => Kind::StringValue(str_value.clone()),
|
|
}
|
|
};
|
|
Ok((key.clone(), Value { kind: Some(kind) }))
|
|
})
|
|
.collect()
|
|
}
|