Skip to main content

linkrs_query/optimizer/analysis/required_properties/
map.rs

1//! Per-node requirement map produced by the required-property analysis.
2
3use std::collections::HashMap;
4
5use super::requirement::PropertyRequirement;
6
7/// Result of the required-property analysis: one requirement list per plan
8/// node id, holding the properties its consumers demand.
9#[derive(Debug, Clone, Default)]
10pub struct RequiredPropertiesMap {
11    requirements: HashMap<i64, Vec<PropertyRequirement>>,
12}
13
14impl RequiredPropertiesMap {
15    /// Record (replace) the requirement list for a node.
16    pub fn record(&mut self, node_id: i64, requirements: &[PropertyRequirement]) {
17        self.requirements.insert(node_id, requirements.to_vec());
18    }
19
20    /// All requirements recorded for a node.
21    pub fn get(&self, node_id: i64) -> Option<&[PropertyRequirement]> {
22        self.requirements.get(&node_id).map(Vec::as_slice)
23    }
24
25    /// The merged requirement for `var` at `node_id`, if any.
26    pub fn requirement_for_var(&self, node_id: i64, var: &str) -> Option<PropertyRequirement> {
27        let mut merged: Option<PropertyRequirement> = None;
28        for req in self.requirements.get(&node_id)? {
29            if req.alias == var {
30                match merged.as_mut() {
31                    Some(acc) => acc.merge(req),
32                    None => merged = Some(req.clone()),
33                }
34            }
35        }
36        merged
37    }
38
39    /// Properties safe to narrow `node_id`'s source to for `var`.
40    ///
41    /// Returns `Some(sorted props)` only when the requirement is narrowable:
42    /// the variable is not consumed in a full-value position and at least
43    /// one property is provably needed. An empty or full-value requirement
44    /// yields `None`, so callers keep the full read (empty
45    /// `projected_properties` means "read everything").
46    pub fn narrowable_properties(&self, node_id: i64, var: &str) -> Option<Vec<String>> {
47        let req = self.requirement_for_var(node_id, var)?;
48        if !req.is_narrowable() {
49            return None;
50        }
51        Some(req.prop_names.into_iter().collect())
52    }
53}