secra_database/
table.rs

1//! 数据库表管理服务
2//!
3//! 提供数据库表的查询、信息获取等功能
4
5use sea_orm::{ConnectionTrait, DatabaseBackend, DatabaseConnection};
6use serde::{Deserialize, Serialize};
7use thiserror::Error;
8use tracing::error;
9
10/// 表管理错误
11#[derive(Error, Debug)]
12pub enum TableError {
13    #[error("数据库查询失败: {0}")]
14    QueryFailed(String),
15    #[error("表不存在: {0}")]
16    TableNotFound(String),
17}
18
19/// 表信息
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct TableInfo {
22    /// 表名
23    pub table_name: String,
24    /// Schema 名称
25    pub schema_name: String,
26    /// 表类型(BASE TABLE, VIEW 等)
27    pub table_type: String,
28    /// 表注释
29    pub table_comment: Option<String>,
30    /// 行数(估算)
31    pub row_count: Option<u64>,
32}
33
34/// 表列信息
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct TableColumnInfo {
37    /// 列名
38    pub column_name: String,
39    /// 数据类型
40    pub data_type: String,
41    /// 是否可为空
42    pub is_nullable: bool,
43    /// 默认值
44    pub default_value: Option<String>,
45    /// 列注释
46    pub column_comment: Option<String>,
47    /// 字符最大长度
48    pub character_maximum_length: Option<u32>,
49    /// 数值精度
50    pub numeric_precision: Option<u32>,
51    /// 数值小数位数
52    pub numeric_scale: Option<u32>,
53    /// 是否为主键
54    pub is_primary_key: bool,
55}
56
57/// 数据库表服务
58pub struct TableService;
59
60impl TableService {
61    /// 获取所有表信息(PostgreSQL)
62    ///
63    /// # 注意
64    /// 此方法需要 PostgreSQL 数据库,并且需要能够执行查询操作。
65    /// 由于 SeaORM 的 DatabaseConnection 不直接支持复杂查询结果解析,
66    /// 建议使用 sqlx 连接池或通过其他方式获取查询结果。
67    ///
68    /// # 参数
69    /// * `db` - 数据库连接
70    /// * `schema` - Schema 名称(可选,默认为 "public")
71    ///
72    /// # 替代方案
73    /// 如果需要获取表列表,可以:
74    /// 1. 使用 sqlx 连接池直接查询
75    /// 2. 使用 SeaORM Entity 查询(如果已定义表 Entity)
76    /// 3. 通过数据库管理工具查询
77    pub async fn list_tables(
78        db: &DatabaseConnection,
79        schema: Option<&str>,
80    ) -> Result<Vec<TableInfo>, TableError> {
81        let schema_name = schema.unwrap_or("public");
82        
83        // 验证 schema_name 不为空
84        if schema_name.is_empty() {
85            return Err(TableError::QueryFailed("Schema 名称不能为空".to_string()));
86        }
87
88        // 检查数据库类型
89        let backend = db.get_database_backend();
90        if backend != DatabaseBackend::Postgres {
91            return Err(TableError::QueryFailed(
92                format!("当前仅支持 PostgreSQL 数据库,当前数据库类型: {:?}", backend)
93            ));
94        }
95
96        // 测试连接是否可用
97        let _ = db.execute_unprepared("SELECT 1").await.map_err(|e| {
98            TableError::QueryFailed(format!("数据库连接不可用: {}", e))
99        })?;
100
101        // 注意:SeaORM 的 DatabaseConnection 不直接支持查询结果解析
102        // 要获取表列表,需要使用 sqlx 连接池或通过其他方式
103        Err(TableError::QueryFailed(
104            format!(
105                "表列表查询功能需要 sqlx 连接池支持。\
106                建议:1) 使用 sqlx 连接池直接查询,或 2) 通过数据库管理工具查询。\
107                要查询的 Schema: {}",
108                schema_name
109            )
110        ))
111    }
112
113    /// 获取指定表的信息
114    ///
115    /// # 注意
116    /// 此方法需要 PostgreSQL 数据库,并且需要能够执行查询操作。
117    /// 由于 SeaORM 的 DatabaseConnection 不直接支持复杂查询结果解析,
118    /// 建议使用 sqlx 连接池或通过其他方式获取查询结果。
119    ///
120    /// # 参数
121    /// * `db` - 数据库连接
122    /// * `schema` - Schema 名称(可选,默认为 "public")
123    /// * `table_name` - 表名称
124    pub async fn get_table_info(
125        db: &DatabaseConnection,
126        schema: Option<&str>,
127        table_name: &str,
128    ) -> Result<TableInfo, TableError> {
129        let schema_name = schema.unwrap_or("public");
130        
131        // 验证输入
132        if schema_name.is_empty() {
133            return Err(TableError::QueryFailed("Schema 名称不能为空".to_string()));
134        }
135        if table_name.is_empty() {
136            return Err(TableError::QueryFailed("表名称不能为空".to_string()));
137        }
138
139        // 检查数据库类型
140        let backend = db.get_database_backend();
141        if backend != DatabaseBackend::Postgres {
142            return Err(TableError::QueryFailed(
143                format!("当前仅支持 PostgreSQL 数据库,当前数据库类型: {:?}", backend)
144            ));
145        }
146
147        // 测试连接是否可用
148        let _ = db.execute_unprepared("SELECT 1").await.map_err(|e| {
149            TableError::QueryFailed(format!("数据库连接不可用: {}", e))
150        })?;
151
152        // 注意:SeaORM 的 DatabaseConnection 不直接支持查询结果解析
153        // 要获取表信息,需要使用 sqlx 连接池或通过其他方式
154        Err(TableError::QueryFailed(
155            format!(
156                "表信息查询功能需要 sqlx 连接池支持。\
157                建议:1) 使用 sqlx 连接池直接查询,或 2) 通过数据库管理工具查询。\
158                要查询的表: {}.{}",
159                schema_name, table_name
160            )
161        ))
162    }
163
164    /// 获取表的所有列信息(PostgreSQL)
165    ///
166    /// # 注意
167    /// 此方法需要 PostgreSQL 数据库,并且需要能够执行查询操作。
168    /// 由于 SeaORM 的 DatabaseConnection 不直接支持复杂查询结果解析,
169    /// 建议使用 sqlx 连接池或通过其他方式获取查询结果。
170    ///
171    /// # 参数
172    /// * `db` - 数据库连接
173    /// * `schema` - Schema 名称(可选,默认为 "public")
174    /// * `table_name` - 表名称
175    pub async fn get_table_columns(
176        db: &DatabaseConnection,
177        schema: Option<&str>,
178        table_name: &str,
179    ) -> Result<Vec<TableColumnInfo>, TableError> {
180        let schema_name = schema.unwrap_or("public");
181        
182        // 验证输入
183        if schema_name.is_empty() {
184            return Err(TableError::QueryFailed("Schema 名称不能为空".to_string()));
185        }
186        if table_name.is_empty() {
187            return Err(TableError::QueryFailed("表名称不能为空".to_string()));
188        }
189
190        // 检查数据库类型
191        let backend = db.get_database_backend();
192        if backend != DatabaseBackend::Postgres {
193            return Err(TableError::QueryFailed(
194                format!("当前仅支持 PostgreSQL 数据库,当前数据库类型: {:?}", backend)
195            ));
196        }
197
198        // 测试连接是否可用
199        let _ = db.execute_unprepared("SELECT 1").await.map_err(|e| {
200            TableError::QueryFailed(format!("数据库连接不可用: {}", e))
201        })?;
202
203        // 注意:SeaORM 的 DatabaseConnection 不直接支持查询结果解析
204        // 要获取表列信息,需要使用 sqlx 连接池或通过其他方式
205        Err(TableError::QueryFailed(
206            format!(
207                "表列信息查询功能需要 sqlx 连接池支持。\
208                建议:1) 使用 sqlx 连接池直接查询,或 2) 通过数据库管理工具查询。\
209                要查询的表: {}.{}",
210                schema_name, table_name
211            )
212        ))
213    }
214
215    /// 检查表是否存在
216    pub async fn table_exists(
217        db: &DatabaseConnection,
218        schema: Option<&str>,
219        table_name: &str,
220    ) -> Result<bool, TableError> {
221        match Self::get_table_info(db, schema, table_name).await {
222            Ok(_) => Ok(true),
223            Err(TableError::TableNotFound(_)) => Ok(false),
224            Err(e) => Err(e),
225        }
226    }
227}
228
229#[cfg(test)]
230mod tests {
231    use super::*;
232
233    #[test]
234    fn test_table_info_serialization() {
235        let info = TableInfo {
236            table_name: "test_table".to_string(),
237            schema_name: "public".to_string(),
238            table_type: "BASE TABLE".to_string(),
239            table_comment: Some("测试表".to_string()),
240            row_count: Some(100),
241        };
242
243        let json = serde_json::to_string(&info).unwrap();
244        assert!(json.contains("test_table"));
245    }
246}