1mod triblesetconstraint;
2pub mod triblesetrangeconstraint;
3
4use triblesetconstraint::*;
5
6use crate::query::TriblePattern;
7use crate::value::Value;
8
9use crate::patch::Entry;
10use crate::patch::PATCH;
11use crate::query::Variable;
12use crate::trible::AEVOrder;
13use crate::trible::AVEOrder;
14use crate::trible::EAVOrder;
15use crate::trible::EVAOrder;
16use crate::trible::Trible;
17use crate::trible::VAEOrder;
18use crate::trible::VEAOrder;
19use crate::trible::TRIBLE_LEN;
20use crate::value::schemas::genid::GenId;
21use crate::value::ValueSchema;
22
23use std::iter::FromIterator;
24use std::iter::Map;
25use std::ops::Add;
26use std::ops::AddAssign;
27
28#[derive(Debug, Clone)]
43pub struct TribleSet {
44 pub eav: PATCH<TRIBLE_LEN, EAVOrder, ()>,
46 pub vea: PATCH<TRIBLE_LEN, VEAOrder, ()>,
48 pub ave: PATCH<TRIBLE_LEN, AVEOrder, ()>,
50 pub vae: PATCH<TRIBLE_LEN, VAEOrder, ()>,
52 pub eva: PATCH<TRIBLE_LEN, EVAOrder, ()>,
54 pub aev: PATCH<TRIBLE_LEN, AEVOrder, ()>,
56}
57
58#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
63pub struct TribleSetFingerprint(Option<u128>);
64
65impl TribleSetFingerprint {
66 pub const EMPTY: Self = Self(None);
68
69 pub fn is_empty(self) -> bool {
71 self.0.is_none()
72 }
73
74 pub fn as_u128(self) -> Option<u128> {
76 self.0
77 }
78}
79
80type TribleSetInner<'a> =
81 Map<crate::patch::PATCHIterator<'a, 64, EAVOrder, ()>, fn(&[u8; 64]) -> &Trible>;
82
83pub struct TribleSetIterator<'a> {
85 inner: TribleSetInner<'a>,
86}
87
88impl TribleSet {
89 pub fn union(&mut self, other: Self) {
93 self.eav.union(other.eav);
94 self.eva.union(other.eva);
95 self.aev.union(other.aev);
96 self.ave.union(other.ave);
97 self.vea.union(other.vea);
98 self.vae.union(other.vae);
99 }
100
101 pub fn intersect(&self, other: &Self) -> Self {
103 Self {
104 eav: self.eav.intersect(&other.eav),
105 eva: self.eva.intersect(&other.eva),
106 aev: self.aev.intersect(&other.aev),
107 ave: self.ave.intersect(&other.ave),
108 vea: self.vea.intersect(&other.vea),
109 vae: self.vae.intersect(&other.vae),
110 }
111 }
112
113 pub fn difference(&self, other: &Self) -> Self {
115 Self {
116 eav: self.eav.difference(&other.eav),
117 eva: self.eva.difference(&other.eva),
118 aev: self.aev.difference(&other.aev),
119 ave: self.ave.difference(&other.ave),
120 vea: self.vea.difference(&other.vea),
121 vae: self.vae.difference(&other.vae),
122 }
123 }
124
125 pub fn new() -> TribleSet {
127 TribleSet {
128 eav: PATCH::<TRIBLE_LEN, EAVOrder, ()>::new(),
129 eva: PATCH::<TRIBLE_LEN, EVAOrder, ()>::new(),
130 aev: PATCH::<TRIBLE_LEN, AEVOrder, ()>::new(),
131 ave: PATCH::<TRIBLE_LEN, AVEOrder, ()>::new(),
132 vea: PATCH::<TRIBLE_LEN, VEAOrder, ()>::new(),
133 vae: PATCH::<TRIBLE_LEN, VAEOrder, ()>::new(),
134 }
135 }
136
137 pub fn len(&self) -> usize {
139 self.eav.len() as usize
140 }
141
142 pub fn is_empty(&self) -> bool {
144 self.len() == 0
145 }
146
147 pub fn fingerprint(&self) -> TribleSetFingerprint {
152 TribleSetFingerprint(self.eav.root_hash())
153 }
154
155 pub fn insert(&mut self, trible: &Trible) {
157 let key = Entry::new(&trible.data);
158 self.eav.insert(&key);
159 self.eva.insert(&key);
160 self.aev.insert(&key);
161 self.ave.insert(&key);
162 self.vea.insert(&key);
163 self.vae.insert(&key);
164 }
165
166 pub fn contains(&self, trible: &Trible) -> bool {
168 self.eav.has_prefix(&trible.data)
169 }
170
171 pub fn value_in_range<V: ValueSchema>(
185 &self,
186 variable: Variable<V>,
187 min: Value<V>,
188 max: Value<V>,
189 ) -> triblesetrangeconstraint::TribleSetRangeConstraint {
190 triblesetrangeconstraint::TribleSetRangeConstraint::new(variable, min, max, self.clone())
191 }
192
193 pub fn iter(&self) -> TribleSetIterator<'_> {
195 TribleSetIterator {
196 inner: self
197 .eav
198 .iter()
199 .map(|data| Trible::as_transmute_raw_unchecked(data)),
200 }
201 }
202}
203
204impl PartialEq for TribleSet {
205 fn eq(&self, other: &Self) -> bool {
206 self.eav == other.eav
207 }
208}
209
210impl Eq for TribleSet {}
211
212impl Default for TribleSetFingerprint {
213 fn default() -> Self {
214 Self::EMPTY
215 }
216}
217
218impl From<&TribleSet> for TribleSetFingerprint {
219 fn from(set: &TribleSet) -> Self {
220 set.fingerprint()
221 }
222}
223
224impl AddAssign for TribleSet {
225 fn add_assign(&mut self, rhs: Self) {
226 self.union(rhs);
227 }
228}
229
230impl Add for TribleSet {
231 type Output = Self;
232
233 fn add(mut self, rhs: Self) -> Self::Output {
234 self.union(rhs);
235 self
236 }
237}
238
239impl FromIterator<Trible> for TribleSet {
240 fn from_iter<I: IntoIterator<Item = Trible>>(iter: I) -> Self {
241 let mut set = TribleSet::new();
242
243 for t in iter {
244 set.insert(&t);
245 }
246
247 set
248 }
249}
250
251impl TriblePattern for TribleSet {
252 type PatternConstraint<'a> = TribleSetConstraint;
253
254 fn pattern<V: ValueSchema>(
255 &self,
256 e: Variable<GenId>,
257 a: Variable<GenId>,
258 v: Variable<V>,
259 ) -> Self::PatternConstraint<'static> {
260 TribleSetConstraint::new(e, a, v, self.clone())
261 }
262}
263
264impl<'a> Iterator for TribleSetIterator<'a> {
265 type Item = &'a Trible;
266
267 fn next(&mut self) -> Option<Self::Item> {
268 self.inner.next()
269 }
270}
271
272impl<'a> IntoIterator for &'a TribleSet {
273 type Item = &'a Trible;
274 type IntoIter = TribleSetIterator<'a>;
275
276 fn into_iter(self) -> Self::IntoIter {
277 self.iter()
278 }
279}
280
281impl Default for TribleSet {
282 fn default() -> Self {
283 Self::new()
284 }
285}
286
287#[cfg(test)]
288mod tests {
289 use crate::examples::literature;
290 use crate::prelude::*;
291
292 use super::*;
293 use fake::faker::lorem::en::Words;
294 use fake::faker::name::raw::FirstName;
295 use fake::faker::name::raw::LastName;
296 use fake::locales::EN;
297 use fake::Fake;
298
299 use rayon::iter::IntoParallelIterator;
300 use rayon::iter::ParallelIterator;
301
302 #[test]
303 fn union() {
304 let mut kb = TribleSet::new();
305 for _i in 0..100 {
306 let author = ufoid();
307 let book = ufoid();
308 kb += entity! { &author @
309 literature::firstname: FirstName(EN).fake::<String>(),
310 literature::lastname: LastName(EN).fake::<String>(),
311 };
312 kb += entity! { &book @
313 literature::title: Words(1..3).fake::<Vec<String>>().join(" "),
314 literature::author: &author
315 };
316 }
317 assert_eq!(kb.len(), 400);
318 }
319
320 #[test]
321 fn union_parallel() {
322 let kb = (0..1000)
323 .into_par_iter()
324 .flat_map(|_| {
325 let author = ufoid();
326 let book = ufoid();
327 [
328 entity! { &author @
329 literature::firstname: FirstName(EN).fake::<String>(),
330 literature::lastname: LastName(EN).fake::<String>(),
331 },
332 entity! { &book @
333 literature::title: Words(1..3).fake::<Vec<String>>().join(" "),
334 literature::author: &author
335 },
336 ]
337 })
338 .reduce(Fragment::default, |a, b| a + b);
339 assert_eq!(kb.len(), 4000);
340 }
341
342 #[test]
343 fn intersection() {
344 let mut kb1 = TribleSet::new();
345 let mut kb2 = TribleSet::new();
346 for _i in 0..100 {
347 let author = ufoid();
348 let book = ufoid();
349 kb1 += entity! { &author @
350 literature::firstname: FirstName(EN).fake::<String>(),
351 literature::lastname: LastName(EN).fake::<String>(),
352 };
353 kb1 += entity! { &book @
354 literature::title: Words(1..3).fake::<Vec<String>>().join(" "),
355 literature::author: &author
356 };
357 kb2 += entity! { &author @
358 literature::firstname: FirstName(EN).fake::<String>(),
359 literature::lastname: LastName(EN).fake::<String>(),
360 };
361 kb2 += entity! { &book @
362 literature::title: Words(1..3).fake::<Vec<String>>().join(" "),
363 literature::author: &author
364 };
365 }
366 let intersection = kb1.intersect(&kb2);
367 for trible in &intersection {
369 assert!(kb1.contains(trible));
370 assert!(kb2.contains(trible));
371 }
372 }
373
374 #[test]
375 fn difference() {
376 let mut kb1 = TribleSet::new();
377 let mut kb2 = TribleSet::new();
378 for _i in 0..100 {
379 let author = ufoid();
380 let book = ufoid();
381 kb1 += entity! { &author @
382 literature::firstname: FirstName(EN).fake::<String>(),
383 literature::lastname: LastName(EN).fake::<String>(),
384 };
385 kb1 += entity! { &book @
386 literature::title: Words(1..3).fake::<Vec<String>>().join(" "),
387 literature::author: &author
388 };
389 if _i % 2 == 0 {
390 kb2 += entity! { &author @
391 literature::firstname: FirstName(EN).fake::<String>(),
392 literature::lastname: LastName(EN).fake::<String>(),
393 };
394 kb2 += entity! { &book @
395 literature::title: Words(1..3).fake::<Vec<String>>().join(" "),
396 literature::author: &author
397 };
398 }
399 }
400 let difference = kb1.difference(&kb2);
401 for trible in &difference {
403 assert!(kb1.contains(trible));
404 assert!(!kb2.contains(trible));
405 }
406 }
407
408 #[test]
409 fn test_contains() {
410 let mut kb = TribleSet::new();
411 let author = ufoid();
412 let book = ufoid();
413 let author_tribles = entity! { &author @
414 literature::firstname: FirstName(EN).fake::<String>(),
415 literature::lastname: LastName(EN).fake::<String>(),
416 };
417 let book_tribles = entity! { &book @
418 literature::title: Words(1..3).fake::<Vec<String>>().join(" "),
419 literature::author: &author
420 };
421
422 kb += author_tribles.clone();
423 kb += book_tribles.clone();
424
425 for trible in &author_tribles {
426 assert!(kb.contains(trible));
427 }
428 for trible in &book_tribles {
429 assert!(kb.contains(trible));
430 }
431
432 let non_existent_trible = entity! { &ufoid() @
433 literature::firstname: FirstName(EN).fake::<String>(),
434 literature::lastname: LastName(EN).fake::<String>(),
435 };
436
437 for trible in &non_existent_trible {
438 assert!(!kb.contains(trible));
439 }
440 }
441}