surrealdb_core/sql/
fetch.rs1use crate::ctx::Context;
2use crate::dbs::Options;
3use crate::err::Error;
4use crate::sql::fmt::Fmt;
5use crate::sql::statements::info::InfoStructure;
6use crate::sql::{Idiom, Value};
7use crate::syn;
8use reblessive::tree::Stk;
9use revision::revisioned;
10use serde::{Deserialize, Serialize};
11use std::fmt::{self, Display, Formatter};
12use std::ops::Deref;
13
14#[revisioned(revision = 1)]
15#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
16#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
17#[non_exhaustive]
18pub struct Fetchs(pub Vec<Fetch>);
19
20impl Deref for Fetchs {
21 type Target = Vec<Fetch>;
22 fn deref(&self) -> &Self::Target {
23 &self.0
24 }
25}
26
27impl IntoIterator for Fetchs {
28 type Item = Fetch;
29 type IntoIter = std::vec::IntoIter<Self::Item>;
30 fn into_iter(self) -> Self::IntoIter {
31 self.0.into_iter()
32 }
33}
34
35impl fmt::Display for Fetchs {
36 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
37 write!(f, "FETCH {}", Fmt::comma_separated(&self.0))
38 }
39}
40
41impl InfoStructure for Fetchs {
42 fn structure(self) -> Value {
43 self.into_iter().map(Fetch::structure).collect::<Vec<_>>().into()
44 }
45}
46
47#[revisioned(revision = 2)]
48#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
49#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
50#[non_exhaustive]
51pub struct Fetch(
52 #[revision(end = 2, convert_fn = "convert_fetch_idiom")] pub Idiom,
53 #[revision(start = 2)] pub Value,
54);
55
56impl Fetch {
57 fn convert_fetch_idiom(&mut self, _revision: u16, old: Idiom) -> Result<(), revision::Error> {
58 self.0 = if old.is_empty() {
59 Value::None
60 } else {
61 Value::Idiom(old)
62 };
63 Ok(())
64 }
65
66 pub(crate) async fn compute(
67 &self,
68 stk: &mut Stk,
69 ctx: &Context,
70 opt: &Options,
71 idioms: &mut Vec<Idiom>,
72 ) -> Result<(), Error> {
73 let strand_or_idiom = |v: Value| match v {
74 Value::Strand(s) => Ok(Idiom::from(s.0)),
75 Value::Idiom(i) => Ok(i.to_owned()),
76 v => Err(Error::InvalidFetch {
77 value: v,
78 }),
79 };
80 match &self.0 {
81 Value::Idiom(idiom) => {
82 idioms.push(idiom.to_owned());
83 Ok(())
84 }
85 Value::Param(param) => {
86 let v = param.compute(stk, ctx, opt, None).await?;
87 idioms.push(strand_or_idiom(v)?);
88 Ok(())
89 }
90 Value::Function(f) => {
91 if f.name() == Some("type::field") {
92 let v = match f.args().first().unwrap() {
93 Value::Param(v) => v.compute(stk, ctx, opt, None).await?,
94 v => v.to_owned(),
95 };
96 idioms.push(strand_or_idiom(v)?);
97 Ok(())
98 } else if f.name() == Some("type::fields") {
99 let args = match f.args().first().unwrap() {
101 Value::Param(v) => v.compute(stk, ctx, opt, None).await?,
102 v => v.to_owned(),
103 };
104 let args: Vec<Value> = args.try_into()?;
106 for v in args.into_iter() {
108 let i = match v {
109 Value::Param(v) => {
110 strand_or_idiom(v.compute(stk, ctx, opt, None).await?)?
111 }
112 Value::Strand(s) => syn::idiom(s.as_str())?,
113 Value::Idiom(i) => i,
114 v => {
115 return Err(Error::InvalidFetch {
116 value: v,
117 })
118 }
119 };
120 idioms.push(i);
121 }
122 Ok(())
123 } else {
124 Err(Error::InvalidFetch {
125 value: Value::Function(f.clone()),
126 })
127 }
128 }
129 v => Err(Error::InvalidFetch {
130 value: v.clone(),
131 }),
132 }
133 }
134}
135
136impl From<Value> for Fetch {
137 fn from(value: Value) -> Self {
138 Self(value)
139 }
140}
141
142impl Deref for Fetch {
143 type Target = Value;
144 fn deref(&self) -> &Self::Target {
145 &self.0
146 }
147}
148
149impl Display for Fetch {
150 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
151 Display::fmt(&self.0, f)
152 }
153}
154
155impl InfoStructure for Fetch {
156 fn structure(self) -> Value {
157 self.to_string().into()
158 }
159}