use sea_orm::{ConnectionTrait, DatabaseBackend, DatabaseConnection};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use tracing::error;
#[derive(Error, Debug)]
pub enum TableError {
#[error("数据库查询失败: {0}")]
QueryFailed(String),
#[error("表不存在: {0}")]
TableNotFound(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TableInfo {
pub table_name: String,
pub schema_name: String,
pub table_type: String,
pub table_comment: Option<String>,
pub row_count: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TableColumnInfo {
pub column_name: String,
pub data_type: String,
pub is_nullable: bool,
pub default_value: Option<String>,
pub column_comment: Option<String>,
pub character_maximum_length: Option<u32>,
pub numeric_precision: Option<u32>,
pub numeric_scale: Option<u32>,
pub is_primary_key: bool,
}
pub struct TableService;
impl TableService {
pub async fn list_tables(
db: &DatabaseConnection,
schema: Option<&str>,
) -> Result<Vec<TableInfo>, TableError> {
let schema_name = schema.unwrap_or("public");
if schema_name.is_empty() {
return Err(TableError::QueryFailed("Schema 名称不能为空".to_string()));
}
let backend = db.get_database_backend();
if backend != DatabaseBackend::Postgres {
return Err(TableError::QueryFailed(
format!("当前仅支持 PostgreSQL 数据库,当前数据库类型: {:?}", backend)
));
}
let _ = db.execute_unprepared("SELECT 1").await.map_err(|e| {
TableError::QueryFailed(format!("数据库连接不可用: {}", e))
})?;
Err(TableError::QueryFailed(
format!(
"表列表查询功能需要 sqlx 连接池支持。\
建议:1) 使用 sqlx 连接池直接查询,或 2) 通过数据库管理工具查询。\
要查询的 Schema: {}",
schema_name
)
))
}
pub async fn get_table_info(
db: &DatabaseConnection,
schema: Option<&str>,
table_name: &str,
) -> Result<TableInfo, TableError> {
let schema_name = schema.unwrap_or("public");
if schema_name.is_empty() {
return Err(TableError::QueryFailed("Schema 名称不能为空".to_string()));
}
if table_name.is_empty() {
return Err(TableError::QueryFailed("表名称不能为空".to_string()));
}
let backend = db.get_database_backend();
if backend != DatabaseBackend::Postgres {
return Err(TableError::QueryFailed(
format!("当前仅支持 PostgreSQL 数据库,当前数据库类型: {:?}", backend)
));
}
let _ = db.execute_unprepared("SELECT 1").await.map_err(|e| {
TableError::QueryFailed(format!("数据库连接不可用: {}", e))
})?;
Err(TableError::QueryFailed(
format!(
"表信息查询功能需要 sqlx 连接池支持。\
建议:1) 使用 sqlx 连接池直接查询,或 2) 通过数据库管理工具查询。\
要查询的表: {}.{}",
schema_name, table_name
)
))
}
pub async fn get_table_columns(
db: &DatabaseConnection,
schema: Option<&str>,
table_name: &str,
) -> Result<Vec<TableColumnInfo>, TableError> {
let schema_name = schema.unwrap_or("public");
if schema_name.is_empty() {
return Err(TableError::QueryFailed("Schema 名称不能为空".to_string()));
}
if table_name.is_empty() {
return Err(TableError::QueryFailed("表名称不能为空".to_string()));
}
let backend = db.get_database_backend();
if backend != DatabaseBackend::Postgres {
return Err(TableError::QueryFailed(
format!("当前仅支持 PostgreSQL 数据库,当前数据库类型: {:?}", backend)
));
}
let _ = db.execute_unprepared("SELECT 1").await.map_err(|e| {
TableError::QueryFailed(format!("数据库连接不可用: {}", e))
})?;
Err(TableError::QueryFailed(
format!(
"表列信息查询功能需要 sqlx 连接池支持。\
建议:1) 使用 sqlx 连接池直接查询,或 2) 通过数据库管理工具查询。\
要查询的表: {}.{}",
schema_name, table_name
)
))
}
pub async fn table_exists(
db: &DatabaseConnection,
schema: Option<&str>,
table_name: &str,
) -> Result<bool, TableError> {
match Self::get_table_info(db, schema, table_name).await {
Ok(_) => Ok(true),
Err(TableError::TableNotFound(_)) => Ok(false),
Err(e) => Err(e),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_table_info_serialization() {
let info = TableInfo {
table_name: "test_table".to_string(),
schema_name: "public".to_string(),
table_type: "BASE TABLE".to_string(),
table_comment: Some("测试表".to_string()),
row_count: Some(100),
};
let json = serde_json::to_string(&info).unwrap();
assert!(json.contains("test_table"));
}
}