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