surrealdb_core/sql/statements/
select.rs1use crate::ctx::{Context, MutableContext};
2use crate::dbs::{Iterable, Iterator, Options, Statement};
3use crate::doc::CursorDoc;
4use crate::err::Error;
5use crate::idx::planner::{GrantedPermission, QueryPlanner, RecordStrategy, StatementContext};
6use crate::sql::{
7 order::{OldOrders, Order, OrderList, Ordering},
8 Cond, Explain, Fetchs, Field, Fields, Groups, Idioms, Limit, Splits, Start, Timeout, Value,
9 Values, Version, With,
10};
11
12use reblessive::tree::Stk;
13use revision::revisioned;
14use serde::{Deserialize, Serialize};
15use std::fmt;
16use std::sync::Arc;
17
18#[revisioned(revision = 4)]
19#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
20#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
21#[non_exhaustive]
22pub struct SelectStatement {
23 pub expr: Fields,
25 pub omit: Option<Idioms>,
26 #[revision(start = 2)]
27 pub only: bool,
28 pub what: Values,
30 pub with: Option<With>,
31 pub cond: Option<Cond>,
32 pub split: Option<Splits>,
33 pub group: Option<Groups>,
34 #[revision(end = 4, convert_fn = "convert_old_orders")]
35 pub old_order: Option<OldOrders>,
36 #[revision(start = 4)]
37 pub order: Option<Ordering>,
38 pub limit: Option<Limit>,
39 pub start: Option<Start>,
40 pub fetch: Option<Fetchs>,
41 pub version: Option<Version>,
42 pub timeout: Option<Timeout>,
43 pub parallel: bool,
44 pub explain: Option<Explain>,
45 #[revision(start = 3)]
46 pub tempfiles: bool,
47}
48
49impl SelectStatement {
50 fn convert_old_orders(
51 &mut self,
52 _rev: u16,
53 old_value: Option<OldOrders>,
54 ) -> Result<(), revision::Error> {
55 let Some(x) = old_value else {
56 return Ok(());
58 };
59
60 if x.0.iter().any(|x| x.random) {
61 self.order = Some(Ordering::Random);
62 return Ok(());
63 }
64
65 let new_ord =
66 x.0.into_iter()
67 .map(|x| Order {
68 value: x.order,
69 collate: x.collate,
70 numeric: x.numeric,
71 direction: x.direction,
72 })
73 .collect();
74
75 self.order = Some(Ordering::Order(OrderList(new_ord)));
76
77 Ok(())
78 }
79
80 pub(crate) fn writeable(&self) -> bool {
82 if self.expr.iter().any(|v| match v {
83 Field::All => false,
84 Field::Single {
85 expr,
86 ..
87 } => expr.writeable(),
88 }) {
89 return true;
90 }
91 if self.what.iter().any(|v| v.writeable()) {
92 return true;
93 }
94 self.cond.as_deref().is_some_and(Value::writeable)
95 }
96
97 pub(crate) async fn compute(
99 &self,
100 stk: &mut Stk,
101 ctx: &Context,
102 opt: &Options,
103 doc: Option<&CursorDoc>,
104 ) -> Result<Value, Error> {
105 opt.valid_for_db()?;
107 let stm = Statement::from(self);
109 let mut i = Iterator::new();
111 let version = match &self.version {
113 Some(v) => Some(v.compute(stk, ctx, opt, doc).await?),
114 _ => None,
115 };
116 let opt = Arc::new(opt.new_with_futures(false).with_version(version));
117 let limit = i.setup_limit(stk, ctx, &opt, &stm).await?;
119 let limit_is_one_or_zero = match limit {
121 Some(l) => l <= 1,
122 _ => false,
123 };
124 if self.only && !limit_is_one_or_zero && self.what.0.len() > 1 {
126 return Err(Error::SingleOnlyOutput);
127 }
128 let ctx = match self.timeout.as_ref() {
130 Some(timeout) => {
131 let mut ctx = MutableContext::new(ctx);
132 ctx.add_timeout(*timeout.0)?;
133 ctx.freeze()
134 }
135 None => ctx.clone(),
136 };
137 let mut planner = QueryPlanner::new();
139 let stm_ctx = StatementContext::new(&ctx, &opt, &stm)?;
140 for w in self.what.0.iter() {
142 let v = w.compute(stk, &ctx, &opt, doc).await?;
143 match v {
144 Value::Thing(v) => {
145 let p = planner.check_table_permission(&stm_ctx, &v.tb).await?;
146 if !matches!(p, GrantedPermission::None) {
148 match v.is_range() {
149 true => {
150 let rs = stm_ctx.check_record_strategy(false, p).await?;
152 i.prepare_range(&stm, v, rs)?
153 }
154 false => i.prepare_thing(&stm, v)?,
155 }
156 }
157 }
158 Value::Edges(v) => {
159 if self.only && !limit_is_one_or_zero {
160 return Err(Error::SingleOnlyOutput);
161 }
162 i.prepare_edges(&stm, *v)?;
163 }
164 Value::Mock(v) => {
165 if self.only && !limit_is_one_or_zero {
166 return Err(Error::SingleOnlyOutput);
167 }
168 i.prepare_mock(&stm, v)?;
169 }
170 Value::Table(t) => {
171 if self.only && !limit_is_one_or_zero {
172 return Err(Error::SingleOnlyOutput);
173 }
174 let p = planner.check_table_permission(&stm_ctx, &t).await?;
175 if !matches!(p, GrantedPermission::None) {
177 planner.add_iterables(stk, &stm_ctx, t, p, &mut i).await?;
178 }
179 }
180 Value::Array(v) => {
181 if self.only && !limit_is_one_or_zero {
182 return Err(Error::SingleOnlyOutput);
183 }
184 for v in v {
185 match v {
186 Value::Table(t) => {
187 let p = planner.check_table_permission(&stm_ctx, &t).await?;
188 if !matches!(p, GrantedPermission::None) {
190 planner.add_iterables(stk, &stm_ctx, t, p, &mut i).await?;
191 }
192 }
193 Value::Mock(v) => i.prepare_mock(&stm, v)?,
194 Value::Edges(v) => i.prepare_edges(&stm, *v)?,
195 Value::Thing(v) => {
196 let p = planner.check_table_permission(&stm_ctx, &v.tb).await?;
197 if !matches!(p, GrantedPermission::None) {
199 match v.is_range() {
200 true => {
201 let rs =
203 stm_ctx.check_record_strategy(false, p).await?;
204 i.prepare_range(&stm, v, rs)?
205 }
206 false => i.prepare_thing(&stm, v)?,
207 }
208 }
209 }
210 _ => i.ingest(Iterable::Value(v)),
211 }
212 }
213 }
214 v => i.ingest(Iterable::Value(v)),
215 };
216 }
217 let mut ctx = MutableContext::new(&ctx);
219 if planner.has_executors() {
221 ctx.set_query_planner(planner);
222 }
223 let ctx = ctx.freeze();
224 let res = i.output(stk, &ctx, &opt, &stm, RecordStrategy::KeysAndValues).await?;
226 if ctx.is_timedout() {
228 return Err(Error::QueryTimedout);
229 }
230 match res {
232 Value::Array(mut a) if self.only => match a.len() {
234 0 => Ok(Value::None),
236 1 => Ok(a.remove(0)),
238 _ => Err(Error::SingleOnlyOutput),
240 },
241 v => Ok(v),
243 }
244 }
245}
246
247impl fmt::Display for SelectStatement {
248 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
249 write!(f, "SELECT {}", self.expr)?;
250 if let Some(ref v) = self.omit {
251 write!(f, " OMIT {v}")?
252 }
253 write!(f, " FROM")?;
254 if self.only {
255 f.write_str(" ONLY")?
256 }
257 write!(f, " {}", self.what)?;
258 if let Some(ref v) = self.with {
259 write!(f, " {v}")?
260 }
261 if let Some(ref v) = self.cond {
262 write!(f, " {v}")?
263 }
264 if let Some(ref v) = self.split {
265 write!(f, " {v}")?
266 }
267 if let Some(ref v) = self.group {
268 write!(f, " {v}")?
269 }
270 if let Some(ref v) = self.order {
271 write!(f, " {v}")?
272 }
273 if let Some(ref v) = self.limit {
274 write!(f, " {v}")?
275 }
276 if let Some(ref v) = self.start {
277 write!(f, " {v}")?
278 }
279 if let Some(ref v) = self.fetch {
280 write!(f, " {v}")?
281 }
282 if let Some(ref v) = self.version {
283 write!(f, " {v}")?
284 }
285 if let Some(ref v) = self.timeout {
286 write!(f, " {v}")?
287 }
288 if self.parallel {
289 f.write_str(" PARALLEL")?
290 }
291 if let Some(ref v) = self.explain {
292 write!(f, " {v}")?
293 }
294 Ok(())
295 }
296}