#![cfg(any(
feature = "mysql",
feature = "postgres",
feature = "sqlite",
feature = "mariadb"
))]
use std::future::Future;
use futures::{Stream, TryStreamExt};
pub use ormx_macros::*;
use sqlx::{Executor, Result};
#[doc(hidden)]
pub mod exports {
pub use futures::Stream;
pub use crate::query2::map::*;
}
#[cfg(any(feature = "mysql", feature = "postgres", feature = "mariadb"))]
mod query2;
#[cfg(any(feature = "mysql", feature = "mariadb"))]
pub type Db = sqlx::MySql;
#[cfg(feature = "postgres")]
pub type Db = sqlx::Postgres;
#[cfg(feature = "sqlite")]
pub type Db = sqlx::Sqlite;
pub trait Table
where
Self: Sized + Send + Sync + 'static,
{
type Id: 'static + Copy + Send;
fn id(&self) -> Self::Id;
fn insert<'a, 'c: 'a>(
#[cfg(not(feature = "mysql"))] db: impl Executor<'c, Database = Db> + 'a,
#[cfg(feature = "mysql")] db: &'c mut sqlx::MySqlConnection,
row: impl Insert<Table = Self>,
) -> impl Future<Output = Result<Self>> + Send + 'a {
row.insert(db)
}
fn get<'a, 'c: 'a>(
db: impl Executor<'c, Database = Db> + 'a,
id: Self::Id,
) -> impl Future<Output = Result<Self>> + Send + 'a;
fn stream_all<'a, 'c: 'a>(
db: impl Executor<'c, Database = Db> + 'a,
) -> impl Stream<Item = Result<Self>> + Send + 'a;
fn stream_all_paginated<'a, 'c: 'a>(
db: impl Executor<'c, Database = Db> + 'a,
offset: i64,
limit: i64,
) -> impl Stream<Item = Result<Self>> + Send + 'a;
fn all<'a, 'c: 'a>(
db: impl Executor<'c, Database = Db> + 'a,
) -> impl Future<Output = Result<Vec<Self>>> + Send + 'a {
Self::stream_all(db).try_collect()
}
fn all_paginated<'a, 'c: 'a>(
db: impl Executor<'c, Database = Db> + 'a,
offset: i64,
limit: i64,
) -> impl Future<Output = Result<Vec<Self>>> + Send + 'a {
Self::stream_all_paginated(db, offset, limit).try_collect()
}
fn patch<'a, 'c: 'a, P>(
&'a mut self,
db: impl Executor<'c, Database = Db> + 'a,
patch: P,
) -> impl Future<Output = Result<()>> + Send + 'a
where
P: Patch<Table = Self>,
{
async move {
let patch: P = patch;
patch.patch_row(db, self.id()).send().await?;
patch.apply_to(self);
Ok(())
}
}
fn update<'a, 'c: 'a>(
&'a self,
db: impl Executor<'c, Database = Db> + 'a,
) -> impl Future<Output = Result<()>> + Send + 'a;
fn reload<'a, 'c: 'a>(
&'a mut self,
db: impl Executor<'c, Database = Db> + 'a,
) -> impl Future<Output = Result<()>> + Send + 'a {
async move {
*self = Self::get(db, self.id()).send().await?;
Ok(())
}
}
}
pub trait Delete
where
Self: Table + Sized + Send + Sync + 'static,
{
fn delete_row<'a, 'c: 'a>(
db: impl Executor<'c, Database = Db> + 'a,
id: Self::Id,
) -> impl Future<Output = Result<()>> + Send + 'a;
fn delete<'a, 'c: 'a>(
self,
db: impl Executor<'c, Database = Db> + 'a,
) -> impl Future<Output = Result<()>> + Send + 'a {
Self::delete_row(db, self.id())
}
fn delete_ref<'a, 'c: 'a>(
&self,
db: impl Executor<'c, Database = Db> + 'a,
) -> impl Future<Output = Result<()>> + Send + 'a {
Self::delete_row(db, self.id())
}
}
pub trait Patch
where
Self: Sized + Send + Sync + 'static,
{
type Table: Table;
fn apply_to(self, entity: &mut Self::Table);
fn patch_row<'a, 'c: 'a>(
&'a self,
db: impl Executor<'c, Database = Db> + 'a,
id: <Self::Table as Table>::Id,
) -> impl Future<Output = Result<()>> + Send + 'a;
}
pub trait Insert
where
Self: Sized + Send + Sync + 'static,
{
type Table: Table;
fn insert<'a, 'c: 'a>(
self,
#[cfg(not(feature = "mysql"))] db: impl Executor<'c, Database = Db> + 'a,
#[cfg(feature = "mysql")] db: &'c mut sqlx::MySqlConnection,
) -> impl Future<Output = Result<Self::Table>> + Send + 'a;
}
trait SendFuture: Future {
fn send(self) -> impl Future<Output = Self::Output> + Send
where
Self: Sized + Send,
{
self
}
}
impl<T: Future> SendFuture for T {}