#![allow(clippy::upper_case_acronyms)]
use super::{SqlStatement, common_helpers};
use crate::model::{Model, Relation, RelationInfo, Value, normalize_table_name_for_db};
use crate::query::builder::WhereExpr;
use crate::query::insert::{IntoInsertAssignment, IntoInsertDefaultColumn};
use crate::raw_sql::{IntoRawSql, RawSql};
#[cfg(feature = "sqlite")]
use super::super::sqlite_backend;
#[cfg(feature = "postgresql")]
use super::super::postgresql_backend;
#[cfg(feature = "mysql")]
use super::super::mysql_backend;
#[cfg(feature = "mssql")]
use super::super::mssql_backend;
fn model_value_key(value: &Value) -> String {
match value {
Value::Integer(v) => format!("i:{v}"),
Value::BigInt(v) => format!("b:{v}"),
Value::Duration(v) => format!("d:{:?}", v),
Value::Text(v) => format!("t:{v}"),
Value::TextArray(v) => format!("ta:{v:?}"),
Value::Real(v) => format!("r:{v}"),
Value::Boolean(v) => format!("o:{v}"),
Value::Bytes(v) => format!("x:{v:?}"),
Value::IntegerArray(v) => format!("ia:{v:?}"),
Value::BigIntArray(v) => format!("ba:{v:?}"),
Value::NullableBigIntArray(v) => format!("na:{v:?}"),
Value::DateTime(v) => format!("dt:{v}"),
Value::Date(v) => format!("da:{v}"),
Value::Time(v) => format!("ti:{v}"),
Value::Json(v) => format!("j:{v}"),
Value::Uuid(v) => format!("u:{v}"),
Value::Null => "n:".to_string(),
}
}
fn relation_filter_values(values: Vec<Value>) -> Vec<crate::query::filter::Value> {
let mut seen = std::collections::HashSet::new();
values
.into_iter()
.filter(|value| !matches!(value, Value::Null))
.filter(|value| seen.insert(model_value_key(value)))
.map(Into::into)
.collect()
}
fn primary_key_filter<T: Model>(key: impl crate::model::PrimaryKey) -> crate::Result<WhereExpr> {
let pk_columns = T::primary_key_columns();
let pk_values = key.into_values();
if pk_columns.is_empty() {
return Err(crate::ormer_error!(
"Model {} does not have a primary key",
T::TABLE_NAME
));
}
if pk_columns.len() != pk_values.len() {
return Err(crate::ormer_error!(
"Primary key column count ({}) does not match value count ({})",
pk_columns.len(),
pk_values.len()
));
}
let filters = pk_columns.iter().zip(pk_values).map(|(col, val)| {
crate::query::filter::FilterExpr::Comparison {
column: col.to_string(),
operator: "=".to_string(),
value: common_helpers::value_to_filter_value(&val),
}
});
let mut filters = filters.into_iter();
let Some(filter) = filters.next() else {
return Err(crate::ormer_error!(
"Model {} does not have a primary key filter",
T::TABLE_NAME
));
};
let filter = filters.fold(filter, |a, b| {
crate::query::filter::FilterExpr::And(Box::new(a), Box::new(b))
});
Ok(WhereExpr::from_filter(filter))
}
fn quote_table_name(db_type: super::super::DbType, table_name: &str) -> String {
let normalized = normalize_table_name_for_db(db_type, table_name);
match db_type {
#[cfg(feature = "postgresql")]
super::super::DbType::PostgreSQL => {
let (schema, table) = crate::model::split_schema_table_name(normalized, "public");
if schema == "public" {
crate::model::quote_identifier(db_type, table)
} else {
format!(
"{}.{}",
crate::model::quote_identifier(db_type, schema),
crate::model::quote_identifier(db_type, table)
)
}
}
#[cfg(feature = "mssql")]
super::super::DbType::MSSQL => {
let (schema, table) = crate::model::split_schema_table_name(normalized, "dbo");
if schema == "dbo" {
crate::model::quote_identifier(db_type, table)
} else {
format!(
"{}.{}",
crate::model::quote_identifier(db_type, schema),
crate::model::quote_identifier(db_type, table)
)
}
}
#[cfg(feature = "sqlite")]
super::super::DbType::Sqlite => crate::model::quote_identifier(db_type, normalized),
#[cfg(feature = "mysql")]
super::super::DbType::MySQL => crate::model::quote_identifier(db_type, normalized),
}
}
pub enum Database {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::Database),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::Database),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::Database),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::Database),
}
pub enum CreateTableExecutor<'a, T: Model> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::CreateTableExecutor<'a, T>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::CreateTableExecutor<'a, T>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::CreateTableExecutor<'a, T>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::CreateTableExecutor<'a, T>),
}
impl<'a, T: Model> CreateTableExecutor<'a, T> {
pub fn to_sql(&self) -> crate::Result<SqlStatement> {
match self {
#[cfg(feature = "sqlite")]
CreateTableExecutor::Sqlite(exec) => exec.to_sql(),
#[cfg(feature = "postgresql")]
CreateTableExecutor::PostgreSQL(exec) => exec.to_sql(),
#[cfg(feature = "mysql")]
CreateTableExecutor::MySQL(exec) => exec.to_sql(),
#[cfg(feature = "mssql")]
CreateTableExecutor::MSSQL(exec) => exec.to_sql(),
}
}
pub async fn execute(self) -> crate::Result<()> {
match self {
#[cfg(feature = "sqlite")]
CreateTableExecutor::Sqlite(exec) => exec.execute().await,
#[cfg(feature = "postgresql")]
CreateTableExecutor::PostgreSQL(exec) => exec.execute().await,
#[cfg(feature = "mysql")]
CreateTableExecutor::MySQL(exec) => exec.execute().await,
#[cfg(feature = "mssql")]
CreateTableExecutor::MSSQL(exec) => exec.execute().await,
}
}
}
pub enum DropTableExecutor<'a, T: Model> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::DropTableExecutor<'a, T>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::DropTableExecutor<'a, T>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::DropTableExecutor<'a, T>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::DropTableExecutor<'a, T>),
}
impl<'a, T: Model> DropTableExecutor<'a, T> {
pub fn to_sql(&self) -> crate::Result<SqlStatement> {
match self {
#[cfg(feature = "sqlite")]
DropTableExecutor::Sqlite(exec) => exec.to_sql(),
#[cfg(feature = "postgresql")]
DropTableExecutor::PostgreSQL(exec) => exec.to_sql(),
#[cfg(feature = "mysql")]
DropTableExecutor::MySQL(exec) => exec.to_sql(),
#[cfg(feature = "mssql")]
DropTableExecutor::MSSQL(exec) => exec.to_sql(),
}
}
pub async fn execute(self) -> crate::Result<()> {
match self {
#[cfg(feature = "sqlite")]
DropTableExecutor::Sqlite(exec) => exec.execute().await,
#[cfg(feature = "postgresql")]
DropTableExecutor::PostgreSQL(exec) => exec.execute().await,
#[cfg(feature = "mysql")]
DropTableExecutor::MySQL(exec) => exec.execute().await,
#[cfg(feature = "mssql")]
DropTableExecutor::MSSQL(exec) => exec.execute().await,
}
}
}
pub enum InsertExecutor<'a, I: crate::model::Insertable> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::InsertExecutor<'a, I>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::InsertExecutor<'a, I>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::InsertExecutor<'a, I>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::InsertExecutor<'a, I>),
}
pub enum InsertPartialExecutor<'a, T: Model> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::InsertPartialExecutor<'a, T>,
std::marker::PhantomData<&'a T>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::InsertPartialExecutor<'a, T>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::InsertPartialExecutor<'a, T>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::InsertPartialExecutor<'a, T>),
}
impl<'a, T: Model + Send + Sync> InsertPartialExecutor<'a, T> {
pub fn set<F, A>(self, f: F) -> Self
where
F: FnOnce(T::Where) -> A,
A: IntoInsertAssignment<T>,
{
match self {
#[cfg(feature = "sqlite")]
InsertPartialExecutor::Sqlite(exec, phantom) => {
InsertPartialExecutor::Sqlite(exec.set(f), phantom)
}
#[cfg(feature = "postgresql")]
InsertPartialExecutor::PostgreSQL(exec) => {
InsertPartialExecutor::PostgreSQL(exec.set(f))
}
#[cfg(feature = "mysql")]
InsertPartialExecutor::MySQL(exec) => InsertPartialExecutor::MySQL(exec.set(f)),
#[cfg(feature = "mssql")]
InsertPartialExecutor::MSSQL(exec) => InsertPartialExecutor::MSSQL(exec.set(f)),
}
}
pub fn default<F, C>(self, f: F) -> Self
where
F: FnOnce(T::Where) -> C,
C: IntoInsertDefaultColumn<T>,
{
match self {
#[cfg(feature = "sqlite")]
InsertPartialExecutor::Sqlite(exec, phantom) => {
InsertPartialExecutor::Sqlite(exec.default(f), phantom)
}
#[cfg(feature = "postgresql")]
InsertPartialExecutor::PostgreSQL(exec) => {
InsertPartialExecutor::PostgreSQL(exec.default(f))
}
#[cfg(feature = "mysql")]
InsertPartialExecutor::MySQL(exec) => InsertPartialExecutor::MySQL(exec.default(f)),
#[cfg(feature = "mssql")]
InsertPartialExecutor::MSSQL(exec) => InsertPartialExecutor::MSSQL(exec.default(f)),
}
}
pub fn to_sql(&self) -> crate::Result<SqlStatement> {
match self {
#[cfg(feature = "sqlite")]
InsertPartialExecutor::Sqlite(exec, _) => exec.to_sql(),
#[cfg(feature = "postgresql")]
InsertPartialExecutor::PostgreSQL(exec) => exec.to_sql(),
#[cfg(feature = "mysql")]
InsertPartialExecutor::MySQL(exec) => exec.to_sql(),
#[cfg(feature = "mssql")]
InsertPartialExecutor::MSSQL(exec) => exec.to_sql(),
}
}
pub async fn execute(self) -> crate::Result<<T as Model>::AutoIncrementKeyType> {
match self {
#[cfg(feature = "sqlite")]
InsertPartialExecutor::Sqlite(exec, _) => exec.execute().await,
#[cfg(feature = "postgresql")]
InsertPartialExecutor::PostgreSQL(exec) => exec.execute().await,
#[cfg(feature = "mysql")]
InsertPartialExecutor::MySQL(exec) => exec.execute().await,
#[cfg(feature = "mssql")]
InsertPartialExecutor::MSSQL(exec) => exec.execute().await,
}
}
}
impl<'a, I: crate::model::Insertable + Send + Sync> InsertExecutor<'a, I> {
pub fn on_conflict<F, C>(self, f: F) -> Self
where
F: FnOnce(<I::Model as Model>::Where) -> C,
C: crate::query::insert::ConflictColumns,
{
match self {
#[cfg(feature = "sqlite")]
InsertExecutor::Sqlite(exec) => InsertExecutor::Sqlite(exec.on_conflict(f)),
#[cfg(feature = "postgresql")]
InsertExecutor::PostgreSQL(exec) => InsertExecutor::PostgreSQL(exec.on_conflict(f)),
#[cfg(feature = "mysql")]
InsertExecutor::MySQL(exec) => InsertExecutor::MySQL(exec.on_conflict(f)),
#[cfg(feature = "mssql")]
InsertExecutor::MSSQL(exec) => InsertExecutor::MSSQL(exec.on_conflict(f)),
}
}
pub fn on_constraint<Target>(self, target: Target) -> Self
where
Target: crate::query::insert::IntoInsertConflictTarget<I::Model>,
{
match self {
#[cfg(feature = "sqlite")]
InsertExecutor::Sqlite(exec) => InsertExecutor::Sqlite(exec.on_constraint(target)),
#[cfg(feature = "postgresql")]
InsertExecutor::PostgreSQL(exec) => {
InsertExecutor::PostgreSQL(exec.on_constraint(target))
}
#[cfg(feature = "mysql")]
InsertExecutor::MySQL(exec) => InsertExecutor::MySQL(exec.on_constraint(target)),
#[cfg(feature = "mssql")]
InsertExecutor::MSSQL(exec) => InsertExecutor::MSSQL(exec.on_constraint(target)),
}
}
pub fn conflict_where<F>(self, f: F) -> Self
where
F: FnOnce(<I::Model as Model>::Where) -> WhereExpr,
{
match self {
#[cfg(feature = "sqlite")]
InsertExecutor::Sqlite(exec) => InsertExecutor::Sqlite(exec.conflict_where(f)),
#[cfg(feature = "postgresql")]
InsertExecutor::PostgreSQL(exec) => InsertExecutor::PostgreSQL(exec.conflict_where(f)),
#[cfg(feature = "mysql")]
InsertExecutor::MySQL(exec) => InsertExecutor::MySQL(exec.conflict_where(f)),
#[cfg(feature = "mssql")]
InsertExecutor::MSSQL(exec) => InsertExecutor::MSSQL(exec.conflict_where(f)),
}
}
pub fn do_nothing(self) -> Self {
match self {
#[cfg(feature = "sqlite")]
InsertExecutor::Sqlite(exec) => InsertExecutor::Sqlite(exec.do_nothing()),
#[cfg(feature = "postgresql")]
InsertExecutor::PostgreSQL(exec) => InsertExecutor::PostgreSQL(exec.do_nothing()),
#[cfg(feature = "mysql")]
InsertExecutor::MySQL(exec) => InsertExecutor::MySQL(exec.do_nothing()),
#[cfg(feature = "mssql")]
InsertExecutor::MSSQL(exec) => InsertExecutor::MSSQL(exec.do_nothing()),
}
}
pub fn do_update(self) -> Self {
match self {
#[cfg(feature = "sqlite")]
InsertExecutor::Sqlite(exec) => InsertExecutor::Sqlite(exec.do_update()),
#[cfg(feature = "postgresql")]
InsertExecutor::PostgreSQL(exec) => InsertExecutor::PostgreSQL(exec.do_update()),
#[cfg(feature = "mysql")]
InsertExecutor::MySQL(exec) => InsertExecutor::MySQL(exec.do_update()),
#[cfg(feature = "mssql")]
InsertExecutor::MSSQL(exec) => InsertExecutor::MSSQL(exec.do_update()),
}
}
pub fn do_update_if<F>(self, f: F) -> Self
where
F: FnOnce(<I::Model as Model>::Where) -> WhereExpr,
{
match self {
#[cfg(feature = "sqlite")]
InsertExecutor::Sqlite(exec) => InsertExecutor::Sqlite(exec.do_update_if(f)),
#[cfg(feature = "postgresql")]
InsertExecutor::PostgreSQL(exec) => InsertExecutor::PostgreSQL(exec.do_update_if(f)),
#[cfg(feature = "mysql")]
InsertExecutor::MySQL(exec) => InsertExecutor::MySQL(exec.do_update_if(f)),
#[cfg(feature = "mssql")]
InsertExecutor::MSSQL(exec) => InsertExecutor::MSSQL(exec.do_update_if(f)),
}
}
pub fn set<F>(self, f: F) -> Self
where
F: FnOnce(&mut <I::Model as Model>::Update),
{
match self {
#[cfg(feature = "sqlite")]
InsertExecutor::Sqlite(exec) => InsertExecutor::Sqlite(exec.set(f)),
#[cfg(feature = "postgresql")]
InsertExecutor::PostgreSQL(exec) => InsertExecutor::PostgreSQL(exec.set(f)),
#[cfg(feature = "mysql")]
InsertExecutor::MySQL(exec) => InsertExecutor::MySQL(exec.set(f)),
#[cfg(feature = "mssql")]
InsertExecutor::MSSQL(exec) => InsertExecutor::MSSQL(exec.set(f)),
}
}
pub fn to_sql(&self) -> crate::Result<SqlStatement> {
match self {
#[cfg(feature = "sqlite")]
InsertExecutor::Sqlite(exec) => exec.to_sql(),
#[cfg(feature = "postgresql")]
InsertExecutor::PostgreSQL(exec) => exec.to_sql(),
#[cfg(feature = "mysql")]
InsertExecutor::MySQL(exec) => exec.to_sql(),
#[cfg(feature = "mssql")]
InsertExecutor::MSSQL(exec) => exec.to_sql(),
}
}
pub async fn execute(
self,
) -> crate::Result<<I::Model as crate::model::Model>::AutoIncrementKeyType> {
match self {
#[cfg(feature = "sqlite")]
InsertExecutor::Sqlite(exec) => exec.execute().await,
#[cfg(feature = "postgresql")]
InsertExecutor::PostgreSQL(exec) => exec.execute().await,
#[cfg(feature = "mysql")]
InsertExecutor::MySQL(exec) => exec.execute().await,
#[cfg(feature = "mssql")]
InsertExecutor::MSSQL(exec) => exec.execute().await,
}
}
pub async fn returning(self) -> crate::Result<Vec<I::Model>> {
match self {
#[cfg(feature = "sqlite")]
InsertExecutor::Sqlite(exec) => exec.returning().await,
#[cfg(feature = "postgresql")]
InsertExecutor::PostgreSQL(exec) => exec.returning().await,
#[cfg(feature = "mysql")]
InsertExecutor::MySQL(exec) => exec.returning().await,
#[cfg(feature = "mssql")]
InsertExecutor::MSSQL(exec) => exec.returning().await,
}
}
}
pub enum InsertOrUpdateExecutor<'a, I: crate::model::Insertable> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::InsertOrUpdateExecutor<'a, I>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::InsertOrUpdateExecutor<'a, I>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::InsertOrUpdateExecutor<'a, I>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::InsertOrUpdateExecutor<'a, I>),
}
impl<'a, I: crate::model::Insertable + Send + Sync> InsertOrUpdateExecutor<'a, I> {
pub fn to_sql(&self) -> crate::Result<SqlStatement> {
match self {
#[cfg(feature = "sqlite")]
InsertOrUpdateExecutor::Sqlite(exec) => exec.to_sql(),
#[cfg(feature = "postgresql")]
InsertOrUpdateExecutor::PostgreSQL(exec) => exec.to_sql(),
#[cfg(feature = "mysql")]
InsertOrUpdateExecutor::MySQL(exec) => exec.to_sql(),
#[cfg(feature = "mssql")]
InsertOrUpdateExecutor::MSSQL(exec) => exec.to_sql(),
}
}
pub async fn execute(self) -> crate::Result<()> {
match self {
#[cfg(feature = "sqlite")]
InsertOrUpdateExecutor::Sqlite(exec) => exec.execute().await,
#[cfg(feature = "postgresql")]
InsertOrUpdateExecutor::PostgreSQL(exec) => exec.execute().await,
#[cfg(feature = "mysql")]
InsertOrUpdateExecutor::MySQL(exec) => exec.execute().await,
#[cfg(feature = "mssql")]
InsertOrUpdateExecutor::MSSQL(exec) => exec.execute().await.map(|_| ()),
}
}
}
pub enum InsertOrIgnoreExecutor<'a, I: crate::model::Insertable> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::InsertOrIgnoreExecutor<'a, I>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::InsertOrIgnoreExecutor<'a, I>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::InsertOrIgnoreExecutor<'a, I>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::InsertOrIgnoreExecutor<'a, I>),
}
impl<'a, I: crate::model::Insertable + Send + Sync> InsertOrIgnoreExecutor<'a, I> {
pub fn to_sql(&self) -> crate::Result<SqlStatement> {
match self {
#[cfg(feature = "sqlite")]
InsertOrIgnoreExecutor::Sqlite(exec) => exec.to_sql(),
#[cfg(feature = "postgresql")]
InsertOrIgnoreExecutor::PostgreSQL(exec) => exec.to_sql(),
#[cfg(feature = "mysql")]
InsertOrIgnoreExecutor::MySQL(exec) => exec.to_sql(),
#[cfg(feature = "mssql")]
InsertOrIgnoreExecutor::MSSQL(exec) => exec.to_sql(),
}
}
pub async fn execute(self) -> crate::Result<()> {
match self {
#[cfg(feature = "sqlite")]
InsertOrIgnoreExecutor::Sqlite(exec) => exec.execute().await,
#[cfg(feature = "postgresql")]
InsertOrIgnoreExecutor::PostgreSQL(exec) => exec.execute().await,
#[cfg(feature = "mysql")]
InsertOrIgnoreExecutor::MySQL(exec) => exec.execute().await,
#[cfg(feature = "mssql")]
InsertOrIgnoreExecutor::MSSQL(exec) => exec.execute().await.map(|_| ()),
}
}
}
impl Database {
pub async fn connect(
db_type: super::super::DbType,
connection_string: &str,
) -> crate::Result<Self> {
match db_type {
#[cfg(feature = "sqlite")]
super::super::DbType::Sqlite => {
let db = sqlite_backend::Database::connect(db_type, connection_string).await?;
Ok(Database::Sqlite(db))
}
#[cfg(feature = "postgresql")]
super::super::DbType::PostgreSQL => {
let db = postgresql_backend::Database::connect(db_type, connection_string).await?;
Ok(Database::PostgreSQL(db))
}
#[cfg(feature = "mysql")]
super::super::DbType::MySQL => {
let db = mysql_backend::Database::connect(db_type, connection_string).await?;
Ok(Database::MySQL(db))
}
#[cfg(feature = "mssql")]
super::super::DbType::MSSQL => {
let db = mssql_backend::Database::connect(db_type, connection_string).await?;
Ok(Database::MSSQL(db))
}
}
}
pub fn create_table<T: Model>(&self) -> CreateTableExecutor<'_, T> {
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => CreateTableExecutor::Sqlite(db.create_table::<T>()),
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => CreateTableExecutor::PostgreSQL(db.create_table::<T>()),
#[cfg(feature = "mysql")]
Database::MySQL(db) => CreateTableExecutor::MySQL(db.create_table::<T>()),
#[cfg(feature = "mssql")]
Database::MSSQL(db) => CreateTableExecutor::MSSQL(db.create_table::<T>()),
}
}
pub async fn validate_table<T: Model>(&self) -> crate::Result<()> {
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => db.validate_table::<T>().await,
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => db.validate_table::<T>().await,
#[cfg(feature = "mysql")]
Database::MySQL(db) => db.validate_table::<T>().await,
#[cfg(feature = "mssql")]
Database::MSSQL(db) => db.validate_table::<T>().await,
}
}
pub fn insert<I: crate::model::Insertable>(&self, models: I) -> InsertExecutor<'_, I> {
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => InsertExecutor::Sqlite(db.insert::<I>(models)),
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => InsertExecutor::PostgreSQL(db.insert::<I>(models)),
#[cfg(feature = "mysql")]
Database::MySQL(db) => InsertExecutor::MySQL(db.insert::<I>(models)),
#[cfg(feature = "mssql")]
Database::MSSQL(db) => InsertExecutor::MSSQL(db.insert::<I>(models)),
}
}
pub fn insert_partial<T: Model + Send + Sync>(&self) -> InsertPartialExecutor<'_, T> {
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => {
InsertPartialExecutor::Sqlite(db.insert_partial::<T>(), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => InsertPartialExecutor::PostgreSQL(db.insert_partial::<T>()),
#[cfg(feature = "mysql")]
Database::MySQL(db) => InsertPartialExecutor::MySQL(db.insert_partial::<T>()),
#[cfg(feature = "mssql")]
Database::MSSQL(db) => InsertPartialExecutor::MSSQL(db.insert_partial::<T>()),
}
}
pub fn insert_model<T>(
&self,
model: impl crate::model::InsertModel<T>,
) -> InsertPartialExecutor<'_, T>
where
T: Model + Send + Sync,
{
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => {
InsertPartialExecutor::Sqlite(db.insert_model::<T>(model), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => {
InsertPartialExecutor::PostgreSQL(db.insert_model::<T>(model))
}
#[cfg(feature = "mysql")]
Database::MySQL(db) => InsertPartialExecutor::MySQL(db.insert_model::<T>(model)),
#[cfg(feature = "mssql")]
Database::MSSQL(db) => InsertPartialExecutor::MSSQL(db.insert_model::<T>(model)),
}
}
pub fn insert_or_update<I: crate::model::Insertable>(
&self,
models: I,
) -> InsertOrUpdateExecutor<'_, I> {
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => {
InsertOrUpdateExecutor::Sqlite(db.insert_or_update::<I>(models))
}
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => {
InsertOrUpdateExecutor::PostgreSQL(db.insert_or_update::<I>(models))
}
#[cfg(feature = "mysql")]
Database::MySQL(db) => InsertOrUpdateExecutor::MySQL(db.insert_or_update::<I>(models)),
#[cfg(feature = "mssql")]
Database::MSSQL(db) => InsertOrUpdateExecutor::MSSQL(db.insert_or_update::<I>(models)),
}
}
pub fn upsert<I: crate::model::Insertable>(&self, models: I) -> InsertOrUpdateExecutor<'_, I> {
self.insert_or_update(models)
}
pub fn insert_or_ignore<I: crate::model::Insertable>(
&self,
models: I,
) -> InsertOrIgnoreExecutor<'_, I> {
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => {
InsertOrIgnoreExecutor::Sqlite(db.insert_or_ignore::<I>(models))
}
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => {
InsertOrIgnoreExecutor::PostgreSQL(db.insert_or_ignore::<I>(models))
}
#[cfg(feature = "mysql")]
Database::MySQL(db) => InsertOrIgnoreExecutor::MySQL(db.insert_or_ignore::<I>(models)),
#[cfg(feature = "mssql")]
Database::MSSQL(db) => InsertOrIgnoreExecutor::MSSQL(db.insert_or_ignore::<I>(models)),
}
}
pub async fn find_by_id<T: Model + 'static + std::marker::Send + std::marker::Sync>(
&self,
key: impl crate::model::PrimaryKey,
) -> crate::Result<Option<T>> {
let where_expr = primary_key_filter::<T>(key)?;
let results = self
.select::<T>()
.filter(|_| where_expr)
.range(..1)
.collect::<Vec<T>>()
.await?;
Ok(results.into_iter().next())
}
pub async fn find_related<
T: Model + 'static + std::marker::Send + std::marker::Sync,
R: Model + Clone + 'static + std::marker::Send + std::marker::Sync,
>(
&self,
owner: &T,
relation: Relation<T, R>,
) -> crate::Result<Vec<R>> {
let relation = relation.info()?;
let key = owner.relation_key_value(relation)?;
self.select_related::<R>(relation, vec![key]).await
}
pub async fn preload<
T: Model + 'static + std::marker::Send + std::marker::Sync,
R: Model + Clone + 'static + std::marker::Send + std::marker::Sync,
>(
&self,
owners: &mut [T],
relation: Relation<T, R>,
) -> crate::Result<()> {
let relation = relation.info()?;
let owner_keys = owners
.iter()
.map(|owner| owner.relation_key_value(relation))
.collect::<crate::Result<Vec<_>>>()?;
let related = self.select_related::<R>(relation, owner_keys).await?;
let mut grouped: std::collections::HashMap<String, Vec<R>> =
std::collections::HashMap::new();
for item in related {
if let Some(key) = item.column_value(relation.target_key) {
grouped.entry(model_value_key(&key)).or_default().push(item);
}
}
for owner in owners {
let key = owner.relation_key_value(relation)?;
let values = grouped
.get(&model_value_key(&key))
.cloned()
.unwrap_or_default();
owner.assign_relation(relation.name, values)?;
}
Ok(())
}
async fn select_related<R: Model + Clone + 'static + std::marker::Send + std::marker::Sync>(
&self,
relation: &RelationInfo,
keys: Vec<Value>,
) -> crate::Result<Vec<R>> {
let values = relation_filter_values(keys);
if values.is_empty() {
return Ok(Vec::new());
}
self.select::<R>()
.filter(|_| {
WhereExpr::from_filter(crate::query::filter::FilterExpr::In {
column: relation.target_key.to_string(),
values,
})
})
.collect::<Vec<R>>()
.await
}
pub fn select<T: Model>(&self) -> SelectExecutor<'_, T> {
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => SelectExecutor::Sqlite(db.select::<T>()),
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => SelectExecutor::PostgreSQL(db.select::<T>()),
#[cfg(feature = "mysql")]
Database::MySQL(db) => SelectExecutor::MySQL(db.select::<T>()),
#[cfg(feature = "mssql")]
Database::MSSQL(db) => SelectExecutor::MSSQL(db.select::<T>()),
}
}
pub fn select_column<T: Model, V>(&self) -> GroupedSelectExecutor<'_, T, V> {
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => GroupedSelectExecutor::Sqlite(db.select_column::<T, V>()),
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => {
GroupedSelectExecutor::PostgreSQL(db.select_column::<T, V>())
}
#[cfg(feature = "mysql")]
Database::MySQL(db) => GroupedSelectExecutor::MySQL(db.select_column::<T, V>()),
#[cfg(feature = "mssql")]
Database::MSSQL(db) => GroupedSelectExecutor::MSSQL(db.select_column::<T, V>()),
}
}
pub fn delete<T: Model>(&self) -> DeleteExecutor<'_, T> {
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => {
DeleteExecutor::Sqlite(db.delete::<T>(), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => DeleteExecutor::PostgreSQL(db.delete::<T>()),
#[cfg(feature = "mysql")]
Database::MySQL(db) => DeleteExecutor::MySQL(db.delete::<T>()),
#[cfg(feature = "mssql")]
Database::MSSQL(db) => DeleteExecutor::MSSQL(db.delete::<T>()),
}
}
pub fn update<T: Model>(&self) -> UpdateExecutor<'_, T> {
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => {
UpdateExecutor::Sqlite(db.update::<T>(), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => UpdateExecutor::PostgreSQL(db.update::<T>()),
#[cfg(feature = "mysql")]
Database::MySQL(db) => UpdateExecutor::MySQL(db.update::<T>()),
#[cfg(feature = "mssql")]
Database::MSSQL(db) => UpdateExecutor::MSSQL(db.update::<T>()),
}
}
pub fn from<T: Model + 'static, R: Model>(&self) -> RelatedSelectExecutor<'_, T, R> {
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => {
RelatedSelectExecutor::Sqlite(db.related::<T, R>(), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => RelatedSelectExecutor::PostgreSQL(db.related::<T, R>()),
#[cfg(feature = "mysql")]
Database::MySQL(db) => RelatedSelectExecutor::MySQL(db.related::<T, R>()),
#[cfg(feature = "mssql")]
Database::MSSQL(db) => RelatedSelectExecutor::MSSQL(db.related::<T, R>()),
}
}
pub async fn begin(&self) -> crate::Result<Transaction<'_>> {
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => {
let txn = db.begin().await?;
Ok(Transaction::Sqlite(txn))
}
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => {
let txn = db.begin().await?;
Ok(Transaction::PostgreSQL(txn))
}
#[cfg(feature = "mysql")]
Database::MySQL(db) => {
let txn = db.begin().await?;
Ok(Transaction::MySQL(txn))
}
#[cfg(feature = "mssql")]
Database::MSSQL(db) => {
let txn = db.begin().await?;
Ok(Transaction::MSSQL(txn))
}
}
}
pub fn drop_table<T: Model>(&self) -> DropTableExecutor<'_, T> {
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => DropTableExecutor::Sqlite(db.drop_table::<T>()),
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => DropTableExecutor::PostgreSQL(db.drop_table::<T>()),
#[cfg(feature = "mysql")]
Database::MySQL(db) => DropTableExecutor::MySQL(db.drop_table::<T>()),
#[cfg(feature = "mssql")]
Database::MSSQL(db) => DropTableExecutor::MSSQL(db.drop_table::<T>()),
}
}
pub fn select_sql<T>(&self, sql: impl IntoRawSql) -> RawSelectExecutor<'_, T> {
RawSelectExecutor {
db: self,
sql: sql.into_raw_sql(),
_marker: std::marker::PhantomData,
}
}
pub async fn execute_sql(&self, sql: impl IntoRawSql) -> crate::Result<u64> {
let sql = sql.into_raw_sql();
match self {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => {
let (sql, params) = sql.render(super::super::DbType::Sqlite)?;
db.exec_raw(&sql, params).await
}
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => {
let (sql, params) = sql.render(super::super::DbType::PostgreSQL)?;
db.exec_raw(&sql, params).await
}
#[cfg(feature = "mysql")]
Database::MySQL(db) => {
let (sql, params) = sql.render(super::super::DbType::MySQL)?;
db.exec_raw(&sql, params).await
}
#[cfg(feature = "mssql")]
Database::MSSQL(db) => {
let (sql, params) = sql.render(super::super::DbType::MSSQL)?;
db.exec_raw(&sql, params).await
}
}
}
pub async fn table_row_count(&self, table_name: &str) -> crate::Result<u64> {
let sql = format!(
"SELECT COUNT(*) FROM {}",
quote_table_name(self.db_type(), table_name)
);
let rows = self.select_sql::<i64>(sql).collect::<Vec<i64>>().await?;
Ok(rows.into_iter().next().unwrap_or(0).max(0) as u64)
}
#[cfg(any(
feature = "sqlite",
feature = "postgresql",
feature = "mysql",
feature = "mssql"
))]
pub fn create_pool(
db_type: super::super::DbType,
connection_string: &str,
) -> super::connection_pool::PoolBuilder {
super::connection_pool::PoolBuilder::new(db_type, connection_string)
}
}
pub struct RawSelectExecutor<'a, T> {
db: &'a Database,
sql: RawSql,
_marker: std::marker::PhantomData<T>,
}
impl<'a, T> RawSelectExecutor<'a, T> {
pub fn collect<C>(self) -> RawCollectFuture<'a, T, C>
where
T: crate::model::FromRowValues + 'static,
C: FromIterator<T> + 'static,
{
RawCollectFuture {
db: self.db,
sql: self.sql,
_marker: std::marker::PhantomData,
}
}
}
pub struct RawCollectFuture<'a, T, C> {
db: &'a Database,
sql: RawSql,
_marker: std::marker::PhantomData<(T, C)>,
}
impl<'a, T, C> std::future::IntoFuture for RawCollectFuture<'a, T, C>
where
T: crate::model::FromRowValues + 'static + std::marker::Send,
C: FromIterator<T> + 'static,
{
type Output = crate::Result<C>;
type IntoFuture =
std::pin::Pin<Box<dyn std::future::Future<Output = Self::Output> + Send + 'a>>;
fn into_future(self) -> Self::IntoFuture {
Box::pin(async move {
match self.db {
#[cfg(feature = "sqlite")]
Database::Sqlite(db) => {
let (sql, params) = self.sql.render(super::super::DbType::Sqlite)?;
db.select_raw::<T, C>(&sql, params).await
}
#[cfg(feature = "postgresql")]
Database::PostgreSQL(db) => {
let (sql, params) = self.sql.render(super::super::DbType::PostgreSQL)?;
db.select_raw::<T, C>(&sql, params).await
}
#[cfg(feature = "mysql")]
Database::MySQL(db) => {
let (sql, params) = self.sql.render(super::super::DbType::MySQL)?;
db.select_raw::<T, C>(&sql, params).await
}
#[cfg(feature = "mssql")]
Database::MSSQL(db) => {
let (sql, params) = self.sql.render(super::super::DbType::MSSQL)?;
db.select_raw::<T, C>(&sql, params).await
}
}
})
}
}
pub struct TransactionRawSelectExecutor<'a, 'tx, T> {
txn: &'a mut Transaction<'tx>,
sql: RawSql,
_marker: std::marker::PhantomData<T>,
}
impl<'a, 'tx, T> TransactionRawSelectExecutor<'a, 'tx, T> {
pub fn collect<C>(self) -> TransactionRawCollectFuture<'a, 'tx, T, C>
where
T: crate::model::FromRowValues + 'static,
C: FromIterator<T> + 'static,
{
TransactionRawCollectFuture {
txn: self.txn,
sql: self.sql,
_marker: std::marker::PhantomData,
}
}
}
pub struct TransactionRawCollectFuture<'a, 'tx, T, C> {
txn: &'a mut Transaction<'tx>,
sql: RawSql,
_marker: std::marker::PhantomData<(T, C)>,
}
impl<'a, 'tx, T, C> std::future::IntoFuture for TransactionRawCollectFuture<'a, 'tx, T, C>
where
T: crate::model::FromRowValues + 'static + std::marker::Send,
C: FromIterator<T> + 'static,
{
type Output = crate::Result<C>;
type IntoFuture =
std::pin::Pin<Box<dyn std::future::Future<Output = Self::Output> + Send + 'a>>;
fn into_future(self) -> Self::IntoFuture {
Box::pin(async move {
match self.txn {
#[cfg(feature = "sqlite")]
Transaction::Sqlite(txn) => {
let (sql, params) = self.sql.render(super::super::DbType::Sqlite)?;
txn.select_raw::<T, C>(&sql, params).await
}
#[cfg(feature = "postgresql")]
Transaction::PostgreSQL(txn) => {
let (sql, params) = self.sql.render(super::super::DbType::PostgreSQL)?;
txn.select_raw::<T, C>(&sql, params).await
}
#[cfg(feature = "mysql")]
Transaction::MySQL(txn) => {
let (sql, params) = self.sql.render(super::super::DbType::MySQL)?;
txn.select_raw::<T, C>(&sql, params).await
}
#[cfg(feature = "mssql")]
Transaction::MSSQL(txn) => {
let (sql, params) = self.sql.render(super::super::DbType::MSSQL)?;
txn.select_raw::<T, C>(&sql, params).await
}
Transaction::_Phantom(_) => unreachable!(),
}
})
}
}
pub enum SelectExecutor<'a, T: Model> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::SelectExecutor<'a, T>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::SelectExecutor<'a, T>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::SelectExecutor<'a, T>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::SelectExecutor<'a, T>),
}
crate::impl_unified_select_executor_methods!(SelectExecutor);
impl<'a, T: Model> SelectExecutor<'a, T> {
pub fn include<R: Model, F>(self, f: F) -> IncludedSelectExecutor<'a, T, R>
where
F: FnOnce(T::Where) -> Relation<T, R>,
{
let where_obj = T::Where::default();
IncludedSelectExecutor {
select: self,
relation: f(where_obj),
_marker: std::marker::PhantomData,
}
}
async fn select_related<R: Model + Clone + 'static + std::marker::Send + std::marker::Sync>(
&self,
relation: &RelationInfo,
keys: Vec<Value>,
) -> crate::Result<Vec<R>> {
let values = relation_filter_values(keys);
if values.is_empty() {
return Ok(Vec::new());
}
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => {
exec.select_model::<R>()
.filter(|_| {
WhereExpr::from_filter(crate::query::filter::FilterExpr::In {
column: relation.target_key.to_string(),
values,
})
})
.collect::<Vec<R>>()
.await
}
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => {
exec.select_model::<R>()
.filter(|_| {
WhereExpr::from_filter(crate::query::filter::FilterExpr::In {
column: relation.target_key.to_string(),
values,
})
})
.collect::<Vec<R>>()
.await
}
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => {
exec.select_model::<R>()
.filter(|_| {
WhereExpr::from_filter(crate::query::filter::FilterExpr::In {
column: relation.target_key.to_string(),
values,
})
})
.collect::<Vec<R>>()
.await
}
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => {
exec.select_model::<R>()
.filter(|_| {
WhereExpr::from_filter(crate::query::filter::FilterExpr::In {
column: relation.target_key.to_string(),
values,
})
})
.collect::<Vec<R>>()
.await
}
}
}
async fn preload_models<R: Model + Clone + 'static + std::marker::Send + std::marker::Sync>(
&self,
owners: &mut [T],
relation: Relation<T, R>,
) -> crate::Result<()> {
let relation = relation.info()?;
let owner_keys = owners
.iter()
.map(|owner| owner.relation_key_value(relation))
.collect::<crate::Result<Vec<_>>>()?;
let related = self.select_related::<R>(relation, owner_keys).await?;
let mut grouped: std::collections::HashMap<String, Vec<R>> =
std::collections::HashMap::new();
for item in related {
if let Some(key) = item.column_value(relation.target_key) {
grouped.entry(model_value_key(&key)).or_default().push(item);
}
}
for owner in owners {
let key = owner.relation_key_value(relation)?;
let values = grouped
.get(&model_value_key(&key))
.cloned()
.unwrap_or_default();
owner.assign_relation(relation.name, values)?;
}
Ok(())
}
pub fn from<T2, R: Model>(self) -> RelatedSelectExecutor<'a, T, R>
where
T2: Model + 'static,
{
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => {
RelatedSelectExecutor::Sqlite(exec.from::<T2, R>(), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => {
RelatedSelectExecutor::PostgreSQL(exec.from::<T2, R>())
}
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => RelatedSelectExecutor::MySQL(exec.from::<T2, R>()),
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => RelatedSelectExecutor::MSSQL(exec.from::<T2, R>()),
}
}
pub fn from3<T2, R1: Model, R2: Model>(self) -> MultiTableSelectExecutor<'a, T, R1, R2>
where
T2: Model + 'static,
{
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => MultiTableSelectExecutor::Sqlite(
exec.from3::<T2, R1, R2>(),
std::marker::PhantomData,
),
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => {
MultiTableSelectExecutor::PostgreSQL(exec.from3::<T2, R1, R2>())
}
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => {
MultiTableSelectExecutor::MySQL(exec.from3::<T2, R1, R2>())
}
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => {
MultiTableSelectExecutor::MSSQL(exec.from3::<T2, R1, R2>())
}
}
}
pub fn from4<T2, R1: Model, R2: Model, R3: Model>(
self,
) -> FourTableSelectExecutor<'a, T, R1, R2, R3>
where
T2: Model + 'static,
{
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => FourTableSelectExecutor::Sqlite(
exec.from4::<T2, R1, R2, R3>(),
std::marker::PhantomData,
),
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => {
FourTableSelectExecutor::PostgreSQL(exec.from4::<T2, R1, R2, R3>())
}
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => {
FourTableSelectExecutor::MySQL(exec.from4::<T2, R1, R2, R3>())
}
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => {
FourTableSelectExecutor::MSSQL(exec.from4::<T2, R1, R2, R3>())
}
}
}
pub fn left_join<J: Model>(
self,
f: impl FnOnce(T::Where, J::Where) -> WhereExpr,
) -> LeftJoinedSelectExecutor<'a, T, J> {
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => {
LeftJoinedSelectExecutor::Sqlite(exec.left_join::<J>(f), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => {
LeftJoinedSelectExecutor::PostgreSQL(exec.left_join::<J>(f))
}
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => LeftJoinedSelectExecutor::MySQL(exec.left_join::<J>(f)),
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => LeftJoinedSelectExecutor::MSSQL(exec.left_join::<J>(f)),
}
}
pub fn inner_join<J: Model>(
self,
f: impl FnOnce(T::Where, J::Where) -> WhereExpr,
) -> InnerJoinedSelectExecutor<'a, T, J> {
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => {
InnerJoinedSelectExecutor::Sqlite(exec.inner_join::<J>(f), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => {
InnerJoinedSelectExecutor::PostgreSQL(exec.inner_join::<J>(f))
}
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => {
InnerJoinedSelectExecutor::MySQL(exec.inner_join::<J>(f))
}
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => {
InnerJoinedSelectExecutor::MSSQL(exec.inner_join::<J>(f))
}
}
}
pub fn right_join<J: Model>(
self,
f: impl FnOnce(T::Where, J::Where) -> WhereExpr,
) -> RightJoinedSelectExecutor<'a, T, J> {
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => {
RightJoinedSelectExecutor::Sqlite(exec.right_join::<J>(f), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => {
RightJoinedSelectExecutor::PostgreSQL(exec.right_join::<J>(f))
}
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => {
RightJoinedSelectExecutor::MySQL(exec.right_join::<J>(f))
}
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => {
RightJoinedSelectExecutor::MSSQL(exec.right_join::<J>(f))
}
}
}
pub fn collect<C: FromIterator<T> + 'static>(&self) -> CollectFuture<'a, T, C>
where
T: 'static,
{
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => CollectFuture::Sqlite(exec.clone().collect::<C>()),
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => {
CollectFuture::PostgreSQL(exec.clone_with_client().collect::<C>())
}
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => {
CollectFuture::MySQL(exec.clone_with_pool().collect::<C>())
}
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => {
CollectFuture::MSSQL(exec.clone_with_pool().collect::<C>())
}
}
}
pub fn first(self) -> FirstFuture<'a, T>
where
T: 'static,
{
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => FirstFuture::Sqlite(exec.first()),
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => FirstFuture::PostgreSQL(exec.first()),
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => FirstFuture::MySQL(exec.first()),
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => FirstFuture::MSSQL(exec.first()),
}
}
pub fn count<F, C>(self, f: F) -> AggregateFuture<'a, T, usize>
where
F: FnOnce(<T as Model>::Where) -> crate::query::builder::TypedColumn<C, T>,
{
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => {
AggregateFuture::Sqlite(exec.count(f), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => AggregateFuture::PostgreSQL(exec.count(f)),
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => AggregateFuture::MySQL(exec.count(f)),
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => AggregateFuture::MSSQL(exec.count(f)),
}
}
pub fn sum<F, C>(self, f: F) -> AggregateFuture<'a, T, C::Output>
where
F: FnOnce(<T as Model>::Where) -> crate::query::builder::TypedColumn<C, T>,
C: crate::query::builder::AggregateResultType + 'static,
{
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => {
AggregateFuture::Sqlite(exec.sum(f), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => AggregateFuture::PostgreSQL(exec.sum(f)),
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => AggregateFuture::MySQL(exec.sum(f)),
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => AggregateFuture::MSSQL(exec.sum(f)),
}
}
pub fn avg<F, C>(self, f: F) -> AggregateFuture<'a, T, Option<f64>>
where
F: FnOnce(<T as Model>::Where) -> crate::query::builder::TypedColumn<C, T>,
C: crate::query::builder::AggregateResultType + 'static,
{
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => {
AggregateFuture::Sqlite(exec.avg(f), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => AggregateFuture::PostgreSQL(exec.avg(f)),
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => AggregateFuture::MySQL(exec.avg(f)),
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => AggregateFuture::MSSQL(exec.avg(f)),
}
}
pub fn max<F, C>(self, f: F) -> AggregateFuture<'a, T, C::Output>
where
F: FnOnce(<T as Model>::Where) -> crate::query::builder::TypedColumn<C, T>,
C: crate::query::builder::AggregateResultType + 'static,
{
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => {
AggregateFuture::Sqlite(exec.max(f), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => AggregateFuture::PostgreSQL(exec.max(f)),
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => AggregateFuture::MySQL(exec.max(f)),
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => AggregateFuture::MSSQL(exec.max(f)),
}
}
pub fn min<F, C>(self, f: F) -> AggregateFuture<'a, T, C::Output>
where
F: FnOnce(<T as Model>::Where) -> crate::query::builder::TypedColumn<C, T>,
C: crate::query::builder::AggregateResultType + 'static,
{
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => {
AggregateFuture::Sqlite(exec.min(f), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => AggregateFuture::PostgreSQL(exec.min(f)),
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => AggregateFuture::MySQL(exec.min(f)),
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => AggregateFuture::MSSQL(exec.min(f)),
}
}
}
pub enum DeleteExecutor<'a, T: Model> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::DeleteExecutor<T>,
std::marker::PhantomData<&'a ()>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::DeleteExecutor<'a, T>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::DeleteExecutor<'a, T>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::DeleteExecutor<'a, T>),
}
crate::impl_unified_delete_executor!(DeleteExecutor);
pub enum UpdateExecutor<'a, T: Model> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::UpdateExecutor<T>,
std::marker::PhantomData<&'a ()>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::UpdateExecutor<'a, T>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::UpdateExecutor<'a, T>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::UpdateExecutor<'a, T>),
}
crate::impl_unified_update_executor!(UpdateExecutor);
pub enum CollectFuture<'a, T: Model, C: FromIterator<T>> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::CollectFuture<'a, T, C>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::CollectFuture<'a, T, C>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::CollectFuture<'a, T, C>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::CollectFuture<'a, T, C>),
}
pub enum FirstFuture<'a, T: Model> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::FirstFuture<'a, T>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::FirstFuture<'a, T>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::FirstFuture<'a, T>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::FirstFuture<'a, T>),
}
pub enum AggregateFuture<'a, T: Model, R> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::AggregateFuture<T, R>,
std::marker::PhantomData<&'a ()>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::AggregateFuture<'a, T, R>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::AggregateFuture<'a, T, R>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::AggregateFuture<'a, T, R>),
}
crate::impl_unified_aggregate_future!(AggregateFuture);
pub enum RelatedSelectExecutor<'a, T: Model, R: Model> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::RelatedSelectExecutor<T, R>,
std::marker::PhantomData<&'a ()>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::RelatedSelectExecutor<'a, T, R>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::RelatedSelectExecutor<'a, T, R>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::RelatedSelectExecutor<'a, T, R>),
}
pub enum MultiTableSelectExecutor<'a, T: Model, R1: Model, R2: Model> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::MultiTableSelectExecutor<T, R1, R2>,
std::marker::PhantomData<&'a ()>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::MultiTableSelectExecutor<'a, T, R1, R2>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::MultiTableSelectExecutor<'a, T, R1, R2>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::MultiTableSelectExecutor<'a, T, R1, R2>),
}
pub enum FourTableSelectExecutor<'a, T: Model, R1: Model, R2: Model, R3: Model> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::FourTableSelectExecutor<T, R1, R2, R3>,
std::marker::PhantomData<&'a ()>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::FourTableSelectExecutor<'a, T, R1, R2, R3>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::FourTableSelectExecutor<'a, T, R1, R2, R3>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::FourTableSelectExecutor<'a, T, R1, R2, R3>),
}
pub enum InnerJoinedSelectExecutor<'a, T: Model, J: Model> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::InnerJoinedSelectExecutor<T, J>,
std::marker::PhantomData<&'a ()>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::InnerJoinedSelectExecutor<'a, T, J>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::InnerJoinedSelectExecutor<'a, T, J>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::InnerJoinedSelectExecutor<'a, T, J>),
}
pub enum RightJoinedSelectExecutor<'a, T: Model, J: Model> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::RightJoinedSelectExecutor<T, J>,
std::marker::PhantomData<&'a ()>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::RightJoinedSelectExecutor<'a, T, J>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::RightJoinedSelectExecutor<'a, T, J>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::RightJoinedSelectExecutor<'a, T, J>),
}
pub enum LeftJoinedSelectExecutor<'a, T: Model, J: Model> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::LeftJoinedSelectExecutor<T, J>,
std::marker::PhantomData<&'a ()>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::LeftJoinedSelectExecutor<'a, T, J>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::LeftJoinedSelectExecutor<'a, T, J>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::LeftJoinedSelectExecutor<'a, T, J>),
}
pub enum LeftJoinCollectFuture<'a, T: Model, J: Model> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::LeftJoinCollectFuture<T, J>,
std::marker::PhantomData<&'a ()>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::LeftJoinCollectFuture<'a, T, J>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::LeftJoinCollectFuture<'a, T, J>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::LeftJoinCollectFuture<'a, T, J>),
}
pub enum InnerJoinCollectFuture<'a, T: Model, J: Model> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::InnerJoinCollectFuture<T, J>,
std::marker::PhantomData<&'a ()>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::InnerJoinCollectFuture<'a, T, J>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::InnerJoinCollectFuture<'a, T, J>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::InnerJoinCollectFuture<'a, T, J>),
}
pub enum RightJoinCollectFuture<'a, T: Model, J: Model> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::RightJoinCollectFuture<T, J>,
std::marker::PhantomData<&'a ()>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::RightJoinCollectFuture<'a, T, J>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::RightJoinCollectFuture<'a, T, J>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::RightJoinCollectFuture<'a, T, J>),
}
crate::impl_unified_collect_future!(CollectFuture);
impl<'a, T: Model + 'static + std::marker::Send + std::marker::Sync> std::future::IntoFuture
for FirstFuture<'a, T>
{
type Output = crate::Result<Option<T>>;
type IntoFuture =
std::pin::Pin<Box<dyn std::future::Future<Output = Self::Output> + Send + 'a>>;
fn into_future(self) -> Self::IntoFuture {
match self {
#[cfg(feature = "sqlite")]
FirstFuture::Sqlite(future) => Box::pin(future.into_future()),
#[cfg(feature = "postgresql")]
FirstFuture::PostgreSQL(future) => Box::pin(future.into_future()),
#[cfg(feature = "mysql")]
FirstFuture::MySQL(future) => Box::pin(future.into_future()),
#[cfg(feature = "mssql")]
FirstFuture::MSSQL(future) => Box::pin(future.into_future()),
}
}
}
crate::impl_unified_related_select_executor!(RelatedSelectExecutor);
pub enum RelatedCollectFuture<'a, T: Model, R: Model> {
#[cfg(feature = "sqlite")]
Sqlite(
sqlite_backend::RelatedCollectFuture<T, R>,
std::marker::PhantomData<&'a ()>,
),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::RelatedCollectFuture<'a, T, R>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::RelatedCollectFuture<'a, T, R>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::RelatedCollectFuture<'a, T, R>),
}
crate::impl_unified_related_collect_future!(RelatedCollectFuture);
pub enum Transaction<'a> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::Transaction),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::Transaction<'a>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::Transaction<'a>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::Transaction<'a>),
_Phantom(std::marker::PhantomData<&'a ()>),
}
pub enum TransactionInsertExecutor<'a, I: crate::model::Insertable> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::TransactionInsertExecutor<'a, I>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::TransactionInsertExecutor<'a, I>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::TransactionInsertExecutor<'a, I>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::TransactionInsertExecutor<'a, I>),
}
impl<'a, I: crate::model::Insertable + Send + Sync> TransactionInsertExecutor<'a, I> {
pub fn on_conflict<F, C>(self, f: F) -> Self
where
F: FnOnce(<I::Model as Model>::Where) -> C,
C: crate::query::insert::ConflictColumns,
{
match self {
#[cfg(feature = "sqlite")]
TransactionInsertExecutor::Sqlite(exec) => {
TransactionInsertExecutor::Sqlite(exec.on_conflict(f))
}
#[cfg(feature = "postgresql")]
TransactionInsertExecutor::PostgreSQL(exec) => {
TransactionInsertExecutor::PostgreSQL(exec.on_conflict(f))
}
#[cfg(feature = "mysql")]
TransactionInsertExecutor::MySQL(exec) => {
TransactionInsertExecutor::MySQL(exec.on_conflict(f))
}
#[cfg(feature = "mssql")]
TransactionInsertExecutor::MSSQL(exec) => {
TransactionInsertExecutor::MSSQL(exec.on_conflict(f))
}
}
}
pub fn on_constraint<Target>(self, target: Target) -> Self
where
Target: crate::query::insert::IntoInsertConflictTarget<I::Model>,
{
match self {
#[cfg(feature = "sqlite")]
TransactionInsertExecutor::Sqlite(exec) => {
TransactionInsertExecutor::Sqlite(exec.on_constraint(target))
}
#[cfg(feature = "postgresql")]
TransactionInsertExecutor::PostgreSQL(exec) => {
TransactionInsertExecutor::PostgreSQL(exec.on_constraint(target))
}
#[cfg(feature = "mysql")]
TransactionInsertExecutor::MySQL(exec) => {
TransactionInsertExecutor::MySQL(exec.on_constraint(target))
}
#[cfg(feature = "mssql")]
TransactionInsertExecutor::MSSQL(exec) => {
TransactionInsertExecutor::MSSQL(exec.on_constraint(target))
}
}
}
pub fn conflict_where<F>(self, f: F) -> Self
where
F: FnOnce(<I::Model as Model>::Where) -> WhereExpr,
{
match self {
#[cfg(feature = "sqlite")]
TransactionInsertExecutor::Sqlite(exec) => {
TransactionInsertExecutor::Sqlite(exec.conflict_where(f))
}
#[cfg(feature = "postgresql")]
TransactionInsertExecutor::PostgreSQL(exec) => {
TransactionInsertExecutor::PostgreSQL(exec.conflict_where(f))
}
#[cfg(feature = "mysql")]
TransactionInsertExecutor::MySQL(exec) => {
TransactionInsertExecutor::MySQL(exec.conflict_where(f))
}
#[cfg(feature = "mssql")]
TransactionInsertExecutor::MSSQL(exec) => {
TransactionInsertExecutor::MSSQL(exec.conflict_where(f))
}
}
}
pub fn do_nothing(self) -> Self {
match self {
#[cfg(feature = "sqlite")]
TransactionInsertExecutor::Sqlite(exec) => {
TransactionInsertExecutor::Sqlite(exec.do_nothing())
}
#[cfg(feature = "postgresql")]
TransactionInsertExecutor::PostgreSQL(exec) => {
TransactionInsertExecutor::PostgreSQL(exec.do_nothing())
}
#[cfg(feature = "mysql")]
TransactionInsertExecutor::MySQL(exec) => {
TransactionInsertExecutor::MySQL(exec.do_nothing())
}
#[cfg(feature = "mssql")]
TransactionInsertExecutor::MSSQL(exec) => {
TransactionInsertExecutor::MSSQL(exec.do_nothing())
}
}
}
pub fn do_update(self) -> Self {
match self {
#[cfg(feature = "sqlite")]
TransactionInsertExecutor::Sqlite(exec) => {
TransactionInsertExecutor::Sqlite(exec.do_update())
}
#[cfg(feature = "postgresql")]
TransactionInsertExecutor::PostgreSQL(exec) => {
TransactionInsertExecutor::PostgreSQL(exec.do_update())
}
#[cfg(feature = "mysql")]
TransactionInsertExecutor::MySQL(exec) => {
TransactionInsertExecutor::MySQL(exec.do_update())
}
#[cfg(feature = "mssql")]
TransactionInsertExecutor::MSSQL(exec) => {
TransactionInsertExecutor::MSSQL(exec.do_update())
}
}
}
pub fn do_update_if<F>(self, f: F) -> Self
where
F: FnOnce(<I::Model as Model>::Where) -> WhereExpr,
{
match self {
#[cfg(feature = "sqlite")]
TransactionInsertExecutor::Sqlite(exec) => {
TransactionInsertExecutor::Sqlite(exec.do_update_if(f))
}
#[cfg(feature = "postgresql")]
TransactionInsertExecutor::PostgreSQL(exec) => {
TransactionInsertExecutor::PostgreSQL(exec.do_update_if(f))
}
#[cfg(feature = "mysql")]
TransactionInsertExecutor::MySQL(exec) => {
TransactionInsertExecutor::MySQL(exec.do_update_if(f))
}
#[cfg(feature = "mssql")]
TransactionInsertExecutor::MSSQL(exec) => {
TransactionInsertExecutor::MSSQL(exec.do_update_if(f))
}
}
}
pub fn set<F>(self, f: F) -> Self
where
F: FnOnce(&mut <I::Model as Model>::Update),
{
match self {
#[cfg(feature = "sqlite")]
TransactionInsertExecutor::Sqlite(exec) => {
TransactionInsertExecutor::Sqlite(exec.set(f))
}
#[cfg(feature = "postgresql")]
TransactionInsertExecutor::PostgreSQL(exec) => {
TransactionInsertExecutor::PostgreSQL(exec.set(f))
}
#[cfg(feature = "mysql")]
TransactionInsertExecutor::MySQL(exec) => TransactionInsertExecutor::MySQL(exec.set(f)),
#[cfg(feature = "mssql")]
TransactionInsertExecutor::MSSQL(exec) => TransactionInsertExecutor::MSSQL(exec.set(f)),
}
}
pub fn to_sql(&self) -> crate::Result<SqlStatement> {
match self {
#[cfg(feature = "sqlite")]
TransactionInsertExecutor::Sqlite(exec) => exec.to_sql(),
#[cfg(feature = "postgresql")]
TransactionInsertExecutor::PostgreSQL(exec) => exec.to_sql(),
#[cfg(feature = "mysql")]
TransactionInsertExecutor::MySQL(exec) => exec.to_sql(),
#[cfg(feature = "mssql")]
TransactionInsertExecutor::MSSQL(exec) => exec.to_sql(),
}
}
pub async fn execute(
self,
) -> crate::Result<<I::Model as crate::model::Model>::AutoIncrementKeyType> {
match self {
#[cfg(feature = "sqlite")]
TransactionInsertExecutor::Sqlite(exec) => exec.execute().await,
#[cfg(feature = "postgresql")]
TransactionInsertExecutor::PostgreSQL(exec) => exec.execute().await,
#[cfg(feature = "mysql")]
TransactionInsertExecutor::MySQL(exec) => exec.execute().await,
#[cfg(feature = "mssql")]
TransactionInsertExecutor::MSSQL(exec) => exec.execute().await,
}
}
}
pub enum TransactionInsertOrUpdateExecutor<'a, I: crate::model::Insertable> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::TransactionInsertOrUpdateExecutor<'a, I>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::TransactionInsertOrUpdateExecutor<'a, I>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::TransactionInsertOrUpdateExecutor<'a, I>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::TransactionInsertOrUpdateExecutor<'a, I>),
}
impl<'a, I: crate::model::Insertable + Send + Sync> TransactionInsertOrUpdateExecutor<'a, I> {
pub fn to_sql(&self) -> crate::Result<SqlStatement> {
match self {
#[cfg(feature = "sqlite")]
TransactionInsertOrUpdateExecutor::Sqlite(exec) => exec.to_sql(),
#[cfg(feature = "postgresql")]
TransactionInsertOrUpdateExecutor::PostgreSQL(exec) => exec.to_sql(),
#[cfg(feature = "mysql")]
TransactionInsertOrUpdateExecutor::MySQL(exec) => exec.to_sql(),
#[cfg(feature = "mssql")]
TransactionInsertOrUpdateExecutor::MSSQL(exec) => exec.to_sql(),
}
}
pub async fn execute(self) -> crate::Result<()> {
match self {
#[cfg(feature = "sqlite")]
TransactionInsertOrUpdateExecutor::Sqlite(exec) => exec.execute().await,
#[cfg(feature = "postgresql")]
TransactionInsertOrUpdateExecutor::PostgreSQL(exec) => exec.execute().await,
#[cfg(feature = "mysql")]
TransactionInsertOrUpdateExecutor::MySQL(exec) => exec.execute().await,
#[cfg(feature = "mssql")]
TransactionInsertOrUpdateExecutor::MSSQL(exec) => exec.execute().await,
}
}
}
pub enum TransactionInsertOrIgnoreExecutor<'a, I: crate::model::Insertable> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::TransactionInsertOrIgnoreExecutor<'a, I>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::TransactionInsertOrIgnoreExecutor<'a, I>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::TransactionInsertOrIgnoreExecutor<'a, I>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::TransactionInsertOrIgnoreExecutor<'a, I>),
}
impl<'a, I: crate::model::Insertable + Send + Sync> TransactionInsertOrIgnoreExecutor<'a, I> {
pub fn to_sql(&self) -> crate::Result<SqlStatement> {
match self {
#[cfg(feature = "sqlite")]
TransactionInsertOrIgnoreExecutor::Sqlite(exec) => exec.to_sql(),
#[cfg(feature = "postgresql")]
TransactionInsertOrIgnoreExecutor::PostgreSQL(exec) => exec.to_sql(),
#[cfg(feature = "mysql")]
TransactionInsertOrIgnoreExecutor::MySQL(exec) => exec.to_sql(),
#[cfg(feature = "mssql")]
TransactionInsertOrIgnoreExecutor::MSSQL(exec) => exec.to_sql(),
}
}
pub async fn execute(self) -> crate::Result<()> {
match self {
#[cfg(feature = "sqlite")]
TransactionInsertOrIgnoreExecutor::Sqlite(exec) => exec.execute().await,
#[cfg(feature = "postgresql")]
TransactionInsertOrIgnoreExecutor::PostgreSQL(exec) => exec.execute().await,
#[cfg(feature = "mysql")]
TransactionInsertOrIgnoreExecutor::MySQL(exec) => exec.execute().await,
#[cfg(feature = "mssql")]
TransactionInsertOrIgnoreExecutor::MSSQL(exec) => exec.execute().await,
}
}
}
impl<'a> Transaction<'a> {
pub fn select_sql<T>(
&mut self,
sql: impl IntoRawSql,
) -> TransactionRawSelectExecutor<'_, 'a, T> {
TransactionRawSelectExecutor {
txn: self,
sql: sql.into_raw_sql(),
_marker: std::marker::PhantomData,
}
}
pub async fn commit(self) -> crate::Result<()> {
match self {
#[cfg(feature = "sqlite")]
Transaction::Sqlite(txn) => txn.commit().await,
#[cfg(feature = "postgresql")]
Transaction::PostgreSQL(txn) => txn.commit().await,
#[cfg(feature = "mysql")]
Transaction::MySQL(txn) => txn.commit().await,
#[cfg(feature = "mssql")]
Transaction::MSSQL(txn) => txn.commit().await,
Transaction::_Phantom(_) => unreachable!(),
}
}
pub async fn rollback(self) -> crate::Result<()> {
match self {
#[cfg(feature = "sqlite")]
Transaction::Sqlite(txn) => txn.rollback().await,
#[cfg(feature = "postgresql")]
Transaction::PostgreSQL(txn) => txn.rollback().await,
#[cfg(feature = "mysql")]
Transaction::MySQL(txn) => txn.rollback().await,
#[cfg(feature = "mssql")]
Transaction::MSSQL(txn) => txn.rollback().await,
Transaction::_Phantom(_) => unreachable!(),
}
}
pub async fn find_by_id<T: Model + 'static + std::marker::Send + std::marker::Sync>(
&self,
key: impl crate::model::PrimaryKey,
) -> crate::Result<Option<T>> {
let where_expr = primary_key_filter::<T>(key)?;
let results = self
.select::<T>()
.filter(|_| where_expr)
.range(..1)
.collect::<Vec<T>>()
.await?;
Ok(results.into_iter().next())
}
pub fn select<T: Model>(&self) -> SelectExecutor<'_, T> {
match self {
#[cfg(feature = "sqlite")]
Transaction::Sqlite(txn) => SelectExecutor::Sqlite(txn.select::<T>()),
#[cfg(feature = "postgresql")]
Transaction::PostgreSQL(txn) => SelectExecutor::PostgreSQL(txn.select::<T>()),
#[cfg(feature = "mysql")]
Transaction::MySQL(txn) => SelectExecutor::MySQL(txn.select::<T>()),
#[cfg(feature = "mssql")]
Transaction::MSSQL(txn) => SelectExecutor::MSSQL(txn.select::<T>()),
Transaction::_Phantom(_) => unreachable!(),
}
}
pub fn select_column<T: Model, V>(&self) -> GroupedSelectExecutor<'_, T, V> {
match self {
#[cfg(feature = "sqlite")]
Transaction::Sqlite(txn) => GroupedSelectExecutor::Sqlite(txn.select_column::<T, V>()),
#[cfg(feature = "postgresql")]
Transaction::PostgreSQL(txn) => {
GroupedSelectExecutor::PostgreSQL(txn.select_column::<T, V>())
}
#[cfg(feature = "mysql")]
Transaction::MySQL(txn) => GroupedSelectExecutor::MySQL(txn.select_column::<T, V>()),
#[cfg(feature = "mssql")]
Transaction::MSSQL(txn) => GroupedSelectExecutor::MSSQL(txn.select_column::<T, V>()),
Transaction::_Phantom(_) => unreachable!(),
}
}
pub fn delete<T: Model>(&self) -> DeleteExecutor<'_, T> {
match self {
#[cfg(feature = "sqlite")]
Transaction::Sqlite(txn) => {
DeleteExecutor::Sqlite(txn.delete::<T>(), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
Transaction::PostgreSQL(txn) => DeleteExecutor::PostgreSQL(txn.delete::<T>()),
#[cfg(feature = "mysql")]
Transaction::MySQL(txn) => DeleteExecutor::MySQL(txn.delete::<T>()),
#[cfg(feature = "mssql")]
Transaction::MSSQL(txn) => DeleteExecutor::MSSQL(txn.delete::<T>()),
Transaction::_Phantom(_) => unreachable!(),
}
}
pub fn update<T: Model>(&self) -> UpdateExecutor<'_, T> {
match self {
#[cfg(feature = "sqlite")]
Transaction::Sqlite(txn) => {
UpdateExecutor::Sqlite(txn.update::<T>(), std::marker::PhantomData)
}
#[cfg(feature = "postgresql")]
Transaction::PostgreSQL(txn) => UpdateExecutor::PostgreSQL(txn.update::<T>()),
#[cfg(feature = "mysql")]
Transaction::MySQL(txn) => UpdateExecutor::MySQL(txn.update::<T>()),
#[cfg(feature = "mssql")]
Transaction::MSSQL(txn) => UpdateExecutor::MSSQL(txn.update::<T>()),
Transaction::_Phantom(_) => unreachable!(),
}
}
pub fn insert<I: crate::model::Insertable>(
&mut self,
models: I,
) -> TransactionInsertExecutor<'_, I> {
match self {
#[cfg(feature = "sqlite")]
Transaction::Sqlite(txn) => TransactionInsertExecutor::Sqlite(txn.insert::<I>(models)),
#[cfg(feature = "postgresql")]
Transaction::PostgreSQL(txn) => {
TransactionInsertExecutor::PostgreSQL(txn.insert::<I>(models))
}
#[cfg(feature = "mysql")]
Transaction::MySQL(txn) => TransactionInsertExecutor::MySQL(txn.insert::<I>(models)),
#[cfg(feature = "mssql")]
Transaction::MSSQL(txn) => TransactionInsertExecutor::MSSQL(txn.insert::<I>(models)),
Transaction::_Phantom(_) => unreachable!(),
}
}
pub fn insert_or_update<I: crate::model::Insertable>(
&mut self,
models: I,
) -> TransactionInsertOrUpdateExecutor<'_, I> {
match self {
#[cfg(feature = "sqlite")]
Transaction::Sqlite(txn) => {
TransactionInsertOrUpdateExecutor::Sqlite(txn.insert_or_update::<I>(models))
}
#[cfg(feature = "postgresql")]
Transaction::PostgreSQL(txn) => {
TransactionInsertOrUpdateExecutor::PostgreSQL(txn.insert_or_update::<I>(models))
}
#[cfg(feature = "mysql")]
Transaction::MySQL(txn) => {
TransactionInsertOrUpdateExecutor::MySQL(txn.insert_or_update::<I>(models))
}
#[cfg(feature = "mssql")]
Transaction::MSSQL(txn) => {
TransactionInsertOrUpdateExecutor::MSSQL(txn.insert_or_update::<I>(models))
}
Transaction::_Phantom(_) => unreachable!(),
}
}
pub fn upsert<I: crate::model::Insertable>(
&mut self,
models: I,
) -> TransactionInsertOrUpdateExecutor<'_, I> {
self.insert_or_update(models)
}
pub fn insert_or_ignore<I: crate::model::Insertable>(
&mut self,
models: I,
) -> TransactionInsertOrIgnoreExecutor<'_, I> {
match self {
#[cfg(feature = "sqlite")]
Transaction::Sqlite(txn) => {
TransactionInsertOrIgnoreExecutor::Sqlite(txn.insert_or_ignore::<I>(models))
}
#[cfg(feature = "postgresql")]
Transaction::PostgreSQL(txn) => {
TransactionInsertOrIgnoreExecutor::PostgreSQL(txn.insert_or_ignore::<I>(models))
}
#[cfg(feature = "mysql")]
Transaction::MySQL(txn) => {
TransactionInsertOrIgnoreExecutor::MySQL(txn.insert_or_ignore::<I>(models))
}
#[cfg(feature = "mssql")]
Transaction::MSSQL(txn) => {
TransactionInsertOrIgnoreExecutor::MSSQL(txn.insert_or_ignore::<I>(models))
}
Transaction::_Phantom(_) => unreachable!(),
}
}
}
crate::impl_unified_join_executor!(LeftJoinedSelectExecutor);
impl<'a, T: Model, J: Model> LeftJoinedSelectExecutor<'a, T, J> {
pub fn collect<C: FromIterator<(T, Option<J>)> + 'static>(
&self,
) -> LeftJoinCollectFuture<'a, T, J>
where
T: 'static,
J: 'static,
{
match self {
#[cfg(feature = "sqlite")]
LeftJoinedSelectExecutor::Sqlite(exec, phantom) => {
LeftJoinCollectFuture::Sqlite(exec.clone().collect::<C>(), *phantom)
}
#[cfg(feature = "postgresql")]
LeftJoinedSelectExecutor::PostgreSQL(exec) => {
LeftJoinCollectFuture::PostgreSQL(exec.clone_with_client().collect::<C>())
}
#[cfg(feature = "mysql")]
LeftJoinedSelectExecutor::MySQL(exec) => {
LeftJoinCollectFuture::MySQL(exec.clone_with_pool().collect::<C>())
}
#[cfg(feature = "mssql")]
LeftJoinedSelectExecutor::MSSQL(exec) => {
LeftJoinCollectFuture::MSSQL(exec.clone_with_pool().collect::<C>())
}
}
}
}
crate::impl_unified_join_executor!(InnerJoinedSelectExecutor);
impl<'a, T: Model, J: Model> InnerJoinedSelectExecutor<'a, T, J> {
pub fn collect<C: FromIterator<(T, J)> + 'static>(&self) -> InnerJoinCollectFuture<'a, T, J>
where
T: 'static,
J: 'static,
{
match self {
#[cfg(feature = "sqlite")]
InnerJoinedSelectExecutor::Sqlite(exec, phantom) => {
InnerJoinCollectFuture::Sqlite(exec.clone().collect::<C>(), *phantom)
}
#[cfg(feature = "postgresql")]
InnerJoinedSelectExecutor::PostgreSQL(exec) => {
InnerJoinCollectFuture::PostgreSQL(exec.clone_with_client().collect::<C>())
}
#[cfg(feature = "mysql")]
InnerJoinedSelectExecutor::MySQL(exec) => {
InnerJoinCollectFuture::MySQL(exec.clone_with_pool().collect::<C>())
}
#[cfg(feature = "mssql")]
InnerJoinedSelectExecutor::MSSQL(exec) => {
InnerJoinCollectFuture::MSSQL(exec.clone_with_pool().collect::<C>())
}
}
}
}
crate::impl_unified_join_executor!(RightJoinedSelectExecutor);
impl<'a, T: Model, J: Model> RightJoinedSelectExecutor<'a, T, J> {
pub fn collect<C: FromIterator<(Option<T>, J)> + 'static>(
&self,
) -> RightJoinCollectFuture<'a, T, J>
where
T: 'static,
J: 'static,
{
match self {
#[cfg(feature = "sqlite")]
RightJoinedSelectExecutor::Sqlite(exec, phantom) => {
RightJoinCollectFuture::Sqlite(exec.clone().collect::<C>(), *phantom)
}
#[cfg(feature = "postgresql")]
RightJoinedSelectExecutor::PostgreSQL(exec) => {
RightJoinCollectFuture::PostgreSQL(exec.clone_with_client().collect::<C>())
}
#[cfg(feature = "mysql")]
RightJoinedSelectExecutor::MySQL(exec) => {
RightJoinCollectFuture::MySQL(exec.clone_with_pool().collect::<C>())
}
#[cfg(feature = "mssql")]
RightJoinedSelectExecutor::MSSQL(exec) => {
RightJoinCollectFuture::MSSQL(exec.clone_with_pool().collect::<C>())
}
}
}
}
crate::impl_unified_join_collect_future!(LeftJoinCollectFuture, crate::Result<Vec<(T, Option<J>)>>);
crate::impl_unified_join_collect_future!(InnerJoinCollectFuture, crate::Result<Vec<(T, J)>>);
crate::impl_unified_join_collect_future!(
RightJoinCollectFuture,
crate::Result<Vec<(Option<T>, J)>>
);
pub enum MappedSelectExecutor<'a, T: Model, V> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::MappedSelectExecutor<'a, T, V>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::MappedSelectExecutor<'a, T, V>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::MappedSelectExecutor<'a, T, V>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::MappedSelectExecutor<'a, T, V>),
}
pub enum GroupedSelectExecutor<'a, T: Model, V> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::GroupedSelectExecutor<'a, T, V>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::GroupedSelectExecutor<'a, T, V>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::GroupedSelectExecutor<'a, T, V>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::GroupedSelectExecutor<'a, T, V>),
}
impl<'a, T: Model, V> GroupedSelectExecutor<'a, T, V> {
#[allow(unused_variables)]
pub fn group_by<F, G>(self, f: F) -> Self
where
F: FnOnce(<T as Model>::Where) -> G,
G: crate::query::builder::GroupByColumns,
{
match self {
#[cfg(feature = "sqlite")]
GroupedSelectExecutor::Sqlite(exec) => GroupedSelectExecutor::Sqlite(exec.group_by(f)),
#[cfg(feature = "postgresql")]
GroupedSelectExecutor::PostgreSQL(exec) => {
GroupedSelectExecutor::PostgreSQL(exec.group_by(f))
}
#[cfg(feature = "mysql")]
GroupedSelectExecutor::MySQL(exec) => GroupedSelectExecutor::MySQL(exec.group_by(f)),
#[cfg(feature = "mssql")]
GroupedSelectExecutor::MSSQL(exec) => GroupedSelectExecutor::MSSQL(exec.group_by(f)),
}
}
#[allow(unused_variables)]
pub fn having<F>(self, f: F) -> Self
where
F: FnOnce(<T as Model>::Where) -> crate::query::builder::WhereExpr,
{
match self {
#[cfg(feature = "sqlite")]
GroupedSelectExecutor::Sqlite(exec) => GroupedSelectExecutor::Sqlite(exec.having(f)),
#[cfg(feature = "postgresql")]
GroupedSelectExecutor::PostgreSQL(exec) => {
GroupedSelectExecutor::PostgreSQL(exec.having(f))
}
#[cfg(feature = "mysql")]
GroupedSelectExecutor::MySQL(exec) => GroupedSelectExecutor::MySQL(exec.having(f)),
#[cfg(feature = "mssql")]
GroupedSelectExecutor::MSSQL(exec) => GroupedSelectExecutor::MSSQL(exec.having(f)),
}
}
#[allow(unused_variables)]
pub fn filter<F>(self, f: F) -> Self
where
F: FnOnce(T::Where) -> crate::query::builder::WhereExpr,
{
match self {
#[cfg(feature = "sqlite")]
GroupedSelectExecutor::Sqlite(exec) => GroupedSelectExecutor::Sqlite(exec.filter(f)),
#[cfg(feature = "postgresql")]
GroupedSelectExecutor::PostgreSQL(exec) => {
GroupedSelectExecutor::PostgreSQL(exec.filter(f))
}
#[cfg(feature = "mysql")]
GroupedSelectExecutor::MySQL(exec) => GroupedSelectExecutor::MySQL(exec.filter(f)),
#[cfg(feature = "mssql")]
GroupedSelectExecutor::MSSQL(exec) => GroupedSelectExecutor::MSSQL(exec.filter(f)),
}
}
pub fn collect<C>(&self) -> GroupedCollectFuture<'a, T, V, C>
where
T: 'static,
V: crate::model::FromRowValues + 'static,
C: FromIterator<V> + 'static,
{
match self {
#[cfg(feature = "sqlite")]
GroupedSelectExecutor::Sqlite(exec) => {
GroupedCollectFuture::Sqlite(exec.collect::<C>())
}
#[cfg(feature = "postgresql")]
GroupedSelectExecutor::PostgreSQL(exec) => {
GroupedCollectFuture::PostgreSQL(exec.collect::<C>())
}
#[cfg(feature = "mysql")]
GroupedSelectExecutor::MySQL(exec) => GroupedCollectFuture::MySQL(exec.collect::<C>()),
#[cfg(feature = "mssql")]
GroupedSelectExecutor::MSSQL(exec) => GroupedCollectFuture::MSSQL(exec.collect::<C>()),
}
}
}
impl<'a, T: Model, V> Clone for MappedSelectExecutor<'a, T, V> {
fn clone(&self) -> Self {
match self {
#[cfg(feature = "sqlite")]
MappedSelectExecutor::Sqlite(exec) => MappedSelectExecutor::Sqlite(exec.clone()),
#[cfg(feature = "postgresql")]
MappedSelectExecutor::PostgreSQL(exec) => {
MappedSelectExecutor::PostgreSQL(exec.clone_with_client())
}
#[cfg(feature = "mysql")]
MappedSelectExecutor::MySQL(exec) => {
MappedSelectExecutor::MySQL(exec.clone_with_pool())
}
#[cfg(feature = "mssql")]
MappedSelectExecutor::MSSQL(exec) => {
MappedSelectExecutor::MSSQL(exec.clone_with_pool())
}
}
}
}
pub enum MappedCollectFuture<'a, T: Model + 'static, V: 'static, C: FromIterator<V> + 'static> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::MappedCollectFuture<'a, T, V, C>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::MappedCollectFuture<'a, T, V, C>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::MappedCollectFuture<'a, T, V, C>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::MappedCollectFuture<'a, T, V, C>),
}
pub enum GroupedCollectFuture<'a, T: Model, V, C: FromIterator<V>> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::GroupedCollectFuture<'a, T, V, C>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::GroupedCollectFuture<'a, T, V, C>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::GroupedCollectFuture<'a, T, V, C>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::GroupedCollectFuture<'a, T, V, C>),
}
impl<
'a,
T: Model + 'static + std::marker::Send + std::marker::Sync,
V: crate::model::FromRowValues + 'static + std::marker::Send + std::marker::Sync,
C: FromIterator<V> + 'static,
> std::future::IntoFuture for GroupedCollectFuture<'a, T, V, C>
{
type Output = crate::Result<C>;
type IntoFuture =
std::pin::Pin<Box<dyn std::future::Future<Output = Self::Output> + Send + 'a>>;
fn into_future(self) -> Self::IntoFuture {
match self {
#[cfg(feature = "sqlite")]
GroupedCollectFuture::Sqlite(future) => Box::pin(future.into_future()),
#[cfg(feature = "postgresql")]
GroupedCollectFuture::PostgreSQL(future) => Box::pin(future.into_future()),
#[cfg(feature = "mysql")]
GroupedCollectFuture::MySQL(future) => Box::pin(future.into_future()),
#[cfg(feature = "mssql")]
GroupedCollectFuture::MSSQL(future) => Box::pin(future.into_future()),
}
}
}
pub enum ModelCollectWithFuture<'a, T: Model + 'static, V: 'static, C, M, F> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::ModelCollectWithFuture<'a, T, V, C, M, F>),
#[cfg(feature = "postgresql")]
PostgreSQLCollect(
postgresql_backend::MappedCollectFuture<'a, T, V, Vec<V>>,
F,
std::marker::PhantomData<&'a (T, C, M)>,
),
#[cfg(feature = "mysql")]
MySQLCollect(
mysql_backend::MappedCollectFuture<'a, T, V, Vec<V>>,
F,
std::marker::PhantomData<&'a (T, C, M)>,
),
#[cfg(feature = "mssql")]
MSSQLCollect(
mssql_backend::MappedCollectFuture<'a, T, V, Vec<V>>,
F,
std::marker::PhantomData<&'a (T, C, M)>,
),
}
impl<'a, T: Model> SelectExecutor<'a, T> {
#[allow(unused_variables)]
pub fn map_to<F, M>(self, f: F) -> MappedSelectExecutor<'a, T, M::Output>
where
F: FnOnce(<T as Model>::Where) -> M,
M: crate::query::builder::MapToResult,
{
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => MappedSelectExecutor::Sqlite(exec.map_to(f)),
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => MappedSelectExecutor::PostgreSQL(exec.map_to(f)),
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => MappedSelectExecutor::MySQL(exec.map_to(f)),
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => MappedSelectExecutor::MSSQL(exec.map_to(f)),
}
}
#[allow(unused_variables)]
pub fn select_column<F, V>(self, f: F) -> GroupedSelectExecutor<'a, T, V>
where
F: FnOnce(<T as Model>::Where) -> V,
V: crate::query::builder::SelectColumnResult,
{
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => GroupedSelectExecutor::Sqlite(exec.select_column(f)),
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => {
GroupedSelectExecutor::PostgreSQL(exec.select_column(f))
}
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => GroupedSelectExecutor::MySQL(exec.select_column(f)),
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => GroupedSelectExecutor::MSSQL(exec.select_column(f)),
}
}
}
pub struct IncludedSelectExecutor<'a, T: Model, R: Model> {
select: SelectExecutor<'a, T>,
relation: Relation<T, R>,
_marker: std::marker::PhantomData<R>,
}
impl<'a, T: Model, R: Model> IncludedSelectExecutor<'a, T, R> {
pub fn collect<C>(self) -> IncludedCollectFuture<'a, T, R, C>
where
T: 'static,
R: Clone + 'static,
C: FromIterator<T> + 'static,
{
IncludedCollectFuture {
select: self.select,
relation: self.relation,
_marker: std::marker::PhantomData,
}
}
}
pub struct IncludedCollectFuture<'a, T: Model, R: Model, C> {
select: SelectExecutor<'a, T>,
relation: Relation<T, R>,
_marker: std::marker::PhantomData<C>,
}
impl<
'a,
T: Model + 'static + std::marker::Send + std::marker::Sync,
R: Model + Clone + 'static + std::marker::Send + std::marker::Sync,
C: FromIterator<T> + 'static,
> std::future::IntoFuture for IncludedCollectFuture<'a, T, R, C>
{
type Output = crate::Result<C>;
type IntoFuture =
std::pin::Pin<Box<dyn std::future::Future<Output = Self::Output> + Send + 'a>>;
fn into_future(self) -> Self::IntoFuture {
Box::pin(async move {
let mut owners = self.select.collect::<Vec<T>>().await?;
self.select
.preload_models::<R>(&mut owners, self.relation)
.await?;
Ok(owners.into_iter().collect())
})
}
}
impl<'a, T: Model, V> MappedSelectExecutor<'a, T, V> {
pub fn collect<C>(self) -> MappedCollectFuture<'a, T, V, C>
where
T: 'static,
V: crate::model::FromRowValues + 'static,
C: FromIterator<V> + 'static,
{
match self {
#[cfg(feature = "sqlite")]
MappedSelectExecutor::Sqlite(exec) => MappedCollectFuture::Sqlite(exec.collect::<C>()),
#[cfg(feature = "postgresql")]
MappedSelectExecutor::PostgreSQL(exec) => {
MappedCollectFuture::PostgreSQL(exec.clone_with_client().collect::<C>())
}
#[cfg(feature = "mysql")]
MappedSelectExecutor::MySQL(exec) => {
MappedCollectFuture::MySQL(exec.clone_with_pool().collect::<C>())
}
#[cfg(feature = "mssql")]
MappedSelectExecutor::MSSQL(exec) => {
MappedCollectFuture::MSSQL(exec.clone_with_pool().collect::<C>())
}
}
}
#[allow(unused_variables)]
pub fn collect_with<C, F, M>(self, f: F) -> ModelCollectWithFuture<'a, T, V, C, M, F>
where
T: 'static,
V: crate::model::FromRowValues + 'static,
C: FromIterator<M> + 'static,
F: Fn(V) -> M + Clone + 'static,
M: 'static,
{
match self {
#[cfg(feature = "sqlite")]
MappedSelectExecutor::Sqlite(exec) => {
ModelCollectWithFuture::Sqlite(exec.collect_with::<C, F, M>(f))
}
#[cfg(feature = "postgresql")]
MappedSelectExecutor::PostgreSQL(exec) => {
let exec_clone = exec.clone_with_client();
let future = exec_clone.collect::<Vec<V>>();
ModelCollectWithFuture::PostgreSQLCollect(future, f, std::marker::PhantomData)
}
#[cfg(feature = "mysql")]
MappedSelectExecutor::MySQL(exec) => {
let exec_clone = exec.clone_with_pool();
let future = exec_clone.collect::<Vec<V>>();
ModelCollectWithFuture::MySQLCollect(future, f, std::marker::PhantomData)
}
#[cfg(feature = "mssql")]
MappedSelectExecutor::MSSQL(exec) => {
let exec_clone = exec.clone_with_pool();
let future = exec_clone.collect::<Vec<V>>();
ModelCollectWithFuture::MSSQLCollect(future, f, std::marker::PhantomData)
}
}
}
}
impl<'a, T: Model, V> crate::query::filter::Subquery for MappedSelectExecutor<'a, T, V> {
fn to_subquery_sql(&self) -> (String, Vec<crate::model::Value>) {
match self {
#[cfg(feature = "sqlite")]
MappedSelectExecutor::Sqlite(exec) => exec.to_subquery_sql(),
#[cfg(feature = "postgresql")]
MappedSelectExecutor::PostgreSQL(exec) => exec.to_subquery_sql(),
#[cfg(feature = "mysql")]
MappedSelectExecutor::MySQL(exec) => exec.to_subquery_sql(),
#[cfg(feature = "mssql")]
MappedSelectExecutor::MSSQL(exec) => exec.to_subquery_sql(),
}
}
}
impl<'a, T: Model, V: crate::query::builder::ColumnValueType> crate::query::builder::IsInValues<V>
for MappedSelectExecutor<'a, T, V>
{
fn to_in_expr(self, column: String) -> crate::query::builder::WhereExpr {
use crate::query::filter::Subquery;
let (sql, params) = self.to_subquery_sql();
let filter_expr = crate::query::filter::FilterExpr::InSubquery {
column,
subquery_sql: sql,
subquery_params: params,
};
crate::query::builder::WhereExpr::from_filter(filter_expr)
}
}
impl<'a, 'b, T: Model, V: crate::query::builder::ColumnValueType>
crate::query::builder::IsInValues<V> for &'b MappedSelectExecutor<'a, T, V>
{
fn to_in_expr(self, column: String) -> crate::query::builder::WhereExpr {
use crate::query::filter::Subquery;
let (sql, params) = self.to_subquery_sql();
let filter_expr = crate::query::filter::FilterExpr::InSubquery {
column,
subquery_sql: sql,
subquery_params: params,
};
crate::query::builder::WhereExpr::from_filter(filter_expr)
}
}
impl<
'a,
T: Model + 'static + std::marker::Send + std::marker::Sync,
V: crate::model::FromRowValues + 'static + std::marker::Send + std::marker::Sync,
C: FromIterator<V> + 'static,
> std::future::IntoFuture for MappedCollectFuture<'a, T, V, C>
{
type Output = crate::Result<C>;
type IntoFuture =
std::pin::Pin<Box<dyn std::future::Future<Output = Self::Output> + Send + 'a>>;
fn into_future(self) -> Self::IntoFuture {
match self {
#[cfg(feature = "sqlite")]
MappedCollectFuture::Sqlite(future) => Box::pin(future.into_future()),
#[cfg(feature = "postgresql")]
MappedCollectFuture::PostgreSQL(future) => Box::pin(future.into_future()),
#[cfg(feature = "mysql")]
MappedCollectFuture::MySQL(future) => Box::pin(future.into_future()),
#[cfg(feature = "mssql")]
MappedCollectFuture::MSSQL(future) => Box::pin(future.into_future()),
}
}
}
impl<'a, T, V, C, M, F> std::future::IntoFuture for ModelCollectWithFuture<'a, T, V, C, M, F>
where
T: Model + 'static + std::marker::Send + std::marker::Sync,
V: crate::model::FromRowValues + 'static + std::marker::Send + std::marker::Sync,
C: FromIterator<M> + 'static,
M: 'static + std::marker::Send,
F: Fn(V) -> M + Clone + Send + 'static,
{
type Output = crate::Result<C>;
type IntoFuture =
std::pin::Pin<Box<dyn std::future::Future<Output = Self::Output> + Send + 'a>>;
fn into_future(self) -> Self::IntoFuture {
match self {
#[cfg(feature = "sqlite")]
ModelCollectWithFuture::Sqlite(future) => Box::pin(future.into_future()),
#[cfg(feature = "postgresql")]
ModelCollectWithFuture::PostgreSQLCollect(future, mapper, _) => Box::pin(async move {
let vec = future.await?;
Ok(vec.into_iter().map(mapper).collect())
}),
#[cfg(feature = "mysql")]
ModelCollectWithFuture::MySQLCollect(future, mapper, _) => Box::pin(async move {
let vec = future.await?;
Ok(vec.into_iter().map(mapper).collect())
}),
#[cfg(feature = "mssql")]
ModelCollectWithFuture::MSSQLCollect(future, mapper, _) => Box::pin(async move {
let vec = future.await?;
Ok(vec.into_iter().map(mapper).collect())
}),
}
}
}
pub enum SelectStream<'a, T: Model> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::SelectStream<'a, T>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::SelectStream<'a, T>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::SelectStream<'a, T>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::SelectStream<'a, T>),
}
impl<'a, T: Model> SelectExecutor<'a, T> {
pub fn stream(self) -> SelectStream<'a, T> {
match self {
#[cfg(feature = "sqlite")]
SelectExecutor::Sqlite(exec) => SelectStream::Sqlite(exec.stream()),
#[cfg(feature = "postgresql")]
SelectExecutor::PostgreSQL(exec) => SelectStream::PostgreSQL(exec.stream()),
#[cfg(feature = "mysql")]
SelectExecutor::MySQL(exec) => SelectStream::MySQL(exec.stream()),
#[cfg(feature = "mssql")]
SelectExecutor::MSSQL(exec) => SelectStream::MSSQL(exec.stream()),
}
}
}
pub enum SelectStreamIterator<'a, T: Model> {
#[cfg(feature = "sqlite")]
Sqlite(sqlite_backend::SelectStreamIterator<'a, T>),
#[cfg(feature = "postgresql")]
PostgreSQL(postgresql_backend::SelectStreamIterator<'a, T>),
#[cfg(feature = "mysql")]
MySQL(mysql_backend::SelectStreamIterator<'a, T>),
#[cfg(feature = "mssql")]
MSSQL(mssql_backend::SelectStreamIterator<'a, T>),
}
impl<'a, T: Model + 'static> SelectStream<'a, T> {
pub async fn into_iter(self) -> crate::Result<SelectStreamIterator<'a, T>> {
match self {
#[cfg(feature = "sqlite")]
SelectStream::Sqlite(stream) => {
let iter = stream.into_iter().await?;
Ok(SelectStreamIterator::Sqlite(iter))
}
#[cfg(feature = "postgresql")]
SelectStream::PostgreSQL(stream) => {
let iter = stream.into_iter().await?;
Ok(SelectStreamIterator::PostgreSQL(iter))
}
#[cfg(feature = "mysql")]
SelectStream::MySQL(stream) => {
let iter = stream.into_iter().await?;
Ok(SelectStreamIterator::MySQL(iter))
}
#[cfg(feature = "mssql")]
SelectStream::MSSQL(stream) => {
let iter = stream.into_iter().await?;
Ok(SelectStreamIterator::MSSQL(iter))
}
}
}
}
impl<'a, T: Model + 'static> SelectStreamIterator<'a, T> {
pub async fn next(&mut self) -> Option<crate::Result<T>> {
match self {
#[cfg(feature = "sqlite")]
SelectStreamIterator::Sqlite(iter) => iter.next().await,
#[cfg(feature = "postgresql")]
SelectStreamIterator::PostgreSQL(iter) => iter.next().await,
#[cfg(feature = "mysql")]
SelectStreamIterator::MySQL(iter) => iter.next().await,
#[cfg(feature = "mssql")]
SelectStreamIterator::MSSQL(iter) => iter.next().await,
}
}
}