Skip to main content

yggdrasil/api/database/
schema.rs

1#![allow(clippy::unused_unit, deprecated)]
2
3//! SQL 补全用 schema 拉取(供 CodeMirror lang-sql 表/列补全)。
4
5use crate::api::error::ApiError;
6use leptos::prelude::*;
7
8// admin 鉴权 + DB 查询仅在 server 构建里被 server function 体引用。
9#[cfg(feature = "server")]
10use crate::api::auth::get_current_admin_user;
11#[cfg(feature = "server")]
12use crate::api::error::AppError;
13#[cfg(feature = "server")]
14use crate::db::pool::get_conn;
15// SqlSchema 是两端共享的纯数据类型(server function 返回值 DTO,定义在 models);
16// SqlTable 只在下面的 server 构建分支里构造,故单独 cfg 门控,避免 web 构建 unused_imports。
17use crate::models::sql_schema::SqlSchema;
18#[cfg(feature = "server")]
19use crate::models::sql_schema::SqlTable;
20
21/// 拉取数据库 schema(表名 + 列名),供 CodeMirror SQL 补全。
22#[server(GetDbSchema, endpoint = "get_db_schema", input = leptos::server_fn::codec::Json)]
23pub async fn get_db_schema() -> Result<SqlSchema, ApiError> {
24    let _user = get_current_admin_user().await?;
25
26    #[cfg(feature = "server")]
27    {
28        let client = get_conn().await.map_err(AppError::db_conn)?;
29        let rows = client
30            .query(
31                "SELECT t.table_name, \
32                 string_agg(c.column_name, ',' ORDER BY c.ordinal_position) \
33                 FROM information_schema.tables t \
34                 JOIN information_schema.columns c USING (table_schema, table_name) \
35                 WHERE t.table_schema = 'public' AND t.table_type = 'BASE TABLE' \
36                 GROUP BY t.table_name ORDER BY t.table_name",
37                &[],
38            )
39            .await
40            .map_err(AppError::query)?;
41        let tables = rows
42            .into_iter()
43            .map(|r| {
44                let cols: String = r.get(1);
45                SqlTable {
46                    name: r.get(0),
47                    columns: cols.split(',').map(|s| s.to_string()).collect(),
48                }
49            })
50            .collect();
51        Ok(SqlSchema { tables })
52    }
53    #[cfg(not(feature = "server"))]
54    {
55        Ok(SqlSchema::default())
56    }
57}