surrealdb_core/syn/parser/stmt/
parts.rs

1//! Contains parsing code for smaller common parts of statements.
2
3use reblessive::Stk;
4
5use crate::sql::reference::{Reference, ReferenceDeleteStrategy};
6use crate::sql::Fetch;
7use crate::syn::error::bail;
8use crate::{
9	sql::{
10		changefeed::ChangeFeed,
11		index::{Distance, VectorType},
12		Base, Cond, Data, Duration, Fetchs, Field, Fields, Group, Groups, Ident, Idiom, Output,
13		Permission, Permissions, Tables, Timeout, Value, View,
14	},
15	syn::{
16		parser::{
17			mac::{expected, unexpected},
18			ParseResult, Parser,
19		},
20		token::{t, DistanceKind, Span, TokenKind, VectorTypeKind},
21	},
22};
23
24pub(crate) enum MissingKind {
25	Split,
26	Order,
27	Group,
28}
29
30impl Parser<'_> {
31	/// Parses a data production if the next token is a data keyword.
32	/// Otherwise returns None
33	pub async fn try_parse_data(&mut self, ctx: &mut Stk) -> ParseResult<Option<Data>> {
34		let res = match self.peek().kind {
35			t!("SET") => {
36				self.pop_peek();
37				let mut set_list = Vec::new();
38				loop {
39					let idiom = self.parse_plain_idiom(ctx).await?;
40					let operator = self.parse_assigner()?;
41					let value = ctx.run(|ctx| self.parse_value_field(ctx)).await?;
42					set_list.push((idiom, operator, value));
43					if !self.eat(t!(",")) {
44						break;
45					}
46				}
47				Data::SetExpression(set_list)
48			}
49			t!("UNSET") => {
50				self.pop_peek();
51				let idiom_list = self.parse_idiom_list(ctx).await?;
52				Data::UnsetExpression(idiom_list)
53			}
54			t!("PATCH") => {
55				self.pop_peek();
56				Data::PatchExpression(ctx.run(|ctx| self.parse_value_field(ctx)).await?)
57			}
58			t!("MERGE") => {
59				self.pop_peek();
60				Data::MergeExpression(ctx.run(|ctx| self.parse_value_field(ctx)).await?)
61			}
62			t!("REPLACE") => {
63				self.pop_peek();
64				Data::ReplaceExpression(ctx.run(|ctx| self.parse_value_field(ctx)).await?)
65			}
66			t!("CONTENT") => {
67				self.pop_peek();
68				Data::ContentExpression(ctx.run(|ctx| self.parse_value_field(ctx)).await?)
69			}
70			_ => return Ok(None),
71		};
72		Ok(Some(res))
73	}
74
75	/// Parses a statement output if the next token is `return`.
76	pub async fn try_parse_output(&mut self, ctx: &mut Stk) -> ParseResult<Option<Output>> {
77		if !self.eat(t!("RETURN")) {
78			return Ok(None);
79		}
80		let res = match self.peek_kind() {
81			t!("NONE") => {
82				self.pop_peek();
83				Output::None
84			}
85			t!("NULL") => {
86				self.pop_peek();
87				Output::Null
88			}
89			t!("DIFF") => {
90				self.pop_peek();
91				Output::Diff
92			}
93			t!("AFTER") => {
94				self.pop_peek();
95				Output::After
96			}
97			t!("BEFORE") => {
98				self.pop_peek();
99				Output::Before
100			}
101			_ => Output::Fields(self.parse_fields(ctx).await?),
102		};
103		Ok(Some(res))
104	}
105
106	/// Parses a statement timeout if the next token is `TIMEOUT`.
107	pub fn try_parse_timeout(&mut self) -> ParseResult<Option<Timeout>> {
108		if !self.eat(t!("TIMEOUT")) {
109			return Ok(None);
110		}
111		let duration = self.next_token_value()?;
112		Ok(Some(Timeout(duration)))
113	}
114
115	pub async fn try_parse_fetch(&mut self, ctx: &mut Stk) -> ParseResult<Option<Fetchs>> {
116		if !self.eat(t!("FETCH")) {
117			return Ok(None);
118		}
119		let mut fetchs = self.try_parse_param_or_idiom_or_fields(ctx).await?;
120		while self.eat(t!(",")) {
121			fetchs.append(&mut self.try_parse_param_or_idiom_or_fields(ctx).await?);
122		}
123		Ok(Some(Fetchs(fetchs)))
124	}
125
126	pub async fn try_parse_param_or_idiom_or_fields(
127		&mut self,
128		ctx: &mut Stk,
129	) -> ParseResult<Vec<Fetch>> {
130		match self.peek().kind {
131			t!("$param") => Ok(vec![Value::Param(self.next_token_value()?).into()]),
132			t!("TYPE") => {
133				let fields = self.parse_fields(ctx).await?;
134				let fetches = fields
135					.0
136					.into_iter()
137					.filter_map(|f| {
138						if let Field::Single {
139							expr,
140							..
141						} = f
142						{
143							Some(expr.into())
144						} else {
145							None
146						}
147					})
148					.collect();
149				Ok(fetches)
150			}
151			_ => Ok(vec![Value::Idiom(self.parse_plain_idiom(ctx).await?).into()]),
152		}
153	}
154
155	pub async fn try_parse_condition(&mut self, ctx: &mut Stk) -> ParseResult<Option<Cond>> {
156		if !self.eat(t!("WHERE")) {
157			return Ok(None);
158		}
159		let v = ctx.run(|ctx| self.parse_value_field(ctx)).await?;
160		Ok(Some(Cond(v)))
161	}
162
163	pub(crate) fn check_idiom<'a>(
164		kind: MissingKind,
165		fields: &'a Fields,
166		field_span: Span,
167		idiom: &Idiom,
168		idiom_span: Span,
169	) -> ParseResult<&'a Field> {
170		let mut found = None;
171		for field in fields.iter() {
172			let Field::Single {
173				expr,
174				alias,
175			} = field
176			else {
177				unreachable!()
178			};
179
180			if let Some(alias) = alias {
181				if idiom == alias {
182					found = Some(field);
183					break;
184				}
185			}
186
187			match expr {
188				Value::Idiom(x) => {
189					if idiom == x {
190						found = Some(field);
191						break;
192					}
193				}
194				v => {
195					if *idiom == v.to_idiom() {
196						found = Some(field);
197						break;
198					}
199				}
200			}
201		}
202
203		let Some(found) = found else {
204			match kind {
205				MissingKind::Split => {
206					bail!(
207						"Missing split idiom `{idiom}` in statement selection",
208						@idiom_span,
209						@field_span => "Idiom missing here",
210					)
211				}
212				MissingKind::Order => {
213					bail!(
214						"Missing order idiom `{idiom}` in statement selection",
215						@idiom_span,
216						@field_span => "Idiom missing here",
217					)
218				}
219				MissingKind::Group => {
220					bail!(
221						"Missing group idiom `{idiom}` in statement selection",
222						@idiom_span,
223						@field_span => "Idiom missing here",
224					)
225				}
226			};
227		};
228
229		Ok(found)
230	}
231
232	pub async fn try_parse_group(
233		&mut self,
234		ctx: &mut Stk,
235		fields: &Fields,
236		fields_span: Span,
237	) -> ParseResult<Option<Groups>> {
238		if !self.eat(t!("GROUP")) {
239			return Ok(None);
240		}
241
242		if self.eat(t!("ALL")) {
243			return Ok(Some(Groups(Vec::new())));
244		}
245
246		self.eat(t!("BY"));
247
248		let has_all = fields.contains(&Field::All);
249
250		let before = self.peek().span;
251		let group = self.parse_basic_idiom(ctx).await?;
252		let group_span = before.covers(self.last_span());
253		if !has_all {
254			Self::check_idiom(MissingKind::Group, fields, fields_span, &group, group_span)?;
255		}
256
257		let mut groups = Groups(vec![Group(group)]);
258		while self.eat(t!(",")) {
259			let before = self.peek().span;
260			let group = self.parse_basic_idiom(ctx).await?;
261			let group_span = before.covers(self.last_span());
262			if !has_all {
263				Self::check_idiom(MissingKind::Group, fields, fields_span, &group, group_span)?;
264			}
265			groups.0.push(Group(group));
266		}
267
268		Ok(Some(groups))
269	}
270
271	/// Parse a permissions production
272	///
273	/// # Parser State
274	/// Expects the parser to have just eaten the `PERMISSIONS` keyword.
275	pub async fn parse_permission(
276		&mut self,
277		stk: &mut Stk,
278		field: bool,
279	) -> ParseResult<Permissions> {
280		let next = self.next();
281		match next.kind {
282			t!("NONE") => Ok(Permissions::none()),
283			t!("FULL") => Ok(Permissions::full()),
284			t!("FOR") => {
285				let mut permission = if field {
286					Permissions::full()
287				} else {
288					Permissions::none()
289				};
290				stk.run(|stk| self.parse_specific_permission(stk, &mut permission, field)).await?;
291				self.eat(t!(","));
292				while self.eat(t!("FOR")) {
293					stk.run(|stk| self.parse_specific_permission(stk, &mut permission, field))
294						.await?;
295					self.eat(t!(","));
296				}
297				Ok(permission)
298			}
299			_ => unexpected!(self, next, "'NONE', 'FULL' or 'FOR'"),
300		}
301	}
302
303	/// Parse a specific permission for a type of query
304	///
305	/// Sets the permission for a specific query on the given permission keyword.
306	///
307	/// # Parser State
308	/// Expects the parser to just have eaten the `FOR` keyword.
309	pub async fn parse_specific_permission(
310		&mut self,
311		stk: &mut Stk,
312		permissions: &mut Permissions,
313		field: bool,
314	) -> ParseResult<()> {
315		let mut select = false;
316		let mut create = false;
317		let mut update = false;
318		let mut delete = false;
319
320		loop {
321			let next = self.next();
322			match next.kind {
323				t!("SELECT") => {
324					select = true;
325				}
326				t!("CREATE") => {
327					create = true;
328				}
329				t!("UPDATE") => {
330					update = true;
331				}
332				t!("DELETE") => {
333					// TODO(gguillemas): Return a parse error instead of logging a warning in 3.0.0.
334					if field {
335						warn!("The DELETE permission has no effect on fields and is deprecated, but was found in a DEFINE FIELD statement.");
336					} else {
337						delete = true;
338					}
339				}
340				_ if field => unexpected!(self, next, "'SELECT', 'CREATE' or 'UPDATE'"),
341				_ => unexpected!(self, next, "'SELECT', 'CREATE', 'UPDATE' or 'DELETE'"),
342			}
343			if !self.eat(t!(",")) {
344				break;
345			}
346		}
347
348		let permission_value = self.parse_permission_value(stk).await?;
349		if select {
350			permissions.select = permission_value.clone();
351		}
352		if create {
353			permissions.create = permission_value.clone();
354		}
355		if update {
356			permissions.update = permission_value.clone();
357		}
358		if delete {
359			permissions.delete = permission_value
360		}
361
362		Ok(())
363	}
364
365	/// Parses a the value for a permission for a type of query
366	///
367	/// # Parser State
368	///
369	/// Expects the parser to just have eaten either `SELECT`, `CREATE`, `UPDATE` or `DELETE`.
370	pub async fn parse_permission_value(&mut self, stk: &mut Stk) -> ParseResult<Permission> {
371		let next = self.next();
372		match next.kind {
373			t!("NONE") => Ok(Permission::None),
374			t!("FULL") => Ok(Permission::Full),
375			t!("WHERE") => Ok(Permission::Specific(self.parse_value_field(stk).await?)),
376			_ => unexpected!(self, next, "'NONE', 'FULL', or 'WHERE'"),
377		}
378	}
379
380	// TODO(gguillemas): Deprecated in 2.0.0. Kept for backward compatibility. Drop it in 3.0.0.
381	/// Parses a base
382	///
383	/// So either `NAMESPACE`, `DATABASE`, `ROOT`, or `SCOPE` if `scope_allowed` is true.
384	///
385	/// # Parser state
386	/// Expects the next keyword to be a base.
387	pub fn parse_base(&mut self, scope_allowed: bool) -> ParseResult<Base> {
388		let next = self.next();
389		match next.kind {
390			t!("NAMESPACE") => Ok(Base::Ns),
391			t!("DATABASE") => Ok(Base::Db),
392			t!("ROOT") => Ok(Base::Root),
393			t!("SCOPE") => {
394				if !scope_allowed {
395					unexpected!(self, next, "a scope is not allowed here");
396				}
397				let name = self.next_token_value()?;
398				Ok(Base::Sc(name))
399			}
400			_ => {
401				if scope_allowed {
402					unexpected!(self, next, "'NAMEPSPACE', 'DATABASE', 'ROOT' or 'SCOPE'")
403				} else {
404					unexpected!(self, next, "'NAMEPSPACE', 'DATABASE' or 'ROOT'")
405				}
406			}
407		}
408	}
409
410	/// Parses a changefeed production
411	///
412	/// # Parser State
413	/// Expects the parser to have already eating the `CHANGEFEED` keyword
414	pub fn parse_changefeed(&mut self) -> ParseResult<ChangeFeed> {
415		let expiry = self.next_token_value::<Duration>()?.0;
416		let store_diff = if self.eat(t!("INCLUDE")) {
417			expected!(self, t!("ORIGINAL"));
418			true
419		} else {
420			false
421		};
422
423		Ok(ChangeFeed {
424			expiry,
425			store_diff,
426		})
427	}
428
429	/// Parses a reference
430	///
431	/// # Parser State
432	/// Expects the parser to have already eating the `REFERENCE` keyword
433	pub async fn parse_reference(&mut self, ctx: &mut Stk) -> ParseResult<Reference> {
434		let on_delete = if self.eat(t!("ON")) {
435			expected!(self, t!("DELETE"));
436			let next = self.next();
437			match next.kind {
438				t!("REJECT") => ReferenceDeleteStrategy::Reject,
439				t!("CASCADE") => ReferenceDeleteStrategy::Cascade,
440				t!("IGNORE") => ReferenceDeleteStrategy::Ignore,
441				t!("UNSET") => ReferenceDeleteStrategy::Unset,
442				t!("THEN") => ReferenceDeleteStrategy::Custom(
443					ctx.run(|ctx| self.parse_value_field(ctx)).await?,
444				),
445				_ => {
446					unexpected!(self, next, "`REJECT`, `CASCASE`, `IGNORE`, `UNSET` or `THEN`")
447				}
448			}
449		} else {
450			ReferenceDeleteStrategy::Ignore
451		};
452
453		Ok(Reference {
454			on_delete,
455		})
456	}
457
458	/// Parses a view production
459	///
460	/// # Parse State
461	/// Expects the parser to have already eaten the possible `(` if the view was wrapped in
462	/// parens. Expects the next keyword to be `SELECT`.
463	pub async fn parse_view(&mut self, stk: &mut Stk) -> ParseResult<View> {
464		expected!(self, t!("SELECT"));
465		let before_fields = self.peek().span;
466		let fields = self.parse_fields(stk).await?;
467		let fields_span = before_fields.covers(self.recent_span());
468		expected!(self, t!("FROM"));
469		let mut from = vec![self.next_token_value()?];
470		while self.eat(t!(",")) {
471			from.push(self.next_token_value()?);
472		}
473
474		let cond = self.try_parse_condition(stk).await?;
475		let group = self.try_parse_group(stk, &fields, fields_span).await?;
476
477		Ok(View {
478			expr: fields,
479			what: Tables(from),
480			cond,
481			group,
482		})
483	}
484
485	pub fn parse_distance(&mut self) -> ParseResult<Distance> {
486		let next = self.next();
487		match next.kind {
488			TokenKind::Distance(k) => {
489				let dist = match k {
490					DistanceKind::Chebyshev => Distance::Chebyshev,
491					DistanceKind::Cosine => Distance::Cosine,
492					DistanceKind::Euclidean => Distance::Euclidean,
493					DistanceKind::Manhattan => Distance::Manhattan,
494					DistanceKind::Hamming => Distance::Hamming,
495					DistanceKind::Jaccard => Distance::Jaccard,
496
497					DistanceKind::Minkowski => {
498						let distance = self.next_token_value()?;
499						Distance::Minkowski(distance)
500					}
501					DistanceKind::Pearson => Distance::Pearson,
502				};
503				Ok(dist)
504			}
505			_ => unexpected!(self, next, "a distance measure"),
506		}
507	}
508
509	pub fn parse_vector_type(&mut self) -> ParseResult<VectorType> {
510		let next = self.next();
511		match next.kind {
512			TokenKind::VectorType(x) => Ok(match x {
513				VectorTypeKind::F64 => VectorType::F64,
514				VectorTypeKind::F32 => VectorType::F32,
515				VectorTypeKind::I64 => VectorType::I64,
516				VectorTypeKind::I32 => VectorType::I32,
517				VectorTypeKind::I16 => VectorType::I16,
518			}),
519			_ => unexpected!(self, next, "a vector type"),
520		}
521	}
522
523	pub fn parse_custom_function_name(&mut self) -> ParseResult<Ident> {
524		expected!(self, t!("fn"));
525		expected!(self, t!("::"));
526		let mut name = self.next_token_value::<Ident>()?;
527		while self.eat(t!("::")) {
528			let part = self.next_token_value::<Ident>()?;
529			name.0.push_str("::");
530			name.0.push_str(part.0.as_str());
531		}
532		Ok(name)
533	}
534}