vantage_vista/reference/
narrow.rs1use ciborium::Value as CborValue;
4use vantage_core::{Context, Result, VantageError, error};
5use vantage_types::Record;
6
7use super::{JoinKey, Reference};
8use crate::filter::FilterOp;
9use crate::vista::Vista;
10
11impl Reference {
12 pub fn narrow(&self, mut target: Vista, row: &Record<CborValue>) -> Result<Vista> {
26 if self.kind.is_contained() || self.keys.is_empty() {
27 return Err(error!(
28 "relation has no join keys to narrow by",
29 relation = self.name.as_str(),
30 kind = self.kind.as_str()
31 )
32 .mark_incorrect_usage());
33 }
34 for key in &self.keys {
35 self.narrow_key(&mut target, key, row)?;
36 }
37 Ok(target)
38 }
39
40 fn narrow_key(&self, target: &mut Vista, key: &JoinKey, row: &Record<CborValue>) -> Result<()> {
41 let relation = self.name.as_str();
42 let value = row
45 .get(&key.from)
46 .or_else(|| crate::eval::path_get(row, &key.from))
47 .ok_or_else(|| {
48 error!(
49 "parent row lacks the join column",
50 relation = relation,
51 column = key.from.as_str()
52 )
53 })?;
54 let column = match key.target_column(target) {
55 Ok(column) => column.to_string(),
56 Err(e) => return Err(wrap(e, relation, &key.from)),
57 };
58 target
59 .add_condition(&column, FilterOp::Eq, value.clone())
60 .map_err(|e| wrap(e, relation, &column))
61 }
62}
63
64fn wrap(err: VantageError, relation: &str, column: &str) -> VantageError {
67 let (unsupported, unimplemented) = (err.is_unsupported(), err.is_unimplemented());
68 let wrapped = Err::<(), _>(err)
69 .with_context(|| {
70 error!(
71 "can't narrow the relation's target to the parent row",
72 relation = relation,
73 column = column
74 )
75 })
76 .unwrap_err();
77 if unsupported {
78 wrapped.mark_unsupported()
79 } else if unimplemented {
80 wrapped.mark_unimplemented()
81 } else {
82 wrapped
83 }
84}