surrealdb_sql/statements/
select.rs

1use crate::ctx::Context;
2use crate::dbs::{Iterable, Iterator, Options, Statement, Transaction};
3use crate::doc::CursorDoc;
4use crate::err::Error;
5use crate::idx::planner::QueryPlanner;
6use crate::{
7	Cond, Explain, Fetchs, Field, Fields, Groups, Idioms, Limit, Orders, Splits, Start, Timeout,
8	Value, Values, Version, With,
9};
10use derive::Store;
11use revision::revisioned;
12use serde::{Deserialize, Serialize};
13use std::fmt;
14
15#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
16#[revisioned(revision = 2)]
17pub struct SelectStatement {
18	pub expr: Fields,
19	pub omit: Option<Idioms>,
20	#[revision(start = 2)]
21	pub only: bool,
22	pub what: Values,
23	pub with: Option<With>,
24	pub cond: Option<Cond>,
25	pub split: Option<Splits>,
26	pub group: Option<Groups>,
27	pub order: Option<Orders>,
28	pub limit: Option<Limit>,
29	pub start: Option<Start>,
30	pub fetch: Option<Fetchs>,
31	pub version: Option<Version>,
32	pub timeout: Option<Timeout>,
33	pub parallel: bool,
34	pub explain: Option<Explain>,
35}
36
37impl SelectStatement {
38	/// Check if we require a writeable transaction
39	pub(crate) fn writeable(&self) -> bool {
40		if self.expr.iter().any(|v| match v {
41			Field::All => false,
42			Field::Single {
43				expr,
44				..
45			} => expr.writeable(),
46		}) {
47			return true;
48		}
49		if self.what.iter().any(|v| v.writeable()) {
50			return true;
51		}
52		self.cond.as_ref().map_or(false, |v| v.writeable())
53	}
54
55	/// Process this type returning a computed simple Value
56	pub(crate) async fn compute(
57		&self,
58		ctx: &Context<'_>,
59		opt: &Options,
60		txn: &Transaction,
61		doc: Option<&CursorDoc<'_>>,
62	) -> Result<Value, Error> {
63		// Valid options?
64		opt.valid_for_db()?;
65		// Create a new iterator
66		let mut i = Iterator::new();
67		// Ensure futures are stored
68		let opt = &opt.new_with_futures(false).with_projections(true);
69		// Get a query planner
70		let mut planner = QueryPlanner::new(opt, &self.with, &self.cond);
71		// Used for ONLY: is the limit 1?
72		let limit_is_one_or_zero = match &self.limit {
73			Some(l) => l.process(ctx, opt, txn, doc).await? <= 1,
74			_ => false,
75		};
76		// Fail for multiple targets without a limit
77		if self.only && !limit_is_one_or_zero && self.what.0.len() > 1 {
78			return Err(Error::SingleOnlyOutput);
79		}
80		// Loop over the select targets
81		for w in self.what.0.iter() {
82			let v = w.compute(ctx, opt, txn, doc).await?;
83			match v {
84				Value::Table(t) => {
85					if self.only && !limit_is_one_or_zero {
86						return Err(Error::SingleOnlyOutput);
87					}
88
89					planner.add_iterables(ctx, txn, t, &mut i).await?;
90				}
91				Value::Thing(v) => i.ingest(Iterable::Thing(v)),
92				Value::Range(v) => {
93					if self.only && !limit_is_one_or_zero {
94						return Err(Error::SingleOnlyOutput);
95					}
96
97					i.ingest(Iterable::Range(*v))
98				}
99				Value::Edges(v) => {
100					if self.only && !limit_is_one_or_zero {
101						return Err(Error::SingleOnlyOutput);
102					}
103
104					i.ingest(Iterable::Edges(*v))
105				}
106				Value::Mock(v) => {
107					if self.only && !limit_is_one_or_zero {
108						return Err(Error::SingleOnlyOutput);
109					}
110
111					for v in v {
112						i.ingest(Iterable::Thing(v));
113					}
114				}
115				Value::Array(v) => {
116					if self.only && !limit_is_one_or_zero {
117						return Err(Error::SingleOnlyOutput);
118					}
119
120					for v in v {
121						match v {
122							Value::Table(t) => {
123								planner.add_iterables(ctx, txn, t, &mut i).await?;
124							}
125							Value::Thing(v) => i.ingest(Iterable::Thing(v)),
126							Value::Edges(v) => i.ingest(Iterable::Edges(*v)),
127							Value::Mock(v) => {
128								for v in v {
129									i.ingest(Iterable::Thing(v));
130								}
131							}
132							_ => i.ingest(Iterable::Value(v)),
133						}
134					}
135				}
136				v => i.ingest(Iterable::Value(v)),
137			};
138		}
139		// Create a new context
140		let mut ctx = Context::new(ctx);
141		// Assign the statement
142		let stm = Statement::from(self);
143		// Add query executors if any
144		if planner.has_executors() {
145			ctx.set_query_planner(&planner);
146		}
147		// Output the results
148		match i.output(&ctx, opt, txn, &stm).await? {
149			// This is a single record result
150			Value::Array(mut a) if self.only => match a.len() {
151				// There were no results
152				0 => Ok(Value::None),
153				// There was exactly one result
154				1 => Ok(a.remove(0)),
155				// There were no results
156				_ => Err(Error::SingleOnlyOutput),
157			},
158			// This is standard query result
159			v => Ok(v),
160		}
161	}
162}
163
164impl fmt::Display for SelectStatement {
165	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
166		write!(f, "SELECT {}", self.expr)?;
167		if let Some(ref v) = self.omit {
168			write!(f, " OMIT {v}")?
169		}
170		write!(f, " FROM")?;
171		if self.only {
172			f.write_str(" ONLY")?
173		}
174		write!(f, " {}", self.what)?;
175		if let Some(ref v) = self.with {
176			write!(f, " {v}")?
177		}
178		if let Some(ref v) = self.cond {
179			write!(f, " {v}")?
180		}
181		if let Some(ref v) = self.split {
182			write!(f, " {v}")?
183		}
184		if let Some(ref v) = self.group {
185			write!(f, " {v}")?
186		}
187		if let Some(ref v) = self.order {
188			write!(f, " {v}")?
189		}
190		if let Some(ref v) = self.limit {
191			write!(f, " {v}")?
192		}
193		if let Some(ref v) = self.start {
194			write!(f, " {v}")?
195		}
196		if let Some(ref v) = self.fetch {
197			write!(f, " {v}")?
198		}
199		if let Some(ref v) = self.version {
200			write!(f, " {v}")?
201		}
202		if let Some(ref v) = self.timeout {
203			write!(f, " {v}")?
204		}
205		if self.parallel {
206			f.write_str(" PARALLEL")?
207		}
208		if let Some(ref v) = self.explain {
209			write!(f, " {v}")?
210		}
211		Ok(())
212	}
213}