Skip to main content

vantage_table/table/base/
relations.rs

1//! The table's relations and contained relations as Vista references.
2
3use vantage_types::Entity;
4
5use super::Table;
6use crate::{references::ContainedRelation, traits::table_source::TableSource};
7
8impl<T: TableSource, E: Entity<T::Value>> Table<T, E> {
9    /// Snapshot the table's relations as Vista references (name, target,
10    /// cardinality, join key). Driver factories fold this into
11    /// `VistaMetadata` so the erased `Vista` carries enough to drive nested
12    /// insert and relation traversal.
13    ///
14    /// A reference's target is the table name of its built target, the name
15    /// a catalog resolves. Building a target is offline: no I/O runs until a
16    /// query does.
17    ///
18    /// Each relation gets one join key. A `has_many` key is fully known
19    /// here: this table's id column into the target's foreign key. A
20    /// `has_one` key constrains the target's id column, so it is
21    /// [`JoinKey::to_target_id`](vantage_vista::JoinKey::to_target_id),
22    /// resolved at traversal from the target the traversal builds.
23    pub fn vista_references(&self) -> Vec<vantage_vista::Reference> {
24        self.vista_references_keyed(&self.id_field_name())
25    }
26
27    /// [`vista_references`](Self::vista_references) with `source_id` as the
28    /// column a `has_many` reads from this table's rows. A contained record
29    /// passes its relation's id column, which may differ from the table's id
30    /// field.
31    pub(crate) fn vista_references_keyed(&self, source_id: &str) -> Vec<vantage_vista::Reference> {
32        let Some(refs) = &self.refs else {
33            return Vec::new();
34        };
35        refs.iter()
36            .map(|(name, r)| {
37                r.vista_reference(name, r.target_table_name(&self.data_source), source_id)
38            })
39            .collect()
40    }
41
42    /// The contained relations declared on this table as Vista references of
43    /// a contained kind, for driver factories to fold into `VistaMetadata`.
44    /// The records' schema is derived at traversal from each relation's
45    /// `build_target` closure.
46    pub fn vista_contained(&self) -> Vec<vantage_vista::Reference> {
47        self.contained.iter().map(|c| c.reference()).collect()
48    }
49
50    /// Look up a contained relation by name (for the driver's traversal).
51    pub fn contained_relation(&self, name: &str) -> Option<&ContainedRelation<T>> {
52        self.contained.iter().find(|c| c.name() == name)
53    }
54}