Files
asd-backend/src/db.rs

121 lines
4.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use sqlx::{PgPool, postgres::PgPoolOptions};
use std::env;
use std::error::Error;
// 从 models 模块引入 WeatherData 结构体
use crate::models::WeatherData;
// 这个函数封装了所有与数据库交互的逻辑
pub async fn insert_weather_data(pool: &PgPool, weather_data: &WeatherData) -> Result<i32, String> {
// 1. 根据 openid 查询 user_id
let user_id = match sqlx::query_as::<_, (i32,)>("SELECT id FROM users WHERE openid = $1")
.bind(&weather_data.openid)
.fetch_optional(pool)
.await
{
Ok(Some((id,))) => id,
Ok(None) => {
return Err(format!("未找到openid为 {} 的用户", weather_data.openid));
}
Err(e) => {
return Err(format!("查询用户失败: {}", e));
}
};
// 2. 准备插入数据的 SQL 语句
let insert_query = r#"
INSERT INTO weather_data (
user_id, title, date, hour, min, longitude, latitude, daysincejanfirst,
theta, solardeclination, sunaltitude, overallcloudiness, lowcloudiness,
cloudindex, solarradiationlevel, hasmeasuredwindspeed, measuredwindspeed,
convertedwindspeed, measurementheight, areatype, pointwindspeed,
atmosphericstability, suitabilitydegree, winddirection, averagewinddirection,
winddirectionstandarddeviation, windspeed, averagewindspeed, windspeedsuitability,
winddirectionsuitability, overallsuitability, inspectiontype, assignmentnumber,
calculatedwindspeed
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19,
$20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34
) RETURNING id
"#;
// 转换经纬度为字符串
let longitude_str = weather_data.longitude.to_string();
let latitude_str = weather_data.latitude.to_string();
// 3. 执行插入操作
let inserted_id = match sqlx::query_as::<_, (i32,)>(insert_query)
.bind(user_id)
.bind(&weather_data.title)
.bind(weather_data.date) // NaiveDate 类型sqlx 会自动处理
.bind(weather_data.hours)
.bind(weather_data.min)
.bind(&longitude_str)
.bind(&latitude_str)
.bind(weather_data.day_since_jan_first)
.bind(weather_data.theta)
.bind(weather_data.solar_declination)
.bind(weather_data.sun_altitude)
.bind(&weather_data.overall_cloudiness)
.bind(&weather_data.low_cloudiness)
.bind(&weather_data.cloud_index)
.bind(weather_data.solar_radiation_level as i32)
.bind(weather_data.has_measured_wind_speed)
.bind(weather_data.measured_wind_speed)
.bind(weather_data.converted_wind_speed as i32)
.bind(weather_data.measurement_height)
.bind(&weather_data.area_type)
.bind(weather_data.point_wind_speed)
.bind(&weather_data.atmospheric_stability)
.bind(&weather_data.suitability_degree)
.bind(
serde_json::to_value(&weather_data.wind_direction)
.map_err(|e| format!("JSON 序列化失败: {}", e))?,
)
.bind(weather_data.average_wind_direction)
.bind(weather_data.wind_direction_standard_deviation)
.bind(
serde_json::to_value(&weather_data.wind_speed)
.map_err(|e| format!("JSON 序列化失败: {}", e))?,
)
.bind(weather_data.average_wind_speed)
.bind(&weather_data.wind_speed_suitability)
.bind(&weather_data.wind_direction_suitability)
.bind(&weather_data.overall_suitability)
.bind(&weather_data.inspection_type)
.bind(&weather_data.assignment_number)
.bind(weather_data.calculated_wind_speed)
.fetch_one(pool)
.await
{
Ok((id,)) => id,
Err(e) => {
return Err(format!("插入数据失败: {}", e));
}
};
// 4. 成功,返回插入的 ID
Ok(inserted_id)
}
pub async fn create_pool() -> Result<PgPool, Box<dyn Error>> {
// 加载环境变量,非致命错误处理
if let Err(e) = dotenvy::dotenv() {
eprintln!("警告: 无法加载.env文件 - {}", e);
}
// 获取数据库URL并提供友好错误信息
let database_url =
env::var("DATABASE_URL").map_err(|_| "环境变量DATABASE_URL未设置请在.env文件中配置")?;
// 配置连接池参数
let pool = PgPoolOptions::new()
.max_connections(20) // 根据应用需求调整最大连接数
.acquire_timeout(std::time::Duration::from_secs(30)) // 获取连接的超时时间
.connect(&database_url)
.await
.map_err(|e| format!("数据库连接失败: {}", e))?;
Ok(pool)
}