linked_data_sparql/
construct_query.rs

1use crate::construct_query::left_join::LeftJoin;
2use crate::to_construct_query::ToConstructQuery;
3use and::And;
4use join::Join;
5use spargebra::Query;
6use spargebra::algebra::{Expression, GraphPattern};
7use spargebra::term::{NamedNode, NamedNodePattern, TermPattern, TriplePattern, Variable};
8use union::Union;
9
10pub mod and;
11pub mod join;
12pub mod left_join;
13pub mod union;
14
15#[derive(Default)]
16pub struct ConstructQuery {
17  construct_template: Vec<TriplePattern>,
18  where_pattern: GraphPattern,
19}
20
21impl ConstructQuery {
22  pub fn new(
23    subject: impl Into<TermPattern>,
24    predicate: impl Into<NamedNodePattern>,
25    object: impl Into<TermPattern>,
26  ) -> Self {
27    let patterns = vec![TriplePattern {
28      subject: subject.into(),
29      predicate: predicate.into(),
30      object: object.into(),
31    }];
32
33    Self {
34      construct_template: patterns.clone(),
35      where_pattern: GraphPattern::Bgp { patterns },
36    }
37  }
38
39  pub fn new_with_binding<F>(
40    subject: Variable,
41    predicate: NamedNode,
42    to_query_with_binding: F,
43  ) -> Self
44  where
45    F: FnOnce(Variable) -> Self,
46  {
47    let object = Variable::new_unchecked(spargebra::term::BlankNode::default().into_string());
48
49    Self::new(subject, predicate, object.clone()).join(to_query_with_binding(object))
50  }
51
52  pub fn union_with_binding<F>(
53    self,
54    subject: Variable,
55    predicate: NamedNode,
56    to_query_with_binding: F,
57  ) -> Self
58  where
59    F: FnOnce(Variable) -> Self,
60  {
61    let object = Variable::new_unchecked(spargebra::term::BlankNode::default().into_string());
62
63    self
64      .union(Self::new(subject, predicate, object.clone()))
65      .join(to_query_with_binding(object))
66  }
67
68  pub fn join_with_binding<F>(
69    self,
70    subject: Variable,
71    predicate: NamedNode,
72    to_query_with_binding: F,
73  ) -> Self
74  where
75    F: FnOnce(Variable) -> Self,
76  {
77    let object = Variable::new_unchecked(spargebra::term::BlankNode::default().into_string());
78
79    self
80      .join(Self::new(subject, predicate, object.clone()))
81      .join(to_query_with_binding(object))
82  }
83
84  pub fn left_join_with_binding<F>(
85    self,
86    subject: Variable,
87    predicate: NamedNode,
88    to_query_with_binding: F,
89  ) -> Self
90  where
91    F: FnOnce(Variable) -> Self,
92  {
93    let object = Variable::new_unchecked(spargebra::term::BlankNode::default().into_string());
94
95    self
96      .left_join(Self::new(subject, predicate, object.clone()))
97      .join(to_query_with_binding(object))
98  }
99
100  pub fn join_with(self, subject: Variable, predicate: NamedNode, object: NamedNode) -> Self {
101    self.join(Self::new(subject, predicate, object))
102  }
103
104  pub fn filter_variable(self, variable: Variable, id: NamedNode) -> Self {
105    let expr = Expression::Equal(
106      Box::new(Expression::Variable(variable)),
107      Box::new(Expression::NamedNode(id)),
108    );
109    Self {
110      construct_template: self.construct_template,
111      where_pattern: GraphPattern::Filter {
112        expr,
113        inner: Box::new(self.where_pattern),
114      },
115    }
116  }
117}
118
119impl From<ConstructQuery> for Query {
120  fn from(value: ConstructQuery) -> Self {
121    Query::Construct {
122      template: value.construct_template,
123      dataset: None,
124      pattern: value.where_pattern,
125      base_iri: None,
126    }
127  }
128}
129
130impl ToConstructQuery for Variable {
131  fn to_query_with_binding(_: Variable) -> ConstructQuery {
132    ConstructQuery::default()
133  }
134}
135
136macro_rules! to_construct_query_datatypes {
137  ($($t:ty),*) => {
138    $(
139      impl ToConstructQuery for $t {
140        fn to_query_with_binding(_: Variable) -> ConstructQuery {
141          ConstructQuery::default()
142        }
143      }
144    )*
145  };
146}
147
148to_construct_query_datatypes!(
149  u8,
150  u16,
151  u32,
152  u64,
153  i8,
154  i16,
155  i32,
156  i64,
157  String,
158  xsd_types::DateTime
159);
160
161impl<T> ToConstructQuery for Option<T> {
162  fn to_query_with_binding(_: Variable) -> ConstructQuery {
163    ConstructQuery {
164      construct_template: vec![],
165      where_pattern: Default::default(),
166    }
167  }
168}
169
170impl<T> ToConstructQuery for Vec<T> {
171  fn to_query_with_binding(_: Variable) -> ConstructQuery {
172    ConstructQuery {
173      construct_template: vec![],
174      where_pattern: Default::default(),
175    }
176  }
177}
178
179impl<T> ToConstructQuery for std::collections::HashSet<T> {
180  fn to_query_with_binding(_: Variable) -> ConstructQuery {
181    ConstructQuery {
182      construct_template: vec![],
183      where_pattern: Default::default(),
184    }
185  }
186}
187
188impl Join for ConstructQuery {
189  fn join(mut self, other: Self) -> Self {
190    self.construct_template.extend(other.construct_template);
191    self.where_pattern = self.where_pattern.join(other.where_pattern);
192    self
193  }
194}
195
196impl LeftJoin for ConstructQuery {
197  fn left_join(mut self, other: Self) -> Self {
198    self.construct_template.extend(other.construct_template);
199    self.where_pattern = self.where_pattern.left_join(other.where_pattern);
200    self
201  }
202}
203
204impl Union for ConstructQuery {
205  fn union(mut self, other: Self) -> Self {
206    self.construct_template.extend(other.construct_template);
207    self.where_pattern = self.where_pattern.union(other.where_pattern);
208    self
209  }
210}
211
212impl And for Vec<TriplePattern> {
213  fn and(mut self, other: Self) -> Self {
214    self.extend(other);
215    self
216  }
217}
218
219impl Join for GraphPattern {
220  fn join(self, other: Self) -> Self {
221    GraphPattern::Join {
222      left: Box::new(self),
223      right: Box::new(other),
224    }
225  }
226}
227
228impl LeftJoin for GraphPattern {
229  fn left_join(self, other: Self) -> Self {
230    GraphPattern::LeftJoin {
231      left: Box::new(self),
232      right: Box::new(other),
233      expression: None,
234    }
235  }
236}
237
238impl Union for GraphPattern {
239  fn union(self, other: Self) -> Self {
240    GraphPattern::Union {
241      left: Box::new(self),
242      right: Box::new(other),
243    }
244  }
245}