use std::sync::Arc;
use crate::adapters::params::convert_params;
use crate::middleware::{ConversionMode, ResultSet, RowValues, SqlMiddlewareDbError};
use crate::query_utils::extract_column_names;
use crate::turso::params::Params as TursoParams;
use crate::tx_outcome::TxOutcome;
pub struct Tx<'a> {
pub(crate) tx: turso::transaction::Transaction<'a>,
}
pub struct Prepared {
stmt: turso::Statement,
cols: Arc<Vec<String>>, }
impl Tx<'_> {
pub async fn prepare(&self, sql: &str) -> Result<Prepared, SqlMiddlewareDbError> {
let stmt = self.tx.prepare(sql).await.map_err(|e| {
SqlMiddlewareDbError::ExecutionError(format!("Turso prepare error: {e}"))
})?;
let cols = extract_column_names(stmt.columns().iter(), |col| col.name());
Ok(Prepared {
stmt,
cols: Arc::new(cols),
})
}
pub async fn execute_batch(&self, sql: &str) -> Result<(), SqlMiddlewareDbError> {
self.tx.execute_batch(sql).await.map_err(|e| {
SqlMiddlewareDbError::ExecutionError(format!("Turso tx execute_batch error: {e}"))
})
}
pub async fn execute_dml(
&self,
query: &str,
params: &[RowValues],
) -> Result<usize, SqlMiddlewareDbError> {
let converted = convert_params::<TursoParams>(params, ConversionMode::Execute)?;
let affected = self.tx.execute(query, converted.0).await.map_err(|e| {
SqlMiddlewareDbError::ExecutionError(format!("Turso tx execute error: {e}"))
})?;
usize::try_from(affected).map_err(|e| {
SqlMiddlewareDbError::ExecutionError(format!(
"Turso affected rows conversion error: {e}"
))
})
}
pub async fn execute_prepared(
&self,
prepared: &mut Prepared,
params: &[RowValues],
) -> Result<usize, SqlMiddlewareDbError> {
let converted = convert_params::<TursoParams>(params, ConversionMode::Execute)?;
let affected = prepared.stmt.execute(converted.0).await.map_err(|e| {
SqlMiddlewareDbError::ExecutionError(format!("Turso tx execute(prepared) error: {e}"))
})?;
usize::try_from(affected).map_err(|e| {
SqlMiddlewareDbError::ExecutionError(format!(
"Turso affected rows conversion error: {e}"
))
})
}
pub async fn execute_select(
&self,
query: &str,
params: &[RowValues],
) -> Result<ResultSet, SqlMiddlewareDbError> {
let converted = convert_params::<TursoParams>(params, ConversionMode::Query)?;
let mut stmt = self.tx.prepare(query).await.map_err(|e| {
SqlMiddlewareDbError::ExecutionError(format!("Turso tx prepare error: {e}"))
})?;
let cols = extract_column_names(stmt.columns().iter(), |col| col.name());
let cols_arc = Arc::new(cols);
let rows = stmt.query(converted.0).await.map_err(|e| {
SqlMiddlewareDbError::ExecutionError(format!("Turso tx query error: {e}"))
})?;
crate::turso::query::build_result_set(rows, Some(cols_arc)).await
}
pub async fn query_prepared(
&self,
prepared: &mut Prepared,
params: &[RowValues],
) -> Result<ResultSet, SqlMiddlewareDbError> {
let converted = convert_params::<TursoParams>(params, ConversionMode::Query)?;
let rows = prepared.stmt.query(converted.0).await.map_err(|e| {
SqlMiddlewareDbError::ExecutionError(format!("Turso tx query(prepared) error: {e}"))
})?;
crate::turso::query::build_result_set(rows, Some(prepared.cols.clone())).await
}
pub async fn commit(self) -> Result<TxOutcome, SqlMiddlewareDbError> {
self.tx
.commit()
.await
.map_err(|e| SqlMiddlewareDbError::ExecutionError(format!("Turso commit error: {e}")))
.map(|()| TxOutcome::without_restored_connection())
}
pub async fn rollback(self) -> Result<TxOutcome, SqlMiddlewareDbError> {
self.tx
.rollback()
.await
.map_err(|e| SqlMiddlewareDbError::ExecutionError(format!("Turso rollback error: {e}")))
.map(|()| TxOutcome::without_restored_connection())
}
}
pub async fn begin_transaction(
conn: &mut turso::Connection,
) -> Result<Tx<'_>, SqlMiddlewareDbError> {
let tx = conn.transaction().await.map_err(|e| {
SqlMiddlewareDbError::ExecutionError(format!("Turso begin transaction error: {e}"))
})?;
Ok(Tx { tx })
}