use serde::{Serialize, de::DeserializeOwned};
use vantage_dataset::dataset::{Result, WritableDataSet};
use vantage_table::{Entity, Table};
use super::{SurrealTableCore, SurrealTableSelectable};
use crate::SurrealDB;
#[async_trait::async_trait]
pub trait SurrealTableTransform<E: Entity>: SurrealTableCore<E> {
async fn map<F>(self, transform: F) -> Result<Self>
where
Self: Sized,
F: Fn(E) -> E + Send + Sync;
async fn map_async<F, Fut>(self, transform: F) -> Result<Self>
where
Self: Sized,
F: Fn(E) -> Fut + Send + Sync,
Fut: std::future::Future<Output = E> + Send;
async fn filter<F>(self, predicate: F) -> Result<Self>
where
Self: Sized,
F: Fn(&E) -> bool + Send + Sync;
async fn update_where<P, T>(self, predicate: P, transform: T) -> Result<Self>
where
Self: Sized,
P: Fn(&E) -> bool + Send + Sync,
T: Fn(E) -> E + Send + Sync;
}
#[async_trait::async_trait]
impl<E> SurrealTableTransform<E> for Table<SurrealDB, E>
where
E: Entity + Serialize + DeserializeOwned + Send + Sync + 'static,
{
async fn map<F>(self, transform: F) -> Result<Self>
where
Self: Sized,
F: Fn(E) -> E + Send + Sync,
{
self.update(move |record| {
let transformed = transform(record.clone());
*record = transformed;
})
.await?;
Ok(self)
}
async fn map_async<F, Fut>(self, transform: F) -> Result<Self>
where
Self: Sized,
F: Fn(E) -> Fut + Send + Sync,
Fut: std::future::Future<Output = E> + Send,
{
let records = self.get_with_ids().await?;
for (id, record) in records {
let transformed = transform(record).await;
self.replace_id(id, transformed).await?;
}
Ok(self)
}
async fn filter<F>(self, predicate: F) -> Result<Self>
where
Self: Sized,
F: Fn(&E) -> bool + Send + Sync,
{
let records = self.get_with_ids().await?;
for (id, record) in records {
if !predicate(&record) {
self.delete_id(id).await?;
}
}
Ok(self)
}
async fn update_where<P, T>(self, predicate: P, transform: T) -> Result<Self>
where
Self: Sized,
P: Fn(&E) -> bool + Send + Sync,
T: Fn(E) -> E + Send + Sync,
{
self.update(move |record| {
if predicate(record) {
let transformed = transform(record.clone());
*record = transformed;
}
})
.await?;
Ok(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
struct TestEntity {
name: String,
value: i32,
active: bool,
}
impl Entity for TestEntity {}
#[test]
fn test_transform_api() {
}
}