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