surrealdb_core/sql/statements/
select.rs

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