Skip to main content

surql_parser/upstream/syn/parser/stmt/
parts.rs

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