use crate::bindings::vtx::api::vtx_sql::{self, DbValue};
use crate::error::{VtxError, VtxResult};
use serde::de::DeserializeOwned;
pub trait ToDbValue {
fn to_db_value(&self) -> DbValue;
}
impl ToDbValue for String {
fn to_db_value(&self) -> DbValue {
DbValue::Text(self.clone())
}
}
impl ToDbValue for &str {
fn to_db_value(&self) -> DbValue {
DbValue::Text(self.to_string())
}
}
impl ToDbValue for i64 {
fn to_db_value(&self) -> DbValue {
DbValue::Integer(*self)
}
}
impl ToDbValue for i32 {
fn to_db_value(&self) -> DbValue {
DbValue::Integer(*self as i64)
}
}
impl ToDbValue for f64 {
fn to_db_value(&self) -> DbValue {
DbValue::Real(*self)
}
}
impl ToDbValue for f32 {
fn to_db_value(&self) -> DbValue {
DbValue::Real(*self as f64)
}
}
impl ToDbValue for u64 {
fn to_db_value(&self) -> DbValue {
DbValue::Integer(*self as i64)
}
}
impl ToDbValue for u32 {
fn to_db_value(&self) -> DbValue {
DbValue::Integer(*self as i64)
}
}
impl ToDbValue for bool {
fn to_db_value(&self) -> DbValue {
DbValue::Integer(if *self { 1 } else { 0 })
}
}
impl ToDbValue for () {
fn to_db_value(&self) -> DbValue {
DbValue::NullVal
}
}
impl<T: ToDbValue> ToDbValue for Option<T> {
fn to_db_value(&self) -> DbValue {
match self {
Some(v) => v.to_db_value(),
None => DbValue::NullVal,
}
}
}
pub fn execute(sql: &str, params: &[&dyn ToDbValue]) -> VtxResult<u64> {
let wit_params: Vec<DbValue> = params.iter().map(|p| p.to_db_value()).collect();
vtx_sql::execute(sql, &wit_params).map_err(|e| {
if e.to_lowercase().contains("permission denied") {
VtxError::PermissionDenied(e)
} else {
VtxError::DatabaseError(e)
}
})
}
pub fn query<T: DeserializeOwned>(sql: &str, params: &[&dyn ToDbValue]) -> VtxResult<Vec<T>> {
let wit_params: Vec<DbValue> = params.iter().map(|p| p.to_db_value()).collect();
let json_str = vtx_sql::query_json(sql, &wit_params).map_err(|e| {
if e.to_lowercase().contains("permission denied") {
VtxError::PermissionDenied(e)
} else {
VtxError::DatabaseError(e)
}
})?;
serde_json::from_str(&json_str).map_err(|e| VtxError::SerializationError(e.to_string()))
}