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