2024-11-18 13:40:47 +08:00
|
|
|
|
// src/database/relational/postgresql/mod.rs
|
2024-11-11 19:31:40 +08:00
|
|
|
|
/*
|
2024-11-18 13:40:47 +08:00
|
|
|
|
* 该模块实现了与PostgreSQL数据库的交互功能。
|
|
|
|
|
* 包含连接池的结构体定义,提供数据库操作的基础。
|
2024-11-11 13:45:02 +08:00
|
|
|
|
*/
|
2024-11-18 13:40:47 +08:00
|
|
|
|
use super::{DatabaseTrait, QueryBuilder};
|
2024-11-11 13:45:02 +08:00
|
|
|
|
use crate::config;
|
2024-11-09 00:05:18 +08:00
|
|
|
|
use async_trait::async_trait;
|
2024-11-11 13:45:02 +08:00
|
|
|
|
use sqlx::{Column, PgPool, Row};
|
2024-11-11 01:38:58 +08:00
|
|
|
|
use std::{collections::HashMap, error::Error};
|
2024-11-09 00:05:18 +08:00
|
|
|
|
|
2024-11-11 01:38:58 +08:00
|
|
|
|
#[derive(Clone)]
|
2024-11-18 13:40:47 +08:00
|
|
|
|
/// PostgreSQL数据库连接池结构体
|
2024-11-09 00:05:18 +08:00
|
|
|
|
pub struct Postgresql {
|
2024-11-18 13:40:47 +08:00
|
|
|
|
/// 数据库连接池
|
2024-11-11 01:38:58 +08:00
|
|
|
|
pool: PgPool,
|
2024-11-09 00:05:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[async_trait]
|
2024-11-11 13:45:02 +08:00
|
|
|
|
impl DatabaseTrait for Postgresql {
|
2024-11-18 13:40:47 +08:00
|
|
|
|
/**
|
|
|
|
|
* 连接到PostgreSQL数据库并返回Postgresql实例。
|
|
|
|
|
*
|
|
|
|
|
* # 参数
|
|
|
|
|
* - `db_config`: 数据库配置
|
|
|
|
|
*
|
|
|
|
|
* # 返回
|
|
|
|
|
* - `Result<Self, Box<dyn Error>>`: 连接结果
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
async fn connect(db_config: config::SqlConfig) -> Result<Self, Box<dyn Error>> {
|
2024-11-11 01:38:58 +08:00
|
|
|
|
let connection_str = format!(
|
|
|
|
|
"postgres://{}:{}@{}:{}/{}",
|
2024-11-12 20:25:43 +08:00
|
|
|
|
db_config.user, db_config.password, db_config.address, db_config.prot, db_config.db_name
|
2024-11-11 01:38:58 +08:00
|
|
|
|
);
|
|
|
|
|
|
2024-11-11 19:31:40 +08:00
|
|
|
|
// 连接到数据库池
|
2024-11-11 01:38:58 +08:00
|
|
|
|
let pool = PgPool::connect(&connection_str)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| Box::new(e) as Box<dyn Error>)?;
|
|
|
|
|
|
2024-11-11 19:31:40 +08:00
|
|
|
|
// 返回Postgresql实例
|
2024-11-11 01:38:58 +08:00
|
|
|
|
Ok(Postgresql { pool })
|
2024-11-09 00:05:18 +08:00
|
|
|
|
}
|
2024-11-11 19:31:40 +08:00
|
|
|
|
|
2024-11-18 13:40:47 +08:00
|
|
|
|
/**
|
2024-11-11 19:31:40 +08:00
|
|
|
|
* 异步执行查询并返回结果。
|
2024-11-18 13:40:47 +08:00
|
|
|
|
*
|
|
|
|
|
* # 参数
|
|
|
|
|
* - `builder`: 查询构建器
|
|
|
|
|
*
|
|
|
|
|
* # 返回
|
|
|
|
|
* - `Result<Vec<HashMap<String, String>>, Box<dyn Error + 'a>>`: 查询结果
|
2024-11-11 19:31:40 +08:00
|
|
|
|
*/
|
2024-11-18 13:40:47 +08:00
|
|
|
|
async fn execute_query<'a>(
|
2024-11-11 13:45:02 +08:00
|
|
|
|
&'a self,
|
2024-11-18 13:40:47 +08:00
|
|
|
|
builder: &QueryBuilder,
|
2024-11-11 13:45:02 +08:00
|
|
|
|
) -> Result<Vec<HashMap<String, String>>, Box<dyn Error + 'a>> {
|
2024-11-18 13:40:47 +08:00
|
|
|
|
let (query, values) = builder.build();
|
|
|
|
|
|
|
|
|
|
// 构建查询
|
|
|
|
|
let mut sqlx_query = sqlx::query(&query);
|
|
|
|
|
|
|
|
|
|
// 绑定参数
|
|
|
|
|
for value in values {
|
|
|
|
|
sqlx_query = sqlx_query.bind(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 执行查询
|
|
|
|
|
let rows = sqlx_query
|
2024-11-11 01:38:58 +08:00
|
|
|
|
.fetch_all(&self.pool)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| Box::new(e) as Box<dyn Error>)?;
|
|
|
|
|
|
2024-11-18 13:40:47 +08:00
|
|
|
|
// 处理结果
|
2024-11-11 01:38:58 +08:00
|
|
|
|
let mut results = Vec::new();
|
|
|
|
|
for row in rows {
|
|
|
|
|
let mut map = HashMap::new();
|
|
|
|
|
for column in row.columns() {
|
|
|
|
|
let value: String = row.try_get(column.name()).unwrap_or_default();
|
|
|
|
|
map.insert(column.name().to_string(), value);
|
|
|
|
|
}
|
|
|
|
|
results.push(map);
|
|
|
|
|
}
|
2024-11-09 00:05:18 +08:00
|
|
|
|
|
2024-11-11 01:38:58 +08:00
|
|
|
|
Ok(results)
|
2024-11-09 00:05:18 +08:00
|
|
|
|
}
|
2024-11-18 13:40:47 +08:00
|
|
|
|
|
2024-11-11 13:45:02 +08:00
|
|
|
|
}
|