use nodedb_types::Value;
pub(crate) fn pg_value_to_value(
row: &tokio_postgres::Row,
idx: usize,
ty: &tokio_postgres::types::Type,
) -> Value {
use tokio_postgres::types::Type;
match *ty {
Type::BOOL => row
.try_get::<_, bool>(idx)
.map(Value::Bool)
.unwrap_or(Value::Null),
Type::INT2 => row
.try_get::<_, i16>(idx)
.map(|v| Value::Integer(v as i64))
.unwrap_or(Value::Null),
Type::INT4 => row
.try_get::<_, i32>(idx)
.map(|v| Value::Integer(v as i64))
.unwrap_or(Value::Null),
Type::INT8 => row
.try_get::<_, i64>(idx)
.map(Value::Integer)
.unwrap_or(Value::Null),
Type::FLOAT4 => row
.try_get::<_, f32>(idx)
.map(|v| Value::Float(v as f64))
.unwrap_or(Value::Null),
Type::FLOAT8 => row
.try_get::<_, f64>(idx)
.map(Value::Float)
.unwrap_or(Value::Null),
Type::TEXT | Type::VARCHAR | Type::NAME => row
.try_get::<_, String>(idx)
.map(Value::String)
.unwrap_or(Value::Null),
Type::BYTEA => row
.try_get::<_, Vec<u8>>(idx)
.map(Value::Bytes)
.unwrap_or(Value::Null),
Type::JSON | Type::JSONB => row
.try_get::<_, serde_json::Value>(idx)
.map(|v| json_to_value(&v))
.unwrap_or(Value::Null),
_ => {
row.try_get::<_, String>(idx)
.map(Value::String)
.unwrap_or(Value::Null)
}
}
}
pub(crate) fn json_to_value(v: &serde_json::Value) -> Value {
match v {
serde_json::Value::Null => Value::Null,
serde_json::Value::Bool(b) => Value::Bool(*b),
serde_json::Value::Number(n) => {
if let Some(i) = n.as_i64() {
Value::Integer(i)
} else {
Value::Float(n.as_f64().unwrap_or(0.0))
}
}
serde_json::Value::String(s) => Value::String(s.clone()),
serde_json::Value::Array(a) => Value::Array(a.iter().map(json_to_value).collect()),
serde_json::Value::Object(m) => Value::Object(
m.iter()
.map(|(k, v)| (k.clone(), json_to_value(v)))
.collect(),
),
}
}
pub(crate) fn quote_identifier(name: &str) -> String {
let escaped = name.replace('"', "\"\"");
format!("\"{escaped}\"")
}
pub(crate) fn format_vector_array(v: &[f32]) -> String {
let inner: Vec<String> = v.iter().map(|f| format!("{f}")).collect();
format!("ARRAY[{}]", inner.join(","))
}