surrealdb_core/syn/parser/stmt/
relate.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use reblessive::Stk;

use crate::{
	sql::{statements::RelateStatement, Subquery, Value},
	syn::{
		parser::{
			mac::{expected, expected_whitespace, unexpected},
			ParseResult, Parser,
		},
		token::t,
	},
};

impl Parser<'_> {
	pub async fn parse_relate_stmt(&mut self, stk: &mut Stk) -> ParseResult<RelateStatement> {
		let only = self.eat(t!("ONLY"));
		let (kind, from, with) = stk.run(|stk| self.parse_relation(stk)).await?;
		let uniq = self.eat(t!("UNIQUE"));

		let data = self.try_parse_data(stk).await?;
		let output = self.try_parse_output(stk).await?;
		let timeout = self.try_parse_timeout()?;
		let parallel = self.eat(t!("PARALLEL"));
		Ok(RelateStatement {
			only,
			kind,
			from,
			with,
			uniq,
			data,
			output,
			timeout,
			parallel,
		})
	}

	pub async fn parse_relation(&mut self, stk: &mut Stk) -> ParseResult<(Value, Value, Value)> {
		let first = self.parse_relate_value(stk).await?;
		let next = self.next();
		let is_o = match next.kind {
			t!("->") => true,
			t!("<") => {
				expected_whitespace!(self, t!("-"));
				false
			}
			_ => unexpected!(self, next, "a relation arrow"),
		};
		let kind = self.parse_relate_kind(stk).await?;
		if is_o {
			expected!(self, t!("->"));
		} else {
			expected!(self, t!("<"));
			expected_whitespace!(self, t!("-"));
		};
		let second = self.parse_relate_value(stk).await?;
		if is_o {
			Ok((kind, first, second))
		} else {
			Ok((kind, second, first))
		}
	}

	pub async fn parse_relate_kind(&mut self, ctx: &mut Stk) -> ParseResult<Value> {
		match self.peek_kind() {
			t!("$param") => self.next_token_value().map(Value::Param),
			t!("(") => {
				let span = self.pop_peek().span;
				let res = self
					.parse_inner_subquery(ctx, Some(span))
					.await
					.map(|x| Value::Subquery(Box::new(x)))?;
				Ok(res)
			}
			_ => self.parse_thing_or_table(ctx).await,
		}
	}
	pub async fn parse_relate_value(&mut self, ctx: &mut Stk) -> ParseResult<Value> {
		let old = self.table_as_field;
		self.table_as_field = true;
		let r = self.parse_relate_value_inner(ctx).await;
		self.table_as_field = old;
		r
	}

	async fn parse_relate_value_inner(&mut self, ctx: &mut Stk) -> ParseResult<Value> {
		match self.peek_kind() {
			t!("[") => {
				let start = self.pop_peek().span;
				self.parse_array(ctx, start).await.map(Value::Array)
			}
			t!("$param") => self.next_token_value().map(Value::Param),
			t!("RETURN")
			| t!("SELECT")
			| t!("CREATE")
			| t!("UPSERT")
			| t!("UPDATE")
			| t!("DELETE")
			| t!("RELATE")
			| t!("DEFINE")
			| t!("ALTER")
			| t!("REMOVE")
			| t!("REBUILD") => {
				self.parse_inner_subquery(ctx, None).await.map(|x| Value::Subquery(Box::new(x)))
			}
			t!("IF") => {
				self.pop_peek();
				ctx.run(|ctx| self.parse_if_stmt(ctx))
					.await
					.map(|x| Value::Subquery(Box::new(Subquery::Ifelse(x))))
			}
			t!("(") => {
				let span = self.pop_peek().span;
				let res = self
					.parse_inner_subquery(ctx, Some(span))
					.await
					.map(|x| Value::Subquery(Box::new(x)))?;
				Ok(res)
			}
			_ => self.parse_thing(ctx).await.map(Value::Thing),
		}
	}

	pub async fn parse_thing_or_table(&mut self, ctx: &mut Stk) -> ParseResult<Value> {
		if self.peek_whitespace1().kind == t!(":") {
			self.parse_thing(ctx).await.map(Value::Thing)
		} else {
			self.next_token_value().map(Value::Table)
		}
	}
}