use crate::{
db::{
DbSession, PersistedRow,
predicate::Predicate,
query::{
api::ResponseCardinalityExt,
explain::ExplainPlan,
expr::{FilterExpr, SortExpr},
intent::{CompiledQuery, PlannedQuery, Query, QueryError},
trace::QueryTracePlan,
},
response::EntityResponse,
},
traits::{EntityKind, EntityValue, SingletonEntity},
types::Id,
};
pub struct FluentDeleteQuery<'a, E>
where
E: EntityKind,
{
session: &'a DbSession<E::Canister>,
query: Query<E>,
}
impl<'a, E> FluentDeleteQuery<'a, E>
where
E: PersistedRow,
{
pub(crate) const fn new(session: &'a DbSession<E::Canister>, query: Query<E>) -> Self {
Self { session, query }
}
#[must_use]
pub const fn query(&self) -> &Query<E> {
&self.query
}
#[must_use]
pub fn by_id(mut self, id: Id<E>) -> Self {
self.query = self.query.by_id(id.key());
self
}
#[must_use]
pub fn by_ids<I>(mut self, ids: I) -> Self
where
I: IntoIterator<Item = Id<E>>,
{
self.query = self.query.by_ids(ids.into_iter().map(|id| id.key()));
self
}
#[must_use]
pub fn filter(mut self, predicate: Predicate) -> Self {
self.query = self.query.filter(predicate);
self
}
pub fn filter_expr(mut self, expr: FilterExpr) -> Result<Self, QueryError> {
self.query = self.query.filter_expr(expr)?;
Ok(self)
}
pub fn sort_expr(mut self, expr: SortExpr) -> Result<Self, QueryError> {
self.query = self.query.sort_expr(expr)?;
Ok(self)
}
#[must_use]
pub fn order_by(mut self, field: impl AsRef<str>) -> Self {
self.query = self.query.order_by(field);
self
}
#[must_use]
pub fn order_by_desc(mut self, field: impl AsRef<str>) -> Self {
self.query = self.query.order_by_desc(field);
self
}
#[must_use]
pub fn limit(mut self, limit: u32) -> Self {
self.query = self.query.limit(limit);
self
}
pub fn explain(&self) -> Result<ExplainPlan, QueryError> {
self.query.explain()
}
pub fn plan_hash_hex(&self) -> Result<String, QueryError> {
self.query.plan_hash_hex()
}
pub fn trace(&self) -> Result<QueryTracePlan, QueryError> {
self.session.trace_query(self.query())
}
pub fn planned(&self) -> Result<PlannedQuery<E>, QueryError> {
self.query.planned()
}
pub fn plan(&self) -> Result<CompiledQuery<E>, QueryError> {
self.query.plan()
}
pub fn execute(&self) -> Result<EntityResponse<E>, QueryError>
where
E: EntityValue,
{
self.session.execute_query(self.query())
}
#[doc(hidden)]
pub fn execute_count_only(&self) -> Result<u32, QueryError>
where
E: EntityValue,
{
self.session.execute_delete_count(self.query())
}
pub fn is_empty(&self) -> Result<bool, QueryError>
where
E: EntityValue,
{
Ok(self.execute()?.is_empty())
}
pub fn count(&self) -> Result<u32, QueryError>
where
E: EntityValue,
{
Ok(self.execute()?.count())
}
pub fn require_one(&self) -> Result<(), QueryError>
where
E: EntityValue,
{
self.execute()?.require_one()?;
Ok(())
}
pub fn require_some(&self) -> Result<(), QueryError>
where
E: EntityValue,
{
self.execute()?.require_some()?;
Ok(())
}
}
impl<E> FluentDeleteQuery<'_, E>
where
E: EntityKind + SingletonEntity,
E::Key: Default,
{
#[must_use]
pub fn only(mut self) -> Self {
self.query = self.query.only();
self
}
}