pyshacl_turbo_engine/
query_graph.rs1use oxigraph::model::*;
3use spareval::{InternalQuad, QueryableDataset};
4
5use crate::{Error, GraphRead, Result};
6
7pub struct QueryGraph<'a, G: GraphRead + ?Sized> {
12 source: &'a G,
13}
14
15impl<'a, G: GraphRead + ?Sized> QueryGraph<'a, G> {
16 fn subject(term: &Term) -> Option<NamedOrBlankNodeRef<'_>> {
17 match term {
18 Term::NamedNode(node) => Some(node.as_ref().into()),
19 Term::BlankNode(node) => Some(node.as_ref().into()),
20 _ => None,
21 }
22 }
23
24 pub fn new(source: &'a G) -> Self {
26 Self { source }
27 }
28}
29
30impl<'a, G: GraphRead + ?Sized + 'a> QueryableDataset<'a> for QueryGraph<'a, G> {
31 type InternalTerm = Term;
32 type Error = Error;
33
34 fn internal_quads_for_pattern(
35 &self,
36 subject: Option<&Term>,
37 predicate: Option<&Term>,
38 object: Option<&Term>,
39 graph_name: Option<Option<&Term>>,
40 ) -> impl Iterator<Item = Result<InternalQuad<Term>>> + use<'a, G> {
41 let subject = match subject {
42 Some(term) => match Self::subject(term) {
43 Some(value) => Some(value),
44 None => return Box::new(std::iter::empty()) as Box<dyn Iterator<Item = _>>,
45 },
46 None => None,
47 };
48 let predicate = match predicate {
49 Some(Term::NamedNode(node)) => Some(node.as_ref()),
50 Some(_) => return Box::new(std::iter::empty()),
51 None => None,
52 };
53 let graph = match graph_name {
54 Some(Some(term)) => match Self::subject(term) {
55 Some(value) => Some(GraphNameRef::from(value)),
56 None => return Box::new(std::iter::empty()),
57 },
58 Some(None) => Some(GraphNameRef::DefaultGraph),
59 None => None,
60 };
61 let named_only = graph_name.is_none();
64 Box::new(
65 self.source
66 .matching_quads(subject, predicate, object.map(Term::as_ref), graph)
67 .filter(move |quad| {
68 !named_only
69 || match quad {
70 Ok(q) => !q.graph_name.is_default_graph(),
71 Err(_) => true,
72 }
73 })
74 .map(|quad| {
75 quad.map(|quad| InternalQuad {
76 subject: quad.subject.into(),
77 predicate: quad.predicate.into(),
78 object: quad.object,
79 graph_name: match quad.graph_name {
80 GraphName::NamedNode(node) => Some(node.into()),
81 GraphName::BlankNode(node) => Some(node.into()),
82 GraphName::DefaultGraph => None,
83 },
84 })
85 }),
86 )
87 }
88
89 fn internal_named_graphs(&self) -> impl Iterator<Item = Result<Term>> + use<'a, G> {
90 self.source
91 .named_graphs()
92 .map(|graph| graph.map(Into::into))
93 }
94
95 fn contains_internal_graph_name(&self, graph: &Term) -> Result<bool> {
96 match Self::subject(graph) {
97 Some(graph) => self.source.contains_named_graph(&graph.into_owned()),
98 None => Ok(false),
99 }
100 }
101
102 fn internalize_term(&self, term: Term) -> Result<Term> {
103 Ok(term)
104 }
105
106 fn externalize_term(&self, term: Term) -> Result<Term> {
107 Ok(term)
108 }
109}