surrealdb_core/sql/
field.rs

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