Skip to main content

yggdrasil/api/database/
schema.rs

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