Skip to main content

lora_executor/pull/
hydration.rs

1use lora_store::GraphStorage;
2
3use crate::errors::ExecResult;
4use crate::executor::{hydrate_node_record, hydrate_relationship_record};
5use crate::value::{LoraValue, Row};
6
7use super::RowSource;
8
9/// Top-of-pipeline hydration. Replaces node / relationship id
10/// references in each emitted row with their full hydrated map form,
11/// matching the buffered executor's post-execution hydration step.
12pub(crate) struct HydratingSource<'a, S: GraphStorage> {
13    upstream: Box<dyn RowSource + 'a>,
14    storage: &'a S,
15}
16
17impl<'a, S: GraphStorage> HydratingSource<'a, S> {
18    pub(crate) fn new(upstream: Box<dyn RowSource + 'a>, storage: &'a S) -> Self {
19        Self { upstream, storage }
20    }
21}
22
23impl<'a, S: GraphStorage> RowSource for HydratingSource<'a, S> {
24    fn next_row(&mut self) -> ExecResult<Option<Row>> {
25        match self.upstream.next_row()? {
26            None => Ok(None),
27            Some(row) => {
28                let mut out = Row::new();
29                for (var, name, value) in row.into_iter_named() {
30                    out.insert_named(var, name, hydrate_value(value, self.storage));
31                }
32                Ok(Some(out))
33            }
34        }
35    }
36}
37
38/// Replace node / relationship id references in `row` with their full
39/// hydrated form (labels, type, properties), as every query result does.
40pub fn hydrate_row<S: GraphStorage>(row: Row, storage: &S) -> Row {
41    let mut out = Row::new();
42    for (var, name, value) in row.into_iter_named() {
43        out.insert_named(var, name, hydrate_value(value, storage));
44    }
45    out
46}
47
48pub(crate) fn hydrate_value<S: GraphStorage>(value: LoraValue, storage: &S) -> LoraValue {
49    match value {
50        LoraValue::Node(id) => storage
51            .with_node(id, hydrate_node_record)
52            .unwrap_or(LoraValue::Null),
53        LoraValue::Relationship(id) => storage
54            .with_relationship(id, hydrate_relationship_record)
55            .unwrap_or(LoraValue::Null),
56        LoraValue::List(values) => LoraValue::List(
57            values
58                .into_iter()
59                .map(|v| hydrate_value(v, storage))
60                .collect(),
61        ),
62        LoraValue::Map(map) => LoraValue::Map(
63            map.into_iter()
64                .map(|(k, v)| (k, hydrate_value(v, storage)))
65                .collect(),
66        ),
67        other => other,
68    }
69}