linked_data_sparql/
construct_query.rs1use 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, Debug)]
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<T: ToConstructQuery>(subject: Variable, predicate: NamedNode) -> Self {
40 let object = Variable::new_unchecked(spargebra::term::BlankNode::default().into_string());
41
42 Self::new(subject, predicate, object.clone()).join(T::to_query_with_binding(object))
43 }
44
45 pub fn union_with_binding<T: ToConstructQuery>(
46 self,
47 subject: Variable,
48 predicate: NamedNode,
49 ) -> (Self, Variable) {
50 let object = Variable::new_unchecked(spargebra::term::BlankNode::default().into_string());
51
52 let construct_query = self
53 .union(Self::new(subject, predicate, object.clone()).join(T::to_query_with_binding(object.clone())));
54
55 (construct_query, object)
56 }
57
58 pub fn join_with_binding<T: ToConstructQuery>(
59 self,
60 subject: Variable,
61 predicate: NamedNode,
62 ) -> (Self, Variable) {
63 let object = Variable::new_unchecked(spargebra::term::BlankNode::default().into_string());
64
65 let construct_query = self
66 .join(Self::new(subject, predicate, object.clone()).join(T::to_query_with_binding(object.clone())));
67
68 (construct_query, object)
69 }
70
71 pub fn left_join_with_binding<T: ToConstructQuery>(
72 self,
73 subject: Variable,
74 predicate: NamedNode,
75 ) -> (Self, Variable) {
76 let object = Variable::new_unchecked(spargebra::term::BlankNode::default().into_string());
77
78 let construct_query = self.left_join(
79 Self::new(subject, predicate, object.clone()).join(T::to_query_with_binding(object.clone())),
80 );
81
82 (construct_query, object)
83 }
84
85 pub fn join_with(self, subject: Variable, predicate: NamedNode, object: NamedNode) -> Self {
86 self.join(Self::new(subject, predicate, object))
87 }
88
89 pub fn filter_variable(self, variable: Variable, id: NamedNode) -> Self {
90 let expr = Expression::Equal(
91 Box::new(Expression::Variable(variable)),
92 Box::new(Expression::NamedNode(id)),
93 );
94 Self {
95 construct_template: self.construct_template,
96 where_pattern: GraphPattern::Filter {
97 expr,
98 inner: Box::new(self.where_pattern),
99 },
100 }
101 }
102}
103
104impl From<ConstructQuery> for Query {
105 fn from(value: ConstructQuery) -> Self {
106 Query::Construct {
107 template: value.construct_template,
108 dataset: None,
109 pattern: value.where_pattern,
110 base_iri: None,
111 }
112 }
113}
114
115impl ToConstructQuery for Variable {
116 fn to_query_with_binding(_: Variable) -> ConstructQuery {
117 ConstructQuery::default()
118 }
119}
120
121macro_rules! to_construct_query_datatypes {
122 ($($t:ty),*) => {
123 $(
124 impl ToConstructQuery for $t {
125 fn to_query_with_binding(_: Variable) -> ConstructQuery {
126 ConstructQuery::default()
127 }
128 }
129 )*
130 };
131}
132
133to_construct_query_datatypes!(
134 u8,
135 u16,
136 u32,
137 u64,
138 i8,
139 i16,
140 i32,
141 i64,
142 String,
143 xsd_types::DateTime
144);
145
146impl<T: ToConstructQuery> ToConstructQuery for Option<T> {
147 fn to_query_with_binding(variable: Variable) -> ConstructQuery {
148 T::to_query_with_binding(variable)
149 }
150}
151
152impl<T: ToConstructQuery> ToConstructQuery for Vec<T> {
153 fn to_query_with_binding(variable: Variable) -> ConstructQuery {
154 T::to_query_with_binding(variable)
155 }
156}
157
158impl<T: ToConstructQuery> ToConstructQuery for std::collections::HashSet<T> {
159 fn to_query_with_binding(variable: Variable) -> ConstructQuery {
160 T::to_query_with_binding(variable)
161 }
162}
163
164impl Join for ConstructQuery {
165 fn join(mut self, other: Self) -> Self {
166 self.construct_template.extend(other.construct_template);
167 self.where_pattern = self.where_pattern.join(other.where_pattern);
168 self
169 }
170}
171
172impl LeftJoin for ConstructQuery {
173 fn left_join(mut self, other: Self) -> Self {
174 self.construct_template.extend(other.construct_template);
175 self.where_pattern = self.where_pattern.left_join(other.where_pattern);
176 self
177 }
178}
179
180impl Union for ConstructQuery {
181 fn union(mut self, other: Self) -> Self {
182 self.construct_template.extend(other.construct_template);
183 self.where_pattern = self.where_pattern.union(other.where_pattern);
184 self
185 }
186}
187
188impl And for Vec<TriplePattern> {
189 fn and(mut self, other: Self) -> Self {
190 self.extend(other);
191 self
192 }
193}
194
195impl Join for GraphPattern {
196 fn join(self, other: Self) -> Self {
197 GraphPattern::Join {
198 left: Box::new(self),
199 right: Box::new(other),
200 }
201 }
202}
203
204impl LeftJoin for GraphPattern {
205 fn left_join(self, other: Self) -> Self {
206 GraphPattern::LeftJoin {
207 left: Box::new(self),
208 right: Box::new(other),
209 expression: None,
210 }
211 }
212}
213
214impl Union for GraphPattern {
215 fn union(self, other: Self) -> Self {
216 GraphPattern::Union {
217 left: Box::new(self),
218 right: Box::new(other),
219 }
220 }
221}