1use crate::ctx::Context;
2use crate::dbs::Options;
3use crate::doc::CursorDoc;
4use crate::err::Error;
5use crate::sql::statements::info::InfoStructure;
6use crate::sql::{fmt::Fmt, Idiom, Part, Value};
7use crate::syn;
8use reblessive::tree::Stk;
9use revision::revisioned;
10use serde::{Deserialize, Serialize};
11use std::borrow::Cow;
12use std::fmt::{self, Display, Formatter, Write};
13use std::ops::Deref;
14
15use super::paths::ID;
16
17#[revisioned(revision = 1)]
18#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
19#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
20#[non_exhaustive]
21pub struct Fields(pub Vec<Field>, pub bool);
22
23impl Fields {
24 pub(crate) fn all() -> Self {
26 Self(vec![Field::All], false)
27 }
28 pub fn is_all(&self) -> bool {
30 self.0.iter().any(|v| matches!(v, Field::All))
31 }
32 pub(crate) fn value_id() -> Self {
34 Self(
35 vec![Field::Single {
36 expr: Value::Idiom(Idiom(ID.to_vec())),
37 alias: None,
38 }],
39 true,
40 )
41 }
42 pub fn other(&self) -> impl Iterator<Item = &Field> {
44 self.0.iter().filter(|v| !matches!(v, Field::All))
45 }
46 pub fn single(&self) -> Option<&Field> {
48 match (self.0.len(), self.1) {
49 (1, true) => match self.0.first() {
50 Some(Field::All) => None,
51 Some(v) => Some(v),
52 _ => None,
53 },
54 _ => None,
55 }
56 }
57 pub(crate) fn is_count_all_only(&self) -> bool {
59 let mut is_count_only = false;
60 for field in &self.0 {
61 if let Field::Single {
62 expr: Value::Function(func),
63 ..
64 } = field
65 {
66 if func.is_count_all() {
67 is_count_only = true;
68 continue;
69 }
70 }
71 return false;
72 }
73 is_count_only
74 }
75}
76
77impl Deref for Fields {
78 type Target = Vec<Field>;
79 fn deref(&self) -> &Self::Target {
80 &self.0
81 }
82}
83
84impl IntoIterator for Fields {
85 type Item = Field;
86 type IntoIter = std::vec::IntoIter<Self::Item>;
87 fn into_iter(self) -> Self::IntoIter {
88 self.0.into_iter()
89 }
90}
91
92impl Display for Fields {
93 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
94 match self.single() {
95 Some(v) => write!(f, "VALUE {}", &v),
96 None => Display::fmt(&Fmt::comma_separated(&self.0), f),
97 }
98 }
99}
100
101impl InfoStructure for Fields {
102 fn structure(self) -> Value {
103 self.to_string().into()
104 }
105}
106
107impl Fields {
108 pub(crate) async fn compute(
110 &self,
111 stk: &mut Stk,
112 ctx: &Context,
113 opt: &Options,
114 doc: Option<&CursorDoc>,
115 group: bool,
116 ) -> Result<Value, Error> {
117 if let Some(doc) = doc {
118 self.compute_value(stk, ctx, opt, doc, group).await
119 } else {
120 let doc = Value::None.into();
121 self.compute_value(stk, ctx, opt, &doc, group).await
122 }
123 }
124
125 async fn compute_value(
126 &self,
127 stk: &mut Stk,
128 ctx: &Context,
129 opt: &Options,
130 doc: &CursorDoc,
131 group: bool,
132 ) -> Result<Value, Error> {
133 let opt = &opt.new_with_futures(true);
135 let mut out = match self.is_all() {
137 true => doc.doc.as_ref().compute(stk, ctx, opt, Some(doc)).await?,
138 false => Value::base(),
139 };
140 for v in self.other() {
141 match v {
142 Field::All => (),
143 Field::Single {
144 expr,
145 alias,
146 } => {
147 let name = alias
148 .as_ref()
149 .map(Cow::Borrowed)
150 .unwrap_or_else(|| Cow::Owned(expr.to_idiom()));
151 match expr {
152 Value::Function(f) if group && f.is_aggregate() => {
154 let x = match f.args().len() {
155 0 => f.compute(stk, ctx, opt, Some(doc)).await?,
157 _ => f.args()[0].compute(stk, ctx, opt, Some(doc)).await?,
159 };
160 match self.single().is_some() {
162 false => out.set(stk, ctx, opt, name.as_ref(), x).await?,
163 true => out = x,
164 }
165 }
166 Value::Idiom(v) if v.is_multi_yield() => {
168 let mut res: Vec<(&[Part], Value)> = Vec::new();
170 for v in v.split_inclusive(Idiom::split_multi_yield) {
172 let x = match res.last() {
174 Some((_, r)) => r,
175 None => doc.doc.as_ref(),
176 };
177 let x = x
179 .get(stk, ctx, opt, Some(doc), v)
180 .await?
181 .compute(stk, ctx, opt, Some(doc))
182 .await?
183 .flatten();
184 res.push((v, x));
186 }
187 for (p, x) in res {
189 match p.last().unwrap().alias() {
190 Some(a) => {
192 if let Some(i) = alias {
193 out.set(stk, ctx, opt, i, x.clone()).await?;
194 }
195 out.set(stk, ctx, opt, a, x).await?;
196 }
197 None => {
199 out.set(stk, ctx, opt, alias.as_ref().unwrap_or(v), x)
200 .await?
201 }
202 }
203 }
204 }
205 Value::Function(f) if f.name() == Some("type::fields") => {
207 let expr = expr.compute(stk, ctx, opt, Some(doc)).await?;
209 match self.single().is_some() {
211 false => {
212 let args = match f.args().first().unwrap() {
214 Value::Param(v) => {
215 v.compute(stk, ctx, opt, Some(doc)).await?
216 }
217 v => v.to_owned(),
218 };
219 let expr: Vec<Value> = expr.try_into()?;
221 let args: Vec<Value> = args.try_into()?;
223 for (name, expr) in args.into_iter().zip(expr) {
225 let name = syn::idiom(&name.to_raw_string())?;
227 out.set(stk, ctx, opt, name.as_ref(), expr).await?
229 }
230 }
231 true => out = expr,
232 }
233 }
234 Value::Function(f) if f.name() == Some("type::field") => {
236 let expr = expr.compute(stk, ctx, opt, Some(doc)).await?;
238 match self.single().is_some() {
240 false => {
241 let name = match f.args().first().unwrap() {
243 Value::Param(v) => {
244 v.compute(stk, ctx, opt, Some(doc)).await?
245 }
246 v => v.to_owned(),
247 };
248 let name = if let Some(x) = alias.as_ref().map(Cow::Borrowed) {
251 x
252 } else {
253 Cow::Owned(syn::idiom(&name.to_raw_string())?)
254 };
255 out.set(stk, ctx, opt, name.as_ref(), expr).await?
257 }
258 true => out = expr,
259 }
260 }
261 _ => {
263 let expr = expr.compute(stk, ctx, opt, Some(doc)).await?;
264 if self.single().is_some() {
266 out = expr;
267 } else {
268 out.set(stk, ctx, opt, name.as_ref(), expr).await?;
269 }
270 }
271 }
272 }
273 }
274 }
275 Ok(out)
276 }
277}
278
279#[revisioned(revision = 1)]
280#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
281#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
282#[non_exhaustive]
283pub enum Field {
284 #[default]
286 All,
287 Single {
289 expr: Value,
290 alias: Option<Idiom>,
292 },
293}
294
295impl Display for Field {
296 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
297 match self {
298 Self::All => f.write_char('*'),
299 Self::Single {
300 expr,
301 alias,
302 } => {
303 Display::fmt(expr, f)?;
304 if let Some(alias) = alias {
305 f.write_str(" AS ")?;
306 Display::fmt(alias, f)
307 } else {
308 Ok(())
309 }
310 }
311 }
312 }
313}