Skip to main content

cratestack_sql/values/
include.rs

1use crate::ModelDescriptor;
2
3/// Typed handle for an `.include(...)` call on a query builder. Carries
4/// everything the runtime needs to issue the side-load query for a
5/// to-one relation: a function pointer that extracts the FK value from
6/// a parent row, and a static descriptor of the related model.
7///
8/// Built by the macro-emitted `<model_module>::<relation_name>()`
9/// accessor — see the `.include(...)` builder method on `FindMany`.
10///
11/// **Scope (v1):** to-one relations only, where the related target
12/// column is the related model's primary key. Non-PK references and
13/// to-many relations are out of scope for this release; the macro
14/// silently omits accessors for non-PK references, and to-many
15/// relations stay on the existing list-side query path.
16pub struct RelationInclude<M: 'static, Rel: 'static, RelPK: 'static> {
17    /// Extracts the FK value from a parent row. `None` ⇒ the parent's
18    /// FK column is null, so there's no related row to load. Function
19    /// pointers (not closures) by design: keep the type cheap to copy
20    /// and ensure call sites can't smuggle in captures that outlive
21    /// the descriptor's `'static`.
22    pub parent_fk_extract: fn(&M) -> Option<RelPK>,
23    /// The related model's descriptor. The runtime uses this to drive
24    /// the side-load query (`SELECT projection FROM related WHERE
25    /// related.pk IN (...)`) so the related-side read policy still
26    /// applies.
27    pub related_descriptor: &'static ModelDescriptor<Rel, RelPK>,
28}
29
30impl<M, Rel, RelPK> Copy for RelationInclude<M, Rel, RelPK> {}
31impl<M, Rel, RelPK> Clone for RelationInclude<M, Rel, RelPK> {
32    fn clone(&self) -> Self {
33        *self
34    }
35}
36
37impl<M, Rel, RelPK> std::fmt::Debug for RelationInclude<M, Rel, RelPK> {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        f.debug_struct("RelationInclude")
40            .field("related_table", &self.related_descriptor.table_name)
41            .field("related_primary_key", &self.related_descriptor.primary_key)
42            .finish()
43    }
44}