surrealdb_expr/expr/
field.rs1use std::slice::Iter;
2
3use revision::revisioned;
4use surrealdb_types::{SqlFormat, ToSql};
5
6use super::paths::ID;
7use crate::expr::{Expr, Function, Idiom};
8
9#[revisioned(revision = 1)]
11#[derive(Clone, Debug, Eq, PartialEq, Hash)]
12pub enum Fields {
13 Value(Box<Selector>),
18 Select(Vec<Field>),
20}
21
22impl ToSql for Fields {
23 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
24 let fields: crate::sql::field::Fields = self.clone().into();
25 fields.fmt_sql(f, fmt);
26 }
27}
28
29impl Fields {
30 pub fn read_only(&self) -> bool {
33 match self {
34 Fields::Value(field) => field.read_only(),
35 Fields::Select(fields) => fields.iter().all(|x| x.read_only()),
36 }
37 }
38
39 pub fn all() -> Self {
41 Fields::Select(vec![Field::All])
42 }
43
44 pub fn has_all_selection(&self) -> bool {
46 match self {
47 Fields::Select(x) => x.iter().any(|x| matches!(x, Field::All)),
48 Fields::Value(_) => false,
49 }
50 }
51 pub fn value_id() -> Self {
53 Fields::Value(Box::new(Selector {
54 expr: Expr::Idiom(Idiom(ID.to_vec())),
55 alias: None,
56 }))
57 }
58
59 pub fn iter_non_all_fields(&self) -> FieldsIter<'_> {
61 match self {
62 Fields::Value(selector) => FieldsIter::Single(Some(selector)),
63 Fields::Select(fields) => FieldsIter::Multiple(fields.iter()),
64 }
65 }
66
67 pub fn is_single(&self) -> bool {
69 matches!(self, Fields::Value(_))
70 }
71 pub fn is_count_all_only(&self) -> bool {
73 fn field_is_count(f: &Field) -> bool {
74 match f {
75 Field::All => false,
76 Field::Single(selector) => selector_is_count(selector),
77 }
78 }
79 fn selector_is_count(f: &Selector) -> bool {
80 let Expr::FunctionCall(x) = &f.expr else {
81 return false;
82 };
83 if !x.arguments.is_empty() {
84 return false;
85 }
86 let Function::Normal(name) = &x.receiver else {
87 return false;
88 };
89 name == "count"
90 }
91
92 match self {
93 Fields::Value(field) => selector_is_count(field),
94 Fields::Select(fields) => !fields.is_empty() && fields.iter().all(field_is_count),
95 }
96 }
97}
98
99pub enum FieldsIter<'a> {
100 Single(Option<&'a Selector>),
101 Multiple(Iter<'a, Field>),
102}
103
104impl<'a> Iterator for FieldsIter<'a> {
105 type Item = &'a Selector;
106
107 fn next(&mut self) -> Option<Self::Item> {
108 match self {
109 FieldsIter::Single(field) => field.take(),
110 FieldsIter::Multiple(iter) => loop {
111 if let Field::Single(x) = iter.next()? {
112 return Some(x);
113 }
114 },
115 }
116 }
117
118 fn size_hint(&self) -> (usize, Option<usize>) {
119 match self {
120 FieldsIter::Single(field) => {
121 if field.is_some() {
122 (1, Some(1))
123 } else {
124 (0, Some(0))
125 }
126 }
127 FieldsIter::Multiple(iter) => iter.size_hint(),
128 }
129 }
130}
131impl ExactSizeIterator for FieldsIter<'_> {}
132
133#[revisioned(revision = 1)]
134#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
135pub enum Field {
136 #[default]
138 All,
139 Single(Selector),
141}
142
143impl Field {
144 pub fn read_only(&self) -> bool {
146 match self {
147 Field::All => true,
148 Field::Single(x) => x.read_only(),
149 }
150 }
151}
152
153impl ToSql for Field {
154 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
155 match self {
156 Self::All => f.push('*'),
157 Self::Single(s) => s.fmt_sql(f, fmt),
158 }
159 }
160}
161
162#[revisioned(revision = 1)]
163#[derive(Clone, Debug, Eq, PartialEq, Hash)]
164pub struct Selector {
165 pub expr: Expr,
166 pub alias: Option<Idiom>,
168}
169
170impl Selector {
171 pub fn read_only(&self) -> bool {
172 self.expr.read_only()
173 }
174}
175
176impl ToSql for Selector {
177 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
178 self.expr.fmt_sql(f, fmt);
179 if let Some(alias) = &self.alias {
180 f.push_str(" AS ");
181 alias.fmt_sql(f, fmt);
182 }
183 }
184}