use rusticx_core::value::{Row, Value};
use sqlx::postgres::PgRow;
use sqlx::{Column, Row as SqlxRow, TypeInfo};
pub fn pg_row_to_row(pg_row: PgRow) -> Row {
let mut map = Row::new();
for col in pg_row.columns() {
let name = col.name().to_owned();
let type_info = col.type_info();
let val = decode_column(&pg_row, col.ordinal(), type_info.name());
map.insert(name, val);
}
map
}
fn decode_column(row: &PgRow, idx: usize, type_name: &str) -> Value {
match type_name {
"BOOL" => row.try_get::<bool, _>(idx).map(Value::Bool).unwrap_or(Value::Null),
"INT2" => row.try_get::<i16, _>(idx).map(|v| Value::Int(v as i64)).unwrap_or(Value::Null),
"INT4" => row.try_get::<i32, _>(idx).map(|v| Value::Int(v as i64)).unwrap_or(Value::Null),
"INT8" => row.try_get::<i64, _>(idx).map(Value::Int).unwrap_or(Value::Null),
"FLOAT4" => row.try_get::<f32, _>(idx).map(|v| Value::Float(v as f64)).unwrap_or(Value::Null),
"FLOAT8" => row.try_get::<f64, _>(idx).map(Value::Float).unwrap_or(Value::Null),
"TEXT" | "VARCHAR" | "BPCHAR" | "NAME" | "CHAR" => {
row.try_get::<String, _>(idx).map(Value::Text).unwrap_or(Value::Null)
}
"UUID" => row
.try_get::<uuid::Uuid, _>(idx)
.map(Value::Uuid)
.unwrap_or(Value::Null),
"TIMESTAMPTZ" => row
.try_get::<chrono::DateTime<chrono::Utc>, _>(idx)
.map(Value::DateTime)
.unwrap_or(Value::Null),
"TIMESTAMP" => row
.try_get::<chrono::NaiveDateTime, _>(idx)
.map(|dt| Value::DateTime(dt.and_utc()))
.unwrap_or(Value::Null),
"JSON" | "JSONB" => row
.try_get::<serde_json::Value, _>(idx)
.map(Value::Json)
.unwrap_or(Value::Null),
"BYTEA" => row
.try_get::<Vec<u8>, _>(idx)
.map(Value::Bytes)
.unwrap_or(Value::Null),
_ => row
.try_get::<String, _>(idx)
.map(Value::Text)
.unwrap_or(Value::Null),
}
}