vtx_sdk/
db.rs

1use crate::bindings::vtx::api::sql::{self, DbValue};
2use crate::error::{VtxError, VtxResult};
3use serde::de::DeserializeOwned;
4
5/// Trait:用于将 Rust 类型转换为 WIT 定义的 `DbValue`
6///
7/// 适用于数据库跨边界调用参数传递。
8pub trait ToDbValue {
9    fn to_db_value(&self) -> DbValue;
10}
11
12// --- 基本类型到 DbValue 的映射实现 ---
13
14impl ToDbValue for String {
15    fn to_db_value(&self) -> DbValue {
16        DbValue::Text(self.clone())
17    }
18}
19
20impl ToDbValue for &str {
21    fn to_db_value(&self) -> DbValue {
22        DbValue::Text(self.to_string())
23    }
24}
25
26impl ToDbValue for i64 {
27    fn to_db_value(&self) -> DbValue {
28        DbValue::Integer(*self)
29    }
30}
31
32impl ToDbValue for i32 {
33    fn to_db_value(&self) -> DbValue {
34        DbValue::Integer(*self as i64)
35    }
36}
37
38impl ToDbValue for f64 {
39    fn to_db_value(&self) -> DbValue {
40        DbValue::Real(*self)
41    }
42}
43
44impl ToDbValue for f32 {
45    fn to_db_value(&self) -> DbValue {
46        DbValue::Real(*self as f64)
47    }
48}
49
50impl ToDbValue for u64 {
51    fn to_db_value(&self) -> DbValue {
52        DbValue::Integer(*self as i64)
53    }
54}
55
56impl ToDbValue for u32 {
57    fn to_db_value(&self) -> DbValue {
58        DbValue::Integer(*self as i64)
59    }
60}
61
62impl ToDbValue for bool {
63    fn to_db_value(&self) -> DbValue {
64        DbValue::Integer(if *self { 1 } else { 0 })
65    }
66}
67
68impl ToDbValue for () {
69    fn to_db_value(&self) -> DbValue {
70        DbValue::NullVal
71    }
72}
73
74impl<T: ToDbValue> ToDbValue for Option<T> {
75    fn to_db_value(&self) -> DbValue {
76        match self {
77            Some(v) => v.to_db_value(),
78            None => DbValue::NullVal,
79        }
80    }
81}
82
83/// 执行非查询类 SQL(INSERT / UPDATE / DELETE)
84///
85/// # Parameters
86/// - `sql`: SQL 原始字符串,支持 `?` 占位符
87/// - `params`: 参数数组,元素需实现 `ToDbValue`
88///
89/// # Returns
90/// - 成功:返回影响行数
91/// - 失败:映射为 `VtxError::DatabaseError`
92///
93/// ⚠️ 注意:Restricted 安全策略下禁止调用该接口
94pub fn execute(sql: &str, params: &[&dyn ToDbValue]) -> VtxResult<u64> {
95    let wit_params: Vec<DbValue> = params.iter().map(|p| p.to_db_value()).collect();
96
97    sql::execute(sql, &wit_params).map_err(|e| {
98        if e.to_lowercase().contains("permission denied") {
99            VtxError::PermissionDenied(e)
100        } else {
101            VtxError::DatabaseError(e)
102        }
103    })
104}
105
106/// 执行查询类 SQL(SELECT)并反序列化为目标类型列表
107///
108/// # Parameters
109/// - `sql`: SQL 字符串(支持 ? 占位符)
110/// - `params`: 参数数组(实现 `ToDbValue`)
111///
112/// # Returns
113/// - 成功:反序列化后的结果集合
114/// - 失败:`DatabaseError` 或 `SerializationError`
115///
116/// # Notes
117/// - 宿主接口返回的是 JSON 字符串
118/// - 为保证性能,建议单次返回控制在 1MB 内(可通过 LIMIT 分页)
119/// - 泛型 `T` 必须实现 `DeserializeOwned`(无需生命周期)
120///
121pub fn query<T: DeserializeOwned>(sql: &str, params: &[&dyn ToDbValue]) -> VtxResult<Vec<T>> {
122    let wit_params: Vec<DbValue> = params.iter().map(|p| p.to_db_value()).collect();
123
124    let json_str = sql::query_json(sql, &wit_params).map_err(|e| {
125        if e.to_lowercase().contains("permission denied") {
126            VtxError::PermissionDenied(e)
127        } else {
128            VtxError::DatabaseError(e)
129        }
130    })?;
131
132    serde_json::from_str(&json_str).map_err(|e| VtxError::SerializationError(e.to_string()))
133}