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 label = self
78            .txn
79            .read()
80            .edge_store
81            .label
82            .get(row)
83            .cloned()
84            .ok_or(crate::GraphError::EdgeNotFound { id })?;
85        let old_props = self
86            .txn
87            .read()
88            .edge_store
89            .properties
90            .get(row)
91            .cloned()
92            .unwrap_or_default();
93        if !old_props.contains_key(&property) {
94            return Ok(());
95        }
96
97        let diff = PropertyDiff::new([], [property.clone()])?;
98        reject_immutable_edge_update(self.txn.read(), id, &diff)?;
99        let mut new_props = old_props.clone();
100        new_props.remove(&property);
101        {
102            let graph = self.txn.guard_mut();
103            graph.edge_store.properties.set(row, new_props.clone());
104            crate::property_index::apply_edge_update(
105                &mut graph.edge_property_index,
106                &label,
107                &old_props,
108                &new_props,
109                row as u32,
110            )?;
111        }
112        self.txn
113            .changes
114            .push(Change::EdgePropertyRemoved { id, property });
115        Ok(())
116    }
117
118    /// Remove a label from an alive node and emit `Change::NodeLabelRemoved`.
119    ///
120    /// The mutation is a no-op when `label` is absent.
121    pub fn remove_node_label(&mut self, id: NodeId, label: DbString) -> GraphResult<()> {
122        let row = self.require_live_node(id)?;
123        let old_labels = self
124            .txn
125            .read()
126            .node_store
127            .labels
128            .get(row)
129            .cloned()
130            .unwrap_or_default();
131        if !old_labels.contains(&label) {
132            return Ok(());
133        }
134        let props = self
135            .txn
136            .read()
137            .node_store
138            .properties
139            .get(row)
140            .cloned()
141            .unwrap_or_default();
142        let mut new_labels = old_labels.clone();
143        new_labels.remove(&label);
144        {
145            let graph = self.txn.guard_mut();
146            graph.node_store.labels.set(row, new_labels.clone());
147            remove_index_row(&mut graph.idx_label, &label, row as u32);
148            crate::property_index::apply_node_update(
149                &mut graph.property_index,
150                &old_labels,
151                &props,
152                &new_labels,
153                &props,
154                row as u32,
155            )?;
156            crate::composite_property_index::apply_node_update(
157                &mut graph.composite_property_index,
158                &old_labels,
159                &props,
160                &new_labels,
161                &props,
162                row as u32,
163            )?;
164            crate::vector_index::apply_node_update(
165                &mut graph.vector_index,
166                &old_labels,
167                &props,
168                &new_labels,
169                &props,
170                row as u32,
171            )?;
172        }
173        self.txn
174            .changes
175            .push(Change::NodeLabelRemoved { id, label });
176        Ok(())
177    }
178}