Skip to main content

selene_graph/mutator/
remove.rs

1use selene_core::{Change, DbString, EdgeId, NodeId, PropertyDiff};
2
3use super::{
4    Mutator, reject_immutable_edge_update, reject_immutable_node_update, remove_index_row,
5};
6use crate::GraphResult;
7
8impl<'tx, 'g> Mutator<'tx, 'g> {
9    /// Remove a property from an alive node and emit `Change::NodePropertyRemoved`.
10    ///
11    /// The mutation is a no-op when `property` is absent.
12    pub fn remove_node_property(&mut self, id: NodeId, property: DbString) -> GraphResult<()> {
13        let row = self.require_live_node(id)?;
14        let labels = self
15            .txn
16            .read()
17            .node_store
18            .labels
19            .get(row)
20            .cloned()
21            .unwrap_or_default();
22        let old_props = self
23            .txn
24            .read()
25            .node_store
26            .properties
27            .get(row)
28            .cloned()
29            .unwrap_or_default();
30        if !old_props.contains_key(&property) {
31            return Ok(());
32        }
33
34        let diff = PropertyDiff::new([], [property.clone()])?;
35        reject_immutable_node_update(self.txn.read(), id, &labels, &diff)?;
36        let mut new_props = old_props.clone();
37        new_props.remove(&property);
38        {
39            let graph = self.txn.guard_mut();
40            graph.node_store.properties.set(row, new_props.clone());
41            crate::property_index::apply_node_update(
42                &mut graph.property_index,
43                &labels,
44                &old_props,
45                &labels,
46                &new_props,
47                row as u32,
48            )?;
49            crate::composite_property_index::apply_node_update(
50                &mut graph.composite_property_index,
51                &labels,
52                &old_props,
53                &labels,
54                &new_props,
55                row as u32,
56            )?;
57            crate::vector_index::apply_node_update(
58                &mut graph.vector_index,
59                &labels,
60                &old_props,
61                &labels,
62                &new_props,
63                row as u32,
64            )?;
65        }
66        self.txn
67            .changes
68            .push(Change::NodePropertyRemoved { id, property });
69        Ok(())
70    }
71
72    /// Remove a property from an alive edge and emit `Change::EdgePropertyRemoved`.
73    ///
74    /// The mutation is a no-op when `property` is absent.
75    pub fn remove_edge_property(&mut self, id: EdgeId, property: DbString) -> GraphResult<()> {
76        let row = self.require_live_edge(id)?;
77        let old_props = self
78            .txn
79            .read()
80            .edge_store
81            .properties
82            .get(row)
83            .cloned()
84            .unwrap_or_default();
85        if !old_props.contains_key(&property) {
86            return Ok(());
87        }
88
89        let diff = PropertyDiff::new([], [property.clone()])?;
90        reject_immutable_edge_update(self.txn.read(), id, &diff)?;
91        let mut new_props = old_props;
92        new_props.remove(&property);
93        self.txn
94            .guard_mut()
95            .edge_store
96            .properties
97            .set(row, new_props);
98        self.txn
99            .changes
100            .push(Change::EdgePropertyRemoved { id, property });
101        Ok(())
102    }
103
104    /// Remove a label from an alive node and emit `Change::NodeLabelRemoved`.
105    ///
106    /// The mutation is a no-op when `label` is absent.
107    pub fn remove_node_label(&mut self, id: NodeId, label: DbString) -> GraphResult<()> {
108        let row = self.require_live_node(id)?;
109        let old_labels = self
110            .txn
111            .read()
112            .node_store
113            .labels
114            .get(row)
115            .cloned()
116            .unwrap_or_default();
117        if !old_labels.contains(&label) {
118            return Ok(());
119        }
120        let props = self
121            .txn
122            .read()
123            .node_store
124            .properties
125            .get(row)
126            .cloned()
127            .unwrap_or_default();
128        let mut new_labels = old_labels.clone();
129        new_labels.remove(&label);
130        {
131            let graph = self.txn.guard_mut();
132            graph.node_store.labels.set(row, new_labels.clone());
133            remove_index_row(&mut graph.idx_label, &label, row as u32);
134            crate::property_index::apply_node_update(
135                &mut graph.property_index,
136                &old_labels,
137                &props,
138                &new_labels,
139                &props,
140                row as u32,
141            )?;
142            crate::composite_property_index::apply_node_update(
143                &mut graph.composite_property_index,
144                &old_labels,
145                &props,
146                &new_labels,
147                &props,
148                row as u32,
149            )?;
150            crate::vector_index::apply_node_update(
151                &mut graph.vector_index,
152                &old_labels,
153                &props,
154                &new_labels,
155                &props,
156                row as u32,
157            )?;
158        }
159        self.txn
160            .changes
161            .push(Change::NodeLabelRemoved { id, label });
162        Ok(())
163    }
164}