use crate::commons::{Arguments, Row};
use crate::executor::{DBSession, DbError};
use crate::interfaces::Record;
use crate::placeholders::Dialect;
use super::super::binds::statement_from_plan;
use super::super::expr::IntoExpr;
use super::super::output::{HasOutputCols, IntoOutputTarget, ReadUsing, select_assignment};
use super::super::plan::QueryPlan;
use super::super::set::{Set, SetOp};
use super::super::source::{Cte, Subquery};
use super::super::traits::Projectable;
use super::{All, First, One, Slice};
use crate::QueryError;
impl<T> All<T>
where
T: Record + 'static,
{
pub fn set<V>(mut self, target: impl IntoOutputTarget<V>, expr: impl IntoExpr<V>) -> Self
where
T: HasOutputCols,
{
self.scope
.output_assignments
.push(select_assignment(target, expr));
self
}
#[doc(hidden)]
pub fn using<F>(mut self, f: F) -> Self
where
T: HasOutputCols,
F: FnOnce(ReadUsing<T>) -> ReadUsing<T>,
{
self.scope.output_assignments = f(ReadUsing::new()).into_selects().assignments;
self
}
pub fn plan(&self, dialect: Dialect) -> Result<QueryPlan, QueryError> {
self.scope.plan_all::<T>(dialect)
}
pub fn union(self, rhs: All<T>) -> Set<T> {
Set::new(self.scope, rhs.scope, SetOp::Union)
}
pub fn union_all(self, rhs: All<T>) -> Set<T> {
Set::new(self.scope, rhs.scope, SetOp::UnionAll)
}
pub fn except(self, rhs: All<T>) -> Set<T> {
Set::new(self.scope, rhs.scope, SetOp::Except)
}
pub fn cte(self) -> Result<Cte<T>, QueryError>
where
T: Projectable + 'static,
{
self.scope.cte::<T>()
}
#[doc(hidden)]
pub fn cte_as(self, name: &str) -> Result<Cte<T>, QueryError>
where
T: Projectable + 'static,
{
self.scope.cte_as::<T>(name)
}
pub fn subquery(self) -> Result<Subquery<T>, QueryError>
where
T: Projectable + 'static,
{
self.scope.subquery::<T>()
}
#[doc(hidden)]
pub fn subquery_as(self, name: &str) -> Result<Subquery<T>, QueryError>
where
T: Projectable + 'static,
{
self.scope.subquery_as::<T>(name)
}
pub async fn exec<S>(self, session: &mut S) -> Result<Vec<T>, DbError>
where
T: for<'r> sqlx::FromRow<'r, Row> + Send + Unpin + 'static,
S: DBSession,
{
let stmt = statement_from_plan(self.plan(Dialect::active())?, Arguments::default())?;
session.fetch_all(stmt).await
}
}
impl<T> One<T>
where
T: Record + 'static,
{
pub fn set<V>(mut self, target: impl IntoOutputTarget<V>, expr: impl IntoExpr<V>) -> Self
where
T: HasOutputCols,
{
self.scope
.output_assignments
.push(select_assignment(target, expr));
self
}
#[doc(hidden)]
pub fn using<F>(mut self, f: F) -> Self
where
T: HasOutputCols,
F: FnOnce(ReadUsing<T>) -> ReadUsing<T>,
{
self.scope.output_assignments = f(ReadUsing::new()).into_selects().assignments;
self
}
pub fn plan(&self, dialect: Dialect) -> Result<QueryPlan, QueryError> {
self.scope.plan_one::<T>(dialect)
}
pub async fn exec<S>(self, session: &mut S) -> Result<T, DbError>
where
T: for<'r> sqlx::FromRow<'r, Row> + Send + Unpin + 'static,
S: DBSession,
{
let stmt = statement_from_plan(self.plan(Dialect::active())?, Arguments::default())?;
let rows = session.fetch_all(stmt).await?;
exactly_one(rows)
}
}
fn exactly_one<T>(rows: Vec<T>) -> Result<T, DbError> {
let mut rows = rows.into_iter();
let Some(row) = rows.next() else {
return Err(DbError::DoesNotExist);
};
if rows.next().is_some() {
return Err(DbError::MultipleObjects);
}
Ok(row)
}
impl<T> First<T>
where
T: Record + 'static,
{
pub fn set<V>(mut self, target: impl IntoOutputTarget<V>, expr: impl IntoExpr<V>) -> Self
where
T: HasOutputCols,
{
self.scope
.output_assignments
.push(select_assignment(target, expr));
self
}
#[doc(hidden)]
pub fn using<F>(mut self, f: F) -> Self
where
T: HasOutputCols,
F: FnOnce(ReadUsing<T>) -> ReadUsing<T>,
{
self.scope.output_assignments = f(ReadUsing::new()).into_selects().assignments;
self
}
pub fn plan(&self, dialect: Dialect) -> Result<QueryPlan, QueryError> {
self.scope.plan_first::<T>(dialect)
}
pub async fn exec<S>(self, session: &mut S) -> Result<Option<T>, DbError>
where
T: for<'r> sqlx::FromRow<'r, Row> + Send + Unpin + 'static,
S: DBSession,
{
let stmt = statement_from_plan(self.plan(Dialect::active())?, Arguments::default())?;
session.fetch_optional(stmt).await
}
}
impl<T> Slice<T>
where
T: Record + 'static,
{
pub fn set<V>(mut self, target: impl IntoOutputTarget<V>, expr: impl IntoExpr<V>) -> Self
where
T: HasOutputCols,
{
self.scope
.output_assignments
.push(select_assignment(target, expr));
self
}
#[doc(hidden)]
pub fn using<F>(mut self, f: F) -> Self
where
T: HasOutputCols,
F: FnOnce(ReadUsing<T>) -> ReadUsing<T>,
{
self.scope.output_assignments = f(ReadUsing::new()).into_selects().assignments;
self
}
pub fn plan(&self, dialect: Dialect) -> Result<QueryPlan, QueryError> {
self.scope.plan_slice::<T>(self.offset, self.count, dialect)
}
pub fn cte(self) -> Result<Cte<T>, QueryError>
where
T: Projectable + 'static,
{
self.scope.cte_as_slice::<T>(
&super::super::validate::generated_source_name::<T>("cte"),
Some((self.offset, self.count)),
)
}
pub fn subquery(self) -> Result<Subquery<T>, QueryError>
where
T: Projectable,
{
self.scope.subquery_as_slice::<T>(
&super::super::validate::generated_source_name::<T>("subquery"),
Some((self.offset, self.count)),
)
}
pub async fn exec<S>(self, session: &mut S) -> Result<Vec<T>, DbError>
where
T: for<'r> sqlx::FromRow<'r, Row> + Send + Unpin + 'static,
S: DBSession,
{
let stmt = statement_from_plan(self.plan(Dialect::active())?, Arguments::default())?;
session.fetch_all(stmt).await
}
}