1use std::collections::HashMap;
11
12use crate::update_protocol_types::{
13 ArqError, ClearType, DropType, PatternTerm, SparqlUpdate, Triple, TriplePattern, UpdateResult,
14};
15
16pub struct UpdateExecutor {
27 pub(crate) triples: Vec<Triple>,
29 pub(crate) named_graphs: HashMap<String, Vec<Triple>>,
31}
32
33impl UpdateExecutor {
34 pub fn new() -> Self {
36 Self {
37 triples: Vec::new(),
38 named_graphs: HashMap::new(),
39 }
40 }
41
42 pub fn execute(&mut self, update: &SparqlUpdate) -> Result<UpdateResult, ArqError> {
44 match update {
45 SparqlUpdate::InsertData(triples) => {
46 let count = triples.len();
47 self.triples.extend(triples.iter().cloned());
48 Ok(UpdateResult {
49 triples_inserted: count,
50 triples_deleted: 0,
51 graphs_affected: 0,
52 })
53 }
54 SparqlUpdate::DeleteData(triples) => {
55 let before = self.triples.len();
56 for t in triples {
57 self.triples.retain(|existing| existing != t);
58 }
59 let deleted = before - self.triples.len();
60 Ok(UpdateResult {
61 triples_inserted: 0,
62 triples_deleted: deleted,
63 graphs_affected: 0,
64 })
65 }
66 SparqlUpdate::InsertWhere {
67 template,
68 where_clause,
69 } => {
70 let bindings = self.match_patterns(where_clause);
71 let mut inserted = 0usize;
72 for binding in &bindings {
73 if let Some(triple) = instantiate_template_triple(template.first(), binding) {
74 for t in &triple {
75 if !self.triples.contains(t) {
76 self.triples.push(t.clone());
77 inserted += 1;
78 }
79 }
80 }
81 }
82 Ok(UpdateResult {
83 triples_inserted: inserted,
84 triples_deleted: 0,
85 graphs_affected: 0,
86 })
87 }
88 SparqlUpdate::DeleteWhere { where_clause, .. } => {
89 let bindings = self.match_patterns(where_clause);
90 let to_delete: Vec<Triple> = bindings
91 .into_iter()
92 .filter_map(|b| {
93 let s = b.get("s").cloned()?;
94 let p = b.get("p").cloned()?;
95 let o = b.get("o").cloned()?;
96 Some(Triple::new(s, p, o))
97 })
98 .collect();
99 let before = self.triples.len();
100 for t in &to_delete {
101 self.triples.retain(|e| e != t);
102 }
103 let deleted = before - self.triples.len();
104 Ok(UpdateResult {
105 triples_inserted: 0,
106 triples_deleted: deleted,
107 graphs_affected: 0,
108 })
109 }
110 SparqlUpdate::Modify {
111 delete,
112 insert,
113 where_clause,
114 } => {
115 let bindings = self.match_patterns(where_clause);
116 let mut inserted = 0usize;
117 let mut deleted_count = 0usize;
118 for binding in &bindings {
119 for tp in delete {
121 if let Some(t) = instantiate_one(tp, binding) {
122 let before = self.triples.len();
123 self.triples.retain(|e| e != &t);
124 deleted_count += before - self.triples.len();
125 }
126 }
127 for tp in insert {
129 if let Some(t) = instantiate_one(tp, binding) {
130 if !self.triples.contains(&t) {
131 self.triples.push(t);
132 inserted += 1;
133 }
134 }
135 }
136 }
137 Ok(UpdateResult {
138 triples_inserted: inserted,
139 triples_deleted: deleted_count,
140 graphs_affected: 0,
141 })
142 }
143 SparqlUpdate::CreateGraph { iri, silent } => {
144 if self.named_graphs.contains_key(iri) && !silent {
145 return Err(ArqError(format!("graph <{iri}> already exists")));
146 }
147 self.named_graphs.entry(iri.clone()).or_default();
148 Ok(UpdateResult {
149 triples_inserted: 0,
150 triples_deleted: 0,
151 graphs_affected: 1,
152 })
153 }
154 SparqlUpdate::DropGraph {
155 iri,
156 silent,
157 drop_type,
158 } => {
159 let count = match drop_type {
160 DropType::Graph => {
161 let key = iri.as_deref().unwrap_or("");
162 if self.named_graphs.remove(key).is_none() && !silent {
163 return Err(ArqError(format!("graph <{key}> does not exist")));
164 }
165 1
166 }
167 DropType::Default => {
168 self.triples.clear();
169 1
170 }
171 DropType::Named => {
172 let count = self.named_graphs.len();
173 self.named_graphs.clear();
174 count
175 }
176 DropType::All => {
177 let ng = self.named_graphs.len();
178 self.named_graphs.clear();
179 self.triples.clear();
180 ng + 1
181 }
182 };
183 Ok(UpdateResult {
184 triples_inserted: 0,
185 triples_deleted: 0,
186 graphs_affected: count,
187 })
188 }
189 SparqlUpdate::ClearGraph {
190 iri,
191 silent,
192 clear_type,
193 } => {
194 let count = match clear_type {
195 ClearType::Graph => {
196 let key = iri.as_deref().unwrap_or("");
197 match self.named_graphs.get_mut(key) {
198 Some(g) => {
199 g.clear();
200 1
201 }
202 None if *silent => 0,
203 None => return Err(ArqError(format!("graph <{key}> does not exist"))),
204 }
205 }
206 ClearType::Default => {
207 self.triples.clear();
208 1
209 }
210 ClearType::Named => {
211 for g in self.named_graphs.values_mut() {
212 g.clear();
213 }
214 self.named_graphs.len()
215 }
216 ClearType::All => {
217 self.triples.clear();
218 for g in self.named_graphs.values_mut() {
219 g.clear();
220 }
221 self.named_graphs.len() + 1
222 }
223 };
224 Ok(UpdateResult {
225 triples_inserted: 0,
226 triples_deleted: 0,
227 graphs_affected: count,
228 })
229 }
230 SparqlUpdate::CopyGraph {
231 source,
232 target,
233 silent: _,
234 } => {
235 let src_triples: Vec<Triple> =
236 self.named_graphs.get(source).cloned().unwrap_or_default();
237 let count = src_triples.len();
238 let tgt = self.named_graphs.entry(target.clone()).or_default();
239 tgt.clear();
240 tgt.extend(src_triples);
241 Ok(UpdateResult {
242 triples_inserted: count,
243 triples_deleted: 0,
244 graphs_affected: 1,
245 })
246 }
247 SparqlUpdate::MoveGraph {
248 source,
249 target,
250 silent: _,
251 } => {
252 let src_triples = self.named_graphs.remove(source).unwrap_or_default();
253 let count = src_triples.len();
254 let tgt = self.named_graphs.entry(target.clone()).or_default();
255 tgt.clear();
256 tgt.extend(src_triples);
257 Ok(UpdateResult {
258 triples_inserted: count,
259 triples_deleted: 0,
260 graphs_affected: 2,
261 })
262 }
263 SparqlUpdate::AddGraph {
264 source,
265 target,
266 silent: _,
267 } => {
268 let src_triples: Vec<Triple> =
269 self.named_graphs.get(source).cloned().unwrap_or_default();
270 let count = src_triples.len();
271 let tgt = self.named_graphs.entry(target.clone()).or_default();
272 tgt.extend(src_triples);
273 Ok(UpdateResult {
274 triples_inserted: count,
275 triples_deleted: 0,
276 graphs_affected: 1,
277 })
278 }
279 SparqlUpdate::Load { iri, into, silent } => {
280 if *silent {
283 Ok(UpdateResult::default())
284 } else {
285 Err(ArqError(format!(
286 "LOAD is not supported in the in-memory executor (iri=<{iri}>, into={into:?})"
287 )))
288 }
289 }
290 }
291 }
292
293 pub fn execute_all(&mut self, updates: &[SparqlUpdate]) -> Result<Vec<UpdateResult>, ArqError> {
295 updates.iter().map(|u| self.execute(u)).collect()
296 }
297
298 pub fn triple_count(&self) -> usize {
300 self.triples.len()
301 }
302
303 pub fn graph_count(&self) -> usize {
305 self.named_graphs.len()
306 }
307
308 pub fn get_graph(&self, iri: &str) -> Option<&Vec<Triple>> {
310 self.named_graphs.get(iri)
311 }
312
313 pub fn default_graph(&self) -> &Vec<Triple> {
315 &self.triples
316 }
317}
318
319impl Default for UpdateExecutor {
320 fn default() -> Self {
321 Self::new()
322 }
323}
324
325pub(crate) type Binding = HashMap<String, String>;
330
331fn match_patterns(triples: &[Triple], patterns: &[TriplePattern]) -> Vec<Binding> {
336 let mut results: Vec<Binding> = vec![HashMap::new()];
337
338 for pattern in patterns {
339 let mut next: Vec<Binding> = Vec::new();
340 for binding in &results {
341 for triple in triples {
342 if let Some(new_binding) = match_pattern(triple, pattern, binding) {
343 next.push(new_binding);
344 }
345 }
346 }
347 results = next;
348 }
349
350 results
351}
352
353fn match_pattern(triple: &Triple, pattern: &TriplePattern, existing: &Binding) -> Option<Binding> {
356 let mut binding = existing.clone();
357 bind_term(&triple.s, &pattern.s, &mut binding)?;
358 bind_term(&triple.p, &pattern.p, &mut binding)?;
359 bind_term(&triple.o, &pattern.o, &mut binding)?;
360 Some(binding)
361}
362
363fn bind_term(value: &str, term: &PatternTerm, binding: &mut Binding) -> Option<()> {
366 match term {
367 PatternTerm::Variable(var) => {
368 if let Some(existing) = binding.get(var.as_str()) {
369 if existing != value {
370 return None;
371 }
372 } else {
373 binding.insert(var.clone(), value.to_string());
374 }
375 Some(())
376 }
377 PatternTerm::Iri(iri) => {
378 if iri == value {
379 Some(())
380 } else {
381 None
382 }
383 }
384 PatternTerm::Literal(lit) => {
385 let inner = lit.trim_matches('"').trim_matches('\'');
387 if inner == value || lit == value {
388 Some(())
389 } else {
390 None
391 }
392 }
393 PatternTerm::BlankNode(bn) => {
394 if bn == value {
395 Some(())
396 } else {
397 None
398 }
399 }
400 }
401}
402
403impl UpdateExecutor {
404 fn match_patterns(&self, patterns: &[TriplePattern]) -> Vec<Binding> {
406 match_patterns(&self.triples, patterns)
407 }
408}
409
410fn instantiate_one(pattern: &TriplePattern, binding: &Binding) -> Option<Triple> {
413 let s = resolve_term(&pattern.s, binding)?;
414 let p = resolve_term(&pattern.p, binding)?;
415 let o = resolve_term(&pattern.o, binding)?;
416 Some(Triple::new(s, p, o))
417}
418
419fn instantiate_template_triple(
422 template: Option<&TriplePattern>,
423 binding: &Binding,
424) -> Option<Vec<Triple>> {
425 let tp = template?;
426 Some(instantiate_one(tp, binding).into_iter().collect())
427}
428
429fn resolve_term(term: &PatternTerm, binding: &Binding) -> Option<String> {
432 match term {
433 PatternTerm::Variable(var) => binding.get(var.as_str()).cloned(),
434 PatternTerm::Iri(iri) => Some(iri.clone()),
435 PatternTerm::Literal(lit) => Some(lit.trim_matches('"').trim_matches('\'').to_string()),
436 PatternTerm::BlankNode(bn) => Some(bn.clone()),
437 }
438}