use crate::DjogiError;
use crate::context::DjogiContext;
use crate::descriptor::ModelDescriptor;
use std::future::Future;
#[doc(hidden)]
pub mod __sealed {
pub trait Sealed {}
}
pub trait Model: Sized + Send + Sync + 'static + __sealed::Sealed {
type Pk: Clone
+ Send
+ Sync
+ postgres_types::ToSql
+ for<'a> postgres_types::FromSql<'a>
+ 'static;
type Fields: Copy + Default + Send + Sync + 'static;
fn table_name() -> &'static str;
fn objects() -> crate::query::QuerySet<Self> {
crate::query::QuerySet::new()
}
fn default_filter_condition() -> Option<crate::query::internal::Condition> {
None
}
fn default_order_by() -> Vec<crate::query::OrderExpr> {
Vec::new()
}
fn pk_value(&self) -> &Self::Pk;
fn descriptor() -> &'static ModelDescriptor;
fn get(
ctx: &mut DjogiContext,
id: Self::Pk,
) -> impl Future<Output = Result<Self, DjogiError>> + Send;
fn create(
ctx: &mut DjogiContext,
value: Self,
) -> impl Future<Output = Result<Self, DjogiError>> + Send;
fn save<'ctx>(
&'ctx mut self,
ctx: &'ctx mut DjogiContext,
) -> impl Future<Output = Result<(), DjogiError>> + Send + 'ctx;
fn delete(self, ctx: &mut DjogiContext) -> impl Future<Output = Result<(), DjogiError>> + Send;
fn refresh_from_db<'ctx>(
&'ctx self,
ctx: &'ctx mut DjogiContext,
) -> impl Future<Output = Result<Self, DjogiError>> + Send + 'ctx;
fn update_returning_pair(
self,
ctx: &mut DjogiContext,
) -> impl Future<Output = Result<crate::query::ReturningPair<Self>, DjogiError>> + Send {
let _ = ctx;
async {
unreachable!("update_returning_pair: #[model] macro must emit this implementation")
}
}
fn delete_returning(
self,
ctx: &mut DjogiContext,
) -> impl Future<Output = Result<Self, DjogiError>> + Send {
let _ = ctx;
async { unreachable!("delete_returning: #[model] macro must emit this implementation") }
}
fn tree_descendants(
root_id: Self::Pk,
) -> Result<crate::query::RecursiveQuerySet<Self>, DjogiError>
where
Self::Pk: postgres_types::ToSql + Sync + Send + 'static,
{
resolve_tree_edge::<Self>().map(|edge| {
crate::query::RecursiveQuerySet::from_path(
edge,
root_id,
crate::query::RecursiveDirection::Descendants,
)
})
}
fn tree_ancestors(
node_id: Self::Pk,
) -> Result<crate::query::RecursiveQuerySet<Self>, DjogiError>
where
Self::Pk: postgres_types::ToSql + Sync + Send + 'static,
{
resolve_tree_edge::<Self>().map(|edge| {
crate::query::RecursiveQuerySet::from_path(
edge,
node_id,
crate::query::RecursiveDirection::Ancestors,
)
})
}
#[doc(hidden)]
fn __delta_should_tombstone(&self) -> bool {
false
}
#[doc(hidden)]
fn __djogi_emit_field_predicate(
acc: &mut crate::pg::accumulator::SqlAccumulator,
field: &crate::types::FieldPredicate<Self>,
ctx: crate::query::SqlEmitContext,
) -> Result<(), crate::query::PortablePredicateError> {
let _ = (acc, field, ctx);
Err(crate::query::PortablePredicateError::UnsupportedModel {
model: ::core::any::type_name::<Self>(),
})
}
#[doc(hidden)]
fn __djogi_emit_save_outbox<'ctx>(
ctx: &'ctx mut DjogiContext,
row: &'ctx Self,
) -> impl Future<Output = Result<(), DjogiError>> + Send + 'ctx {
let _ = (ctx, row);
async { Ok(()) }
}
#[doc(hidden)]
fn __djogi_emit_save_outbox_batch<'ctx>(
ctx: &'ctx mut DjogiContext,
rows: &'ctx [&'ctx Self],
) -> impl Future<Output = Result<(), DjogiError>> + Send + 'ctx {
let _ = (ctx, rows);
async { Ok(()) }
}
#[doc(hidden)]
fn __djogi_enqueue_on_save_cache_invalidation<'ctx>(
ctx: &'ctx mut DjogiContext,
row: &'ctx Self,
) -> Result<(), DjogiError> {
let _ = (ctx, row);
Ok(())
}
#[doc(hidden)]
fn __djogi_should_collect_bulk_update_ids(ctx: &DjogiContext) -> bool {
let _ = ctx;
false
}
#[doc(hidden)]
fn __djogi_enqueue_bulk_on_save_cache_invalidation(
ctx: &mut DjogiContext,
ids: Vec<Self::Pk>,
) -> Result<(), DjogiError> {
let _ = (ctx, ids);
Ok(())
}
fn full_ancestors(node_id: Self::Pk) -> crate::query::RecursiveQuerySet<Self>
where
Self::Pk: postgres_types::ToSql + Sync + Send + 'static,
{
let descriptor = Self::descriptor();
let edges: Vec<crate::relation::RelationPath<Self, Self>> = descriptor
.self_fk_columns()
.map(|col| {
crate::relation::__macro_support::__make_relation_path::<Self, Self>(
col,
Self::table_name(),
crate::relation::RelationKind::ForeignKey,
)
})
.collect();
crate::query::RecursiveQuerySet::from_paths(
edges,
node_id,
crate::query::RecursiveDirection::Ancestors,
)
}
fn materialize_closure<'ctx, C>(
ctx: &'ctx mut DjogiContext,
opts: crate::query::MaterializeClosureOptions<Self::Pk>,
) -> impl Future<Output = Result<crate::query::MaterializeClosureReport, DjogiError>> + Send + 'ctx
where
C: crate::query::ClosureModel<Source = Self> + 'ctx,
Self::Pk: postgres_types::ToSql + Sync + Send + 'static,
{
crate::query::closure::materialize_closure_impl::<Self, C>(ctx, opts)
}
}
fn resolve_tree_edge<M: Model>() -> Result<crate::relation::RelationPath<M, M>, DjogiError> {
let descriptor = M::descriptor();
let edge_name = descriptor.tree_edge.ok_or_else(|| {
DjogiError::Validation(format!(
"model '{}' has no #[model(tree_edge = \"...\")] declared; \
either add the attribute or use QuerySet::tree_descendants / \
QuerySet::tree_ancestors with an explicit RelationPath",
descriptor.type_name,
))
})?;
Ok(
crate::relation::__macro_support::__make_relation_path::<M, M>(
edge_name,
M::table_name(),
crate::relation::RelationKind::ForeignKey,
),
)
}