use crate::error::{QuickDbError, QuickDbResult};
use crate::types::*;
use crate::model::{FieldDefinition, FieldType};
use std::collections::HashMap;
use rat_logger::debug;
use sqlx::{Row, mysql::MySqlRow, Column};
pub fn row_to_data_map_with_metadata(
row: &MySqlRow,
fields: &HashMap<String, FieldDefinition>,
) -> QuickDbResult<HashMap<String, DataValue>> {
let mut map = HashMap::new();
for column in row.columns() {
let column_name = column.name();
let field_def = fields.get(column_name).ok_or_else(|| {
QuickDbError::ValidationError {
field: column_name.to_string(),
message: format!("字段 '{}' 未在模型元数据中定义", column_name),
}
})?;
let data_value = match &field_def.field_type {
FieldType::DateTime => {
if let Ok(value) = row.try_get::<Option<chrono::DateTime<chrono::Utc>>, _>(column_name) {
match value {
Some(dt) => {
DataValue::DateTime(dt.with_timezone(&chrono::FixedOffset::east(0)))
},
None => DataValue::Null,
}
} else {
return Err(QuickDbError::QueryError {
message: format!("读取DateTime字段 '{}' 失败", column_name),
});
}
},
FieldType::DateTimeWithTz { timezone_offset } => {
if let Ok(value) = row.try_get::<Option<chrono::DateTime<chrono::Utc>>, _>(column_name) {
match value {
Some(utc_dt) => {
let local_dt = apply_timezone_offset_to_utc(utc_dt, timezone_offset)?;
DataValue::DateTime(local_dt)
},
None => DataValue::Null,
}
} else {
return Err(QuickDbError::QueryError {
message: format!("读取DateTimeWithTz字段 '{}' 失败", column_name),
});
}
},
FieldType::Boolean => {
if let Ok(value) = row.try_get::<Option<i32>, _>(column_name) {
match value {
Some(v) => DataValue::Bool(v != 0),
None => DataValue::Null,
}
} else {
return Err(QuickDbError::QueryError {
message: format!("读取Boolean字段 '{}' 失败", column_name),
});
}
},
FieldType::Integer { .. } | FieldType::BigInteger => {
if let Ok(value) = row.try_get::<Option<i64>, _>(column_name) {
match value {
Some(v) => DataValue::Int(v),
None => DataValue::Null,
}
} else {
return Err(QuickDbError::QueryError {
message: format!("读取整数字段 '{}' 失败", column_name),
});
}
},
FieldType::Float { .. } | FieldType::Double => {
if let Ok(value) = row.try_get::<Option<f64>, _>(column_name) {
match value {
Some(v) => DataValue::Float(v),
None => DataValue::Null,
}
} else {
return Err(QuickDbError::QueryError {
message: format!("读取浮点数字段 '{}' 失败", column_name),
});
}
},
FieldType::String { .. } | FieldType::Text | FieldType::Uuid => {
if let Ok(value) = row.try_get::<Option<String>, _>(column_name) {
match value {
Some(v) => DataValue::String(v),
None => DataValue::Null,
}
} else {
return Err(QuickDbError::QueryError {
message: format!("读取字符串字段 '{}' 失败", column_name),
});
}
},
FieldType::Json | FieldType::Array { .. } | FieldType::Object { .. } => {
if let Ok(value) = row.try_get::<Option<String>, _>(column_name) {
match value {
Some(v) => {
crate::types::data_value::parse_json_string_to_data_value(v)
},
None => DataValue::Null,
}
} else {
return Err(QuickDbError::QueryError {
message: format!("读取JSON字段 '{}' 失败", column_name),
});
}
},
FieldType::Binary => {
if let Ok(value) = row.try_get::<Option<Vec<u8>>, _>(column_name) {
match value {
Some(v) => DataValue::Bytes(v),
None => DataValue::Null,
}
} else {
return Err(QuickDbError::QueryError {
message: format!("读取二进制字段 '{}' 失败", column_name),
});
}
},
_ => {
return Err(QuickDbError::ValidationError {
field: column_name.to_string(),
message: format!("不支持的字段类型: {:?}", field_def.field_type),
});
}
};
map.insert(column_name.to_string(), data_value);
}
Ok(map)
}
fn apply_timezone_offset_to_utc(
utc_dt: chrono::DateTime<chrono::Utc>,
timezone_offset: &str,
) -> QuickDbResult<chrono::DateTime<chrono::FixedOffset>> {
let offset_seconds = crate::utils::timezone::parse_timezone_offset_to_seconds(timezone_offset)?;
if offset_seconds < -86399 || offset_seconds > 86399 {
return Err(QuickDbError::ValidationError {
field: "timezone_offset".to_string(),
message: format!("时区偏移超出有效范围: {}, 允许范围: -23:59 到 +23:59", timezone_offset),
});
}
Ok(utc_dt.with_timezone(&chrono::FixedOffset::east(offset_seconds)))
}