1use crate::algebra::*;
2use crate::parser::{parse_query, SparqlSyntaxError};
3use crate::term::*;
4use oxiri::Iri;
5use std::fmt;
6use std::str::FromStr;
7
8#[derive(Eq, PartialEq, Debug, Clone, Hash)]
23pub enum Query {
24 Select {
26 dataset: Option<QueryDataset>,
28 pattern: GraphPattern,
30 base_iri: Option<Iri<String>>,
32 },
33 Construct {
35 template: Vec<TriplePattern>,
37 dataset: Option<QueryDataset>,
39 pattern: GraphPattern,
41 base_iri: Option<Iri<String>>,
43 },
44 Describe {
46 dataset: Option<QueryDataset>,
48 pattern: GraphPattern,
50 base_iri: Option<Iri<String>>,
52 },
53 Ask {
55 dataset: Option<QueryDataset>,
57 pattern: GraphPattern,
59 base_iri: Option<Iri<String>>,
61 },
62}
63
64impl Query {
65 pub fn parse(query: &str, base_iri: Option<&str>) -> Result<Self, SparqlSyntaxError> {
67 parse_query(query, base_iri)
68 }
69
70 #[inline]
71 pub fn dataset(&self) -> Option<&QueryDataset> {
72 match self {
73 Query::Select { dataset, .. }
74 | Query::Construct { dataset, .. }
75 | Query::Describe { dataset, .. }
76 | Query::Ask { dataset, .. } => dataset.as_ref(),
77 }
78 }
79
80 #[inline]
81 pub fn dataset_mut(&mut self) -> Option<&mut QueryDataset> {
82 match self {
83 Query::Select { dataset, .. }
84 | Query::Construct { dataset, .. }
85 | Query::Describe { dataset, .. }
86 | Query::Ask { dataset, .. } => dataset.as_mut(),
87 }
88 }
89
90 #[inline]
91 pub fn base_iri(&self) -> Option<&Iri<String>> {
92 match self {
93 Query::Select { base_iri, .. }
94 | Query::Construct { base_iri, .. }
95 | Query::Describe { base_iri, .. }
96 | Query::Ask { base_iri, .. } => base_iri.as_ref(),
97 }
98 }
99
100 pub fn to_sse(&self) -> String {
102 let mut buffer = String::new();
103 self.fmt_sse(&mut buffer).unwrap();
104 buffer
105 }
106
107 fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result {
109 match self {
110 Self::Select {
111 dataset,
112 pattern,
113 base_iri,
114 } => {
115 if let Some(base_iri) = base_iri {
116 write!(f, "(base <{base_iri}> ")?;
117 }
118 if let Some(dataset) = dataset {
119 f.write_str("(dataset ")?;
120 dataset.fmt_sse(f)?;
121 f.write_str(" ")?;
122 }
123 pattern.fmt_sse(f)?;
124 if dataset.is_some() {
125 f.write_str(")")?;
126 }
127 if base_iri.is_some() {
128 f.write_str(")")?;
129 }
130 Ok(())
131 }
132 Self::Construct {
133 template,
134 dataset,
135 pattern,
136 base_iri,
137 } => {
138 if let Some(base_iri) = base_iri {
139 write!(f, "(base <{base_iri}> ")?;
140 }
141 f.write_str("(construct (")?;
142 for (i, t) in template.iter().enumerate() {
143 if i > 0 {
144 f.write_str(" ")?;
145 }
146 t.fmt_sse(f)?;
147 }
148 f.write_str(") ")?;
149 if let Some(dataset) = dataset {
150 f.write_str("(dataset ")?;
151 dataset.fmt_sse(f)?;
152 f.write_str(" ")?;
153 }
154 pattern.fmt_sse(f)?;
155 if dataset.is_some() {
156 f.write_str(")")?;
157 }
158 f.write_str(")")?;
159 if base_iri.is_some() {
160 f.write_str(")")?;
161 }
162 Ok(())
163 }
164 Self::Describe {
165 dataset,
166 pattern,
167 base_iri,
168 } => {
169 if let Some(base_iri) = base_iri {
170 write!(f, "(base <{base_iri}> ")?;
171 }
172 f.write_str("(describe ")?;
173 if let Some(dataset) = dataset {
174 f.write_str("(dataset ")?;
175 dataset.fmt_sse(f)?;
176 f.write_str(" ")?;
177 }
178 pattern.fmt_sse(f)?;
179 if dataset.is_some() {
180 f.write_str(")")?;
181 }
182 f.write_str(")")?;
183 if base_iri.is_some() {
184 f.write_str(")")?;
185 }
186 Ok(())
187 }
188 Self::Ask {
189 dataset,
190 pattern,
191 base_iri,
192 } => {
193 if let Some(base_iri) = base_iri {
194 write!(f, "(base <{base_iri}> ")?;
195 }
196 f.write_str("(ask ")?;
197 if let Some(dataset) = dataset {
198 f.write_str("(dataset ")?;
199 dataset.fmt_sse(f)?;
200 f.write_str(" ")?;
201 }
202 pattern.fmt_sse(f)?;
203 if dataset.is_some() {
204 f.write_str(")")?;
205 }
206 f.write_str(")")?;
207 if base_iri.is_some() {
208 f.write_str(")")?;
209 }
210 Ok(())
211 }
212 }
213 }
214}
215
216impl fmt::Display for Query {
217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218 match self {
219 Self::Select {
220 dataset,
221 pattern,
222 base_iri,
223 } => {
224 if let Some(base_iri) = base_iri {
225 writeln!(f, "BASE <{base_iri}>")?;
226 }
227 write!(
228 f,
229 "{}",
230 SparqlGraphRootPattern::new(pattern, dataset.as_ref())
231 )
232 }
233 Self::Construct {
234 template,
235 dataset,
236 pattern,
237 base_iri,
238 } => {
239 if let Some(base_iri) = base_iri {
240 writeln!(f, "BASE <{base_iri}>")?;
241 }
242 f.write_str("CONSTRUCT { ")?;
243 for triple in template {
244 write!(f, "{triple} . ")?;
245 }
246 f.write_str("}")?;
247 if let Some(dataset) = dataset {
248 dataset.fmt(f)?;
249 }
250 write!(
251 f,
252 " WHERE {{ {} }}",
253 SparqlGraphRootPattern::new(pattern, None)
254 )
255 }
256 Self::Describe {
257 dataset,
258 pattern,
259 base_iri,
260 } => {
261 if let Some(base_iri) = base_iri {
262 writeln!(f, "BASE <{}>", base_iri.as_str())?;
263 }
264 f.write_str("DESCRIBE *")?;
265 if let Some(dataset) = dataset {
266 dataset.fmt(f)?;
267 }
268 write!(
269 f,
270 " WHERE {{ {} }}",
271 SparqlGraphRootPattern::new(pattern, None)
272 )
273 }
274 Self::Ask {
275 dataset,
276 pattern,
277 base_iri,
278 } => {
279 if let Some(base_iri) = base_iri {
280 writeln!(f, "BASE <{base_iri}>")?;
281 }
282 f.write_str("ASK")?;
283 if let Some(dataset) = dataset {
284 dataset.fmt(f)?;
285 }
286 write!(
287 f,
288 " WHERE {{ {} }}",
289 SparqlGraphRootPattern::new(pattern, None)
290 )
291 }
292 }
293 }
294}
295
296impl FromStr for Query {
297 type Err = SparqlSyntaxError;
298
299 fn from_str(query: &str) -> Result<Self, Self::Err> {
300 Self::parse(query, None)
301 }
302}
303
304impl TryFrom<&str> for Query {
305 type Error = SparqlSyntaxError;
306
307 fn try_from(query: &str) -> Result<Self, Self::Error> {
308 Self::from_str(query)
309 }
310}
311
312impl TryFrom<&String> for Query {
313 type Error = SparqlSyntaxError;
314
315 fn try_from(query: &String) -> Result<Self, Self::Error> {
316 Self::from_str(query)
317 }
318}