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