1use crate::{
4 cnf::{MAX_OBJECT_PARSING_DEPTH, MAX_QUERY_PARSING_DEPTH},
5 dbs::{capabilities::ExperimentalTarget, Capabilities},
6 err::Error,
7 sql::{Block, Datetime, Duration, Idiom, Kind, Query, Range, Subquery, Thing, Value},
8};
9
10pub mod error;
11pub mod lexer;
12pub mod parser;
13pub mod token;
14
15#[cfg(test)]
16pub trait Parse<T> {
17 fn parse(val: &str) -> T;
18}
19
20#[cfg(test)]
21mod test;
22
23use lexer::{compound, Lexer};
24use parser::{Parser, ParserSettings};
25use reblessive::Stack;
26use token::t;
27
28const TARGET: &str = "surrealdb::core::syn";
29
30pub fn could_be_reserved_keyword(s: &str) -> bool {
32 lexer::keywords::could_be_reserved(s)
33}
34
35#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
46pub fn parse(input: &str) -> Result<Query, Error> {
47 let capabilities = Capabilities::all();
48 parse_with_capabilities(input, &capabilities)
49}
50
51#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
62pub fn parse_with_capabilities(input: &str, capabilities: &Capabilities) -> Result<Query, Error> {
63 trace!(target: TARGET, "Parsing SurrealQL query");
64
65 if input.len() > u32::MAX as usize {
66 return Err(Error::QueryTooLarge);
67 }
68
69 let mut parser = Parser::new_with_settings(
70 input.as_bytes(),
71 ParserSettings {
72 object_recursion_limit: *MAX_OBJECT_PARSING_DEPTH as usize,
73 query_recursion_limit: *MAX_QUERY_PARSING_DEPTH as usize,
74 references_enabled: capabilities
75 .allows_experimental(&ExperimentalTarget::RecordReferences),
76 bearer_access_enabled: capabilities
77 .allows_experimental(&ExperimentalTarget::BearerAccess),
78 define_api_enabled: capabilities.allows_experimental(&ExperimentalTarget::DefineApi),
79 ..Default::default()
80 },
81 );
82 let mut stack = Stack::new();
83 stack
84 .enter(|stk| parser.parse_query(stk))
85 .finish()
86 .map_err(|e| e.render_on(input))
87 .map_err(Error::InvalidQuery)
88}
89
90#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
92pub fn value(input: &str) -> Result<Value, Error> {
93 let capabilities = Capabilities::all();
94 value_with_capabilities(input, &capabilities)
95}
96
97#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
99pub fn value_with_capabilities(input: &str, capabilities: &Capabilities) -> Result<Value, Error> {
100 trace!(target: TARGET, "Parsing SurrealQL value");
101
102 if input.len() > u32::MAX as usize {
103 return Err(Error::QueryTooLarge);
104 }
105
106 let mut parser = Parser::new_with_settings(
107 input.as_bytes(),
108 ParserSettings {
109 object_recursion_limit: *MAX_OBJECT_PARSING_DEPTH as usize,
110 query_recursion_limit: *MAX_QUERY_PARSING_DEPTH as usize,
111 references_enabled: capabilities
112 .allows_experimental(&ExperimentalTarget::RecordReferences),
113 bearer_access_enabled: capabilities
114 .allows_experimental(&ExperimentalTarget::BearerAccess),
115 ..Default::default()
116 },
117 );
118 let mut stack = Stack::new();
119 stack
120 .enter(|stk| parser.parse_value_field(stk))
121 .finish()
122 .and_then(|e| parser.assert_finished().map(|_| e))
123 .map_err(|e| e.render_on(input))
124 .map_err(Error::InvalidQuery)
125}
126
127#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
129pub fn json(input: &str) -> Result<Value, Error> {
130 trace!(target: TARGET, "Parsing inert JSON value");
131
132 if input.len() > u32::MAX as usize {
133 return Err(Error::QueryTooLarge);
134 }
135
136 let mut parser = Parser::new_with_settings(
137 input.as_bytes(),
138 ParserSettings {
139 object_recursion_limit: *MAX_OBJECT_PARSING_DEPTH as usize,
140 query_recursion_limit: *MAX_QUERY_PARSING_DEPTH as usize,
141 ..Default::default()
142 },
143 );
144 let mut stack = Stack::new();
145 stack
146 .enter(|stk| parser.parse_json(stk))
147 .finish()
148 .and_then(|e| parser.assert_finished().map(|_| e))
149 .map_err(|e| e.render_on(input))
150 .map_err(Error::InvalidQuery)
151}
152
153#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
155pub fn subquery(input: &str) -> Result<Subquery, Error> {
156 trace!(target: TARGET, "Parsing SurrealQL subquery");
157
158 if input.len() > u32::MAX as usize {
159 return Err(Error::QueryTooLarge);
160 }
161
162 let mut parser = Parser::new_with_settings(
163 input.as_bytes(),
164 ParserSettings {
165 object_recursion_limit: *MAX_OBJECT_PARSING_DEPTH as usize,
166 query_recursion_limit: *MAX_QUERY_PARSING_DEPTH as usize,
167 ..Default::default()
168 },
169 );
170 let mut stack = Stack::new();
171 stack
172 .enter(|stk| parser.parse_full_subquery(stk))
173 .finish()
174 .and_then(|e| parser.assert_finished().map(|_| e))
175 .map_err(|e| e.render_on(input))
176 .map_err(Error::InvalidQuery)
177}
178
179#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
181pub fn idiom(input: &str) -> Result<Idiom, Error> {
182 trace!(target: TARGET, "Parsing SurrealQL idiom");
183
184 if input.len() > u32::MAX as usize {
185 return Err(Error::QueryTooLarge);
186 }
187
188 let mut parser = Parser::new_with_settings(
189 input.as_bytes(),
190 ParserSettings {
191 object_recursion_limit: *MAX_OBJECT_PARSING_DEPTH as usize,
192 query_recursion_limit: *MAX_QUERY_PARSING_DEPTH as usize,
193 ..Default::default()
194 },
195 );
196 parser.table_as_field = true;
197 let mut stack = Stack::new();
198 stack
199 .enter(|stk| parser.parse_plain_idiom(stk))
200 .finish()
201 .and_then(|e| parser.assert_finished().map(|_| e))
202 .map_err(|e| e.render_on(input))
203 .map_err(Error::InvalidQuery)
204}
205
206#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
208pub fn datetime(input: &str) -> Result<Datetime, Error> {
209 trace!(target: TARGET, "Parsing SurrealQL datetime");
210
211 if input.len() > u32::MAX as usize {
212 return Err(Error::QueryTooLarge);
213 }
214
215 let mut lexer = Lexer::new(input.as_bytes());
216 let res = compound::datetime_inner(&mut lexer);
217 if let Err(e) = lexer.assert_finished() {
218 return Err(Error::InvalidQuery(e.render_on(input)));
219 }
220 res.map(Datetime).map_err(|e| e.render_on(input)).map_err(Error::InvalidQuery)
221}
222
223#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
225pub fn duration(input: &str) -> Result<Duration, Error> {
226 trace!(target: TARGET, "Parsing SurrealQL duration");
227
228 if input.len() > u32::MAX as usize {
229 return Err(Error::QueryTooLarge);
230 }
231
232 let mut parser = Parser::new(input.as_bytes());
233 parser
234 .next_token_value::<Duration>()
235 .and_then(|e| parser.assert_finished().map(|_| e))
236 .map_err(|e| e.render_on(input))
237 .map_err(Error::InvalidQuery)
238}
239
240#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
242pub fn range(input: &str) -> Result<Range, Error> {
243 trace!(target: TARGET, "Parsing SurrealQL range");
244
245 if input.len() > u32::MAX as usize {
246 return Err(Error::QueryTooLarge);
247 }
248
249 let mut parser = Parser::new(input.as_bytes());
250 let mut stack = Stack::new();
251 stack
252 .enter(|stk| parser.parse_range(stk))
253 .finish()
254 .and_then(|e| parser.assert_finished().map(|_| e))
255 .map_err(|e| e.render_on(input))
256 .map_err(Error::InvalidQuery)
257}
258
259#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
261pub fn thing(input: &str) -> Result<Thing, Error> {
262 trace!(target: TARGET, "Parsing SurrealQL thing");
263
264 if input.len() > u32::MAX as usize {
265 return Err(Error::QueryTooLarge);
266 }
267
268 let mut parser = Parser::new_with_settings(
269 input.as_bytes(),
270 ParserSettings {
271 object_recursion_limit: *MAX_OBJECT_PARSING_DEPTH as usize,
272 query_recursion_limit: *MAX_QUERY_PARSING_DEPTH as usize,
273 ..Default::default()
274 },
275 );
276 let mut stack = Stack::new();
277 stack
278 .enter(|stk| parser.parse_thing(stk))
279 .finish()
280 .and_then(|e| parser.assert_finished().map(|_| e))
281 .map_err(|e| e.render_on(input))
282 .map_err(Error::InvalidQuery)
283}
284
285#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
287pub fn thing_with_range(input: &str) -> Result<Thing, Error> {
288 trace!(target: TARGET, "Parsing SurrealQL thing");
289
290 if input.len() > u32::MAX as usize {
291 return Err(Error::QueryTooLarge);
292 }
293
294 let mut parser = Parser::new_with_settings(
295 input.as_bytes(),
296 ParserSettings {
297 object_recursion_limit: *MAX_OBJECT_PARSING_DEPTH as usize,
298 query_recursion_limit: *MAX_QUERY_PARSING_DEPTH as usize,
299 ..Default::default()
300 },
301 );
302 let mut stack = Stack::new();
303 stack
304 .enter(|stk| parser.parse_thing_with_range(stk))
305 .finish()
306 .and_then(|e| parser.assert_finished().map(|_| e))
307 .map_err(|e| e.render_on(input))
308 .map_err(Error::InvalidQuery)
309}
310
311#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
313pub fn block(input: &str) -> Result<Block, Error> {
314 trace!(target: TARGET, "Parsing SurrealQL block");
315
316 if input.len() > u32::MAX as usize {
317 return Err(Error::QueryTooLarge);
318 }
319
320 let mut parser = Parser::new_with_settings(
321 input.as_bytes(),
322 ParserSettings {
323 object_recursion_limit: *MAX_OBJECT_PARSING_DEPTH as usize,
324 query_recursion_limit: *MAX_QUERY_PARSING_DEPTH as usize,
325 ..Default::default()
326 },
327 );
328 let mut stack = Stack::new();
329 let token = parser.peek();
330 match token.kind {
331 t!("{") => {
332 let start = parser.pop_peek().span;
333 stack
334 .enter(|stk| parser.parse_block(stk, start))
335 .finish()
336 .and_then(|e| parser.assert_finished().map(|_| e))
337 .map_err(|e| e.render_on(input))
338 .map_err(Error::InvalidQuery)
339 }
340 found => Err(Error::InvalidQuery(
341 error::SyntaxError::new(format_args!("Unexpected token `{found}` expected `{{`"))
342 .with_span(token.span, error::MessageKind::Error)
343 .render_on(input),
344 )),
345 }
346}
347
348#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
350pub fn value_legacy_strand(input: &str) -> Result<Value, Error> {
351 trace!(target: TARGET, "Parsing SurrealQL value, with legacy strings");
352
353 if input.len() > u32::MAX as usize {
354 return Err(Error::QueryTooLarge);
355 }
356
357 let mut parser = Parser::new_with_settings(
358 input.as_bytes(),
359 ParserSettings {
360 object_recursion_limit: *MAX_OBJECT_PARSING_DEPTH as usize,
361 query_recursion_limit: *MAX_QUERY_PARSING_DEPTH as usize,
362 legacy_strands: true,
363 ..Default::default()
364 },
365 );
366 let mut stack = Stack::new();
367 stack
368 .enter(|stk| parser.parse_value_field(stk))
369 .finish()
370 .and_then(|e| parser.assert_finished().map(|_| e))
371 .map_err(|e| e.render_on(input))
372 .map_err(Error::InvalidQuery)
373}
374
375#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
377pub fn json_legacy_strand(input: &str) -> Result<Value, Error> {
378 trace!(target: TARGET, "Parsing inert JSON value, with legacy strings");
379
380 if input.len() > u32::MAX as usize {
381 return Err(Error::QueryTooLarge);
382 }
383
384 let mut parser = Parser::new_with_settings(
385 input.as_bytes(),
386 ParserSettings {
387 object_recursion_limit: *MAX_OBJECT_PARSING_DEPTH as usize,
388 query_recursion_limit: *MAX_QUERY_PARSING_DEPTH as usize,
389 legacy_strands: true,
390 ..Default::default()
391 },
392 );
393 let mut stack = Stack::new();
394 stack
395 .enter(|stk| parser.parse_json(stk))
396 .finish()
397 .and_then(|e| parser.assert_finished().map(|_| e))
398 .map_err(|e| e.render_on(input))
399 .map_err(Error::InvalidQuery)
400}
401
402#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
404pub fn kind(input: &str) -> Result<Kind, Error> {
405 trace!(target: TARGET, "Parsing SurrealQL duration");
406
407 if input.len() > u32::MAX as usize {
408 return Err(Error::QueryTooLarge);
409 }
410
411 let mut parser = Parser::new(input.as_bytes());
412 let mut stack = Stack::new();
413 stack
414 .enter(|stk| parser.parse_inner_kind(stk))
415 .finish()
416 .and_then(|e| parser.assert_finished().map(|_| e))
417 .map_err(|e| e.render_on(input))
418 .map_err(Error::InvalidQuery)
419}