mz_expr/scalar/func/impls/
list.rs1use std::fmt;
11
12use mz_lowertest::MzReflect;
13use mz_repr::{Datum, Row, RowArena, SqlColumnType, SqlScalarType};
14use serde::{Deserialize, Serialize};
15
16use crate::scalar::func::{LazyUnaryFunc, stringify_datum};
17use crate::{EvalError, MirScalarExpr};
18
19#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
20pub struct CastListToString {
21 pub ty: SqlScalarType,
22}
23
24impl LazyUnaryFunc for CastListToString {
25 fn eval<'a>(
26 &'a self,
27 datums: &[Datum<'a>],
28 temp_storage: &'a RowArena,
29 a: &'a MirScalarExpr,
30 ) -> Result<Datum<'a>, EvalError> {
31 let a = a.eval(datums, temp_storage)?;
32 if a.is_null() {
33 return Ok(Datum::Null);
34 }
35 let mut buf = String::new();
36 stringify_datum(&mut buf, a, &self.ty)?;
37 Ok(Datum::String(temp_storage.push_string(buf)))
38 }
39
40 fn output_type(&self, input_type: SqlColumnType) -> SqlColumnType {
41 SqlScalarType::String.nullable(input_type.nullable)
42 }
43
44 fn propagates_nulls(&self) -> bool {
45 true
46 }
47
48 fn introduces_nulls(&self) -> bool {
49 false
50 }
51
52 fn preserves_uniqueness(&self) -> bool {
53 true
54 }
55
56 fn inverse(&self) -> Option<crate::UnaryFunc> {
57 None
59 }
60
61 fn is_monotone(&self) -> bool {
62 false
63 }
64}
65
66impl fmt::Display for CastListToString {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 f.write_str("listtostr")
69 }
70}
71
72#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
73pub struct CastListToJsonb {
74 pub cast_element: Box<MirScalarExpr>,
75}
76
77impl LazyUnaryFunc for CastListToJsonb {
78 fn eval<'a>(
79 &'a self,
80 datums: &[Datum<'a>],
81 temp_storage: &'a RowArena,
82 a: &'a MirScalarExpr,
83 ) -> Result<Datum<'a>, EvalError> {
84 let a = a.eval(datums, temp_storage)?;
85 if a.is_null() {
86 return Ok(Datum::Null);
87 }
88 let mut row = Row::default();
89 row.packer().push_list_with(|packer| {
90 for elem in a.unwrap_list().iter() {
91 let elem = match self.cast_element.eval(&[elem], temp_storage)? {
92 Datum::Null => Datum::JsonNull,
93 d => d,
94 };
95 packer.push(elem);
96 }
97 Ok::<_, EvalError>(())
98 })?;
99 Ok(temp_storage.push_unary_row(row))
100 }
101
102 fn output_type(&self, input_type: SqlColumnType) -> SqlColumnType {
103 SqlScalarType::Jsonb.nullable(input_type.nullable)
104 }
105
106 fn propagates_nulls(&self) -> bool {
107 true
108 }
109
110 fn introduces_nulls(&self) -> bool {
111 false
112 }
113
114 fn preserves_uniqueness(&self) -> bool {
115 true
116 }
117
118 fn inverse(&self) -> Option<crate::UnaryFunc> {
119 None
122 }
123
124 fn is_monotone(&self) -> bool {
125 false
126 }
127}
128
129impl fmt::Display for CastListToJsonb {
130 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131 f.write_str("listtojsonb")
132 }
133}
134
135#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
138pub struct CastList1ToList2 {
139 pub return_ty: SqlScalarType,
141 pub cast_expr: Box<MirScalarExpr>,
143}
144
145impl LazyUnaryFunc for CastList1ToList2 {
146 fn eval<'a>(
147 &'a self,
148 datums: &[Datum<'a>],
149 temp_storage: &'a RowArena,
150 a: &'a MirScalarExpr,
151 ) -> Result<Datum<'a>, EvalError> {
152 let a = a.eval(datums, temp_storage)?;
153 if a.is_null() {
154 return Ok(Datum::Null);
155 }
156 let mut cast_datums = Vec::new();
157 for el in a.unwrap_list().iter() {
158 cast_datums.push(self.cast_expr.eval(&[el], temp_storage)?);
162 }
163
164 Ok(temp_storage.make_datum(|packer| packer.push_list(cast_datums)))
165 }
166
167 fn output_type(&self, input_type: SqlColumnType) -> SqlColumnType {
168 self.return_ty
169 .without_modifiers()
170 .nullable(input_type.nullable)
171 }
172
173 fn propagates_nulls(&self) -> bool {
174 true
175 }
176
177 fn introduces_nulls(&self) -> bool {
178 false
179 }
180
181 fn preserves_uniqueness(&self) -> bool {
182 false
183 }
184
185 fn inverse(&self) -> Option<crate::UnaryFunc> {
186 None
188 }
189
190 fn is_monotone(&self) -> bool {
191 false
192 }
193}
194
195impl fmt::Display for CastList1ToList2 {
196 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197 f.write_str("list1tolist2")
198 }
199}
200
201#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
202pub struct ListLength;
203
204impl LazyUnaryFunc for ListLength {
205 fn eval<'a>(
206 &'a self,
207 datums: &[Datum<'a>],
208 temp_storage: &'a RowArena,
209 a: &'a MirScalarExpr,
210 ) -> Result<Datum<'a>, EvalError> {
211 let a = a.eval(datums, temp_storage)?;
212 if a.is_null() {
213 return Ok(Datum::Null);
214 }
215 let count = a.unwrap_list().iter().count();
216 match count.try_into() {
217 Ok(c) => Ok(Datum::Int32(c)),
218 Err(_) => Err(EvalError::Int32OutOfRange(count.to_string().into())),
219 }
220 }
221
222 fn output_type(&self, input_type: SqlColumnType) -> SqlColumnType {
223 SqlScalarType::Int32.nullable(input_type.nullable)
224 }
225
226 fn propagates_nulls(&self) -> bool {
227 true
228 }
229
230 fn introduces_nulls(&self) -> bool {
231 false
232 }
233
234 fn preserves_uniqueness(&self) -> bool {
235 false
236 }
237
238 fn inverse(&self) -> Option<crate::UnaryFunc> {
239 None
240 }
241
242 fn is_monotone(&self) -> bool {
243 false
244 }
245}
246
247impl fmt::Display for ListLength {
248 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
249 f.write_str("list_length")
250 }
251}