surrealdb_core/sql/
field.rs

1use crate::ctx::Context;
2use crate::dbs::Options;
3use crate::doc::CursorDoc;
4use crate::err::Error;
5use crate::sql::statements::info::InfoStructure;
6use crate::sql::{fmt::Fmt, Idiom, Part, Value};
7use crate::syn;
8use reblessive::tree::Stk;
9use revision::revisioned;
10use serde::{Deserialize, Serialize};
11use std::borrow::Cow;
12use std::fmt::{self, Display, Formatter, Write};
13use std::ops::Deref;
14
15use super::paths::ID;
16
17#[revisioned(revision = 1)]
18#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
19#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
20#[non_exhaustive]
21pub struct Fields(pub Vec<Field>, pub bool);
22
23impl Fields {
24	/// Create a new `*` field projection
25	pub(crate) fn all() -> Self {
26		Self(vec![Field::All], false)
27	}
28	/// Check to see if this field is a `*` projection
29	pub fn is_all(&self) -> bool {
30		self.0.iter().any(|v| matches!(v, Field::All))
31	}
32	/// Create a new `VALUE id` field projection
33	pub(crate) fn value_id() -> Self {
34		Self(
35			vec![Field::Single {
36				expr: Value::Idiom(Idiom(ID.to_vec())),
37				alias: None,
38			}],
39			true,
40		)
41	}
42	/// Get all fields which are not an `*` projection
43	pub fn other(&self) -> impl Iterator<Item = &Field> {
44		self.0.iter().filter(|v| !matches!(v, Field::All))
45	}
46	/// Check to see if this field is a single VALUE clause
47	pub fn single(&self) -> Option<&Field> {
48		match (self.0.len(), self.1) {
49			(1, true) => match self.0.first() {
50				Some(Field::All) => None,
51				Some(v) => Some(v),
52				_ => None,
53			},
54			_ => None,
55		}
56	}
57	/// Check if the fields are only about counting
58	pub(crate) fn is_count_all_only(&self) -> bool {
59		let mut is_count_only = false;
60		for field in &self.0 {
61			if let Field::Single {
62				expr: Value::Function(func),
63				..
64			} = field
65			{
66				if func.is_count_all() {
67					is_count_only = true;
68					continue;
69				}
70			}
71			return false;
72		}
73		is_count_only
74	}
75}
76
77impl Deref for Fields {
78	type Target = Vec<Field>;
79	fn deref(&self) -> &Self::Target {
80		&self.0
81	}
82}
83
84impl IntoIterator for Fields {
85	type Item = Field;
86	type IntoIter = std::vec::IntoIter<Self::Item>;
87	fn into_iter(self) -> Self::IntoIter {
88		self.0.into_iter()
89	}
90}
91
92impl Display for Fields {
93	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
94		match self.single() {
95			Some(v) => write!(f, "VALUE {}", &v),
96			None => Display::fmt(&Fmt::comma_separated(&self.0), f),
97		}
98	}
99}
100
101impl InfoStructure for Fields {
102	fn structure(self) -> Value {
103		self.to_string().into()
104	}
105}
106
107impl Fields {
108	/// Process this type returning a computed simple Value
109	pub(crate) async fn compute(
110		&self,
111		stk: &mut Stk,
112		ctx: &Context,
113		opt: &Options,
114		doc: Option<&CursorDoc>,
115		group: bool,
116	) -> Result<Value, Error> {
117		if let Some(doc) = doc {
118			self.compute_value(stk, ctx, opt, doc, group).await
119		} else {
120			let doc = Value::None.into();
121			self.compute_value(stk, ctx, opt, &doc, group).await
122		}
123	}
124
125	async fn compute_value(
126		&self,
127		stk: &mut Stk,
128		ctx: &Context,
129		opt: &Options,
130		doc: &CursorDoc,
131		group: bool,
132	) -> Result<Value, Error> {
133		// Ensure futures are run
134		let opt = &opt.new_with_futures(true);
135		// Process the desired output
136		let mut out = match self.is_all() {
137			true => doc.doc.as_ref().compute(stk, ctx, opt, Some(doc)).await?,
138			false => Value::base(),
139		};
140		for v in self.other() {
141			match v {
142				Field::All => (),
143				Field::Single {
144					expr,
145					alias,
146				} => {
147					let name = alias
148						.as_ref()
149						.map(Cow::Borrowed)
150						.unwrap_or_else(|| Cow::Owned(expr.to_idiom()));
151					match expr {
152						// This expression is a grouped aggregate function
153						Value::Function(f) if group && f.is_aggregate() => {
154							let x = match f.args().len() {
155								// If no function arguments, then compute the result
156								0 => f.compute(stk, ctx, opt, Some(doc)).await?,
157								// If arguments, then pass the first value through
158								_ => f.args()[0].compute(stk, ctx, opt, Some(doc)).await?,
159							};
160							// Check if this is a single VALUE field expression
161							match self.single().is_some() {
162								false => out.set(stk, ctx, opt, name.as_ref(), x).await?,
163								true => out = x,
164							}
165						}
166						// This expression is a multi-output graph traversal
167						Value::Idiom(v) if v.is_multi_yield() => {
168							// Store the different output yields here
169							let mut res: Vec<(&[Part], Value)> = Vec::new();
170							// Split the expression by each output alias
171							for v in v.split_inclusive(Idiom::split_multi_yield) {
172								// Use the last fetched value for each fetch
173								let x = match res.last() {
174									Some((_, r)) => r,
175									None => doc.doc.as_ref(),
176								};
177								// Continue fetching the next idiom part
178								let x = x
179									.get(stk, ctx, opt, Some(doc), v)
180									.await?
181									.compute(stk, ctx, opt, Some(doc))
182									.await?
183									.flatten();
184								// Add the result to the temporary store
185								res.push((v, x));
186							}
187							// Assign each fetched yield to the output
188							for (p, x) in res {
189								match p.last().unwrap().alias() {
190									// This is an alias expression part
191									Some(a) => {
192										if let Some(i) = alias {
193											out.set(stk, ctx, opt, i, x.clone()).await?;
194										}
195										out.set(stk, ctx, opt, a, x).await?;
196									}
197									// This is the end of the expression
198									None => {
199										out.set(stk, ctx, opt, alias.as_ref().unwrap_or(v), x)
200											.await?
201									}
202								}
203							}
204						}
205						// This expression is a variable fields expression
206						Value::Function(f) if f.name() == Some("type::fields") => {
207							// Process the function using variable field projections
208							let expr = expr.compute(stk, ctx, opt, Some(doc)).await?;
209							// Check if this is a single VALUE field expression
210							match self.single().is_some() {
211								false => {
212									// Get the first argument which is guaranteed to exist
213									let args = match f.args().first().unwrap() {
214										Value::Param(v) => {
215											v.compute(stk, ctx, opt, Some(doc)).await?
216										}
217										v => v.to_owned(),
218									};
219									// This value is always an array, so we can convert it
220									let expr: Vec<Value> = expr.try_into()?;
221									// This value is always an array, so we can convert it
222									let args: Vec<Value> = args.try_into()?;
223									// This value is always an array, so we can convert it
224									for (name, expr) in args.into_iter().zip(expr) {
225										// This value is always a string, so we can convert it
226										let name = syn::idiom(&name.to_raw_string())?;
227										// Check if this is a single VALUE field expression
228										out.set(stk, ctx, opt, name.as_ref(), expr).await?
229									}
230								}
231								true => out = expr,
232							}
233						}
234						// This expression is a variable field expression
235						Value::Function(f) if f.name() == Some("type::field") => {
236							// Process the function using variable field projections
237							let expr = expr.compute(stk, ctx, opt, Some(doc)).await?;
238							// Check if this is a single VALUE field expression
239							match self.single().is_some() {
240								false => {
241									// Get the first argument which is guaranteed to exist
242									let name = match f.args().first().unwrap() {
243										Value::Param(v) => {
244											v.compute(stk, ctx, opt, Some(doc)).await?
245										}
246										v => v.to_owned(),
247									};
248									// find the name for the field, either from the argument or the
249									// alias.
250									let name = if let Some(x) = alias.as_ref().map(Cow::Borrowed) {
251										x
252									} else {
253										Cow::Owned(syn::idiom(&name.to_raw_string())?)
254									};
255									// Add the projected field to the output document
256									out.set(stk, ctx, opt, name.as_ref(), expr).await?
257								}
258								true => out = expr,
259							}
260						}
261						// This expression is a normal field expression
262						_ => {
263							let expr = expr.compute(stk, ctx, opt, Some(doc)).await?;
264							// Check if this is a single VALUE field expression
265							if self.single().is_some() {
266								out = expr;
267							} else {
268								out.set(stk, ctx, opt, name.as_ref(), expr).await?;
269							}
270						}
271					}
272				}
273			}
274		}
275		Ok(out)
276	}
277}
278
279#[revisioned(revision = 1)]
280#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
281#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
282#[non_exhaustive]
283pub enum Field {
284	/// The `*` in `SELECT * FROM ...`
285	#[default]
286	All,
287	/// The 'rating' in `SELECT rating FROM ...`
288	Single {
289		expr: Value,
290		/// The `quality` in `SELECT rating AS quality FROM ...`
291		alias: Option<Idiom>,
292	},
293}
294
295impl Display for Field {
296	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
297		match self {
298			Self::All => f.write_char('*'),
299			Self::Single {
300				expr,
301				alias,
302			} => {
303				Display::fmt(expr, f)?;
304				if let Some(alias) = alias {
305					f.write_str(" AS ")?;
306					Display::fmt(alias, f)
307				} else {
308					Ok(())
309				}
310			}
311		}
312	}
313}