mz_expr/scalar/func/impls/
map.rs
1use std::fmt;
11
12use itertools::Itertools;
13use mz_lowertest::MzReflect;
14use mz_repr::{ColumnType, Datum, RowArena, ScalarType};
15use proptest_derive::Arbitrary;
16use serde::{Deserialize, Serialize};
17
18use crate::scalar::func::{LazyUnaryFunc, stringify_datum};
19use crate::{EvalError, MirScalarExpr};
20
21#[derive(
22 Arbitrary, Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect,
23)]
24pub struct CastMapToString {
25 pub ty: ScalarType,
26}
27
28impl LazyUnaryFunc for CastMapToString {
29 fn eval<'a>(
30 &'a self,
31 datums: &[Datum<'a>],
32 temp_storage: &'a RowArena,
33 a: &'a MirScalarExpr,
34 ) -> Result<Datum<'a>, EvalError> {
35 let a = a.eval(datums, temp_storage)?;
36 if a.is_null() {
37 return Ok(Datum::Null);
38 }
39 let mut buf = String::new();
40 stringify_datum(&mut buf, a, &self.ty)?;
41 Ok(Datum::String(temp_storage.push_string(buf)))
42 }
43
44 fn output_type(&self, input_type: ColumnType) -> ColumnType {
45 ScalarType::String.nullable(input_type.nullable)
46 }
47
48 fn propagates_nulls(&self) -> bool {
49 true
50 }
51
52 fn introduces_nulls(&self) -> bool {
53 false
54 }
55
56 fn preserves_uniqueness(&self) -> bool {
57 true
58 }
59
60 fn inverse(&self) -> Option<crate::UnaryFunc> {
61 None
63 }
64
65 fn is_monotone(&self) -> bool {
66 false
67 }
68}
69
70impl fmt::Display for CastMapToString {
71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 f.write_str("maptostr")
73 }
74}
75
76#[derive(
77 Arbitrary, Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect,
78)]
79pub struct MapLength;
80
81impl LazyUnaryFunc for MapLength {
82 fn eval<'a>(
83 &'a self,
84 datums: &[Datum<'a>],
85 temp_storage: &'a RowArena,
86 a: &'a MirScalarExpr,
87 ) -> Result<Datum<'a>, EvalError> {
88 let a = a.eval(datums, temp_storage)?;
89 if a.is_null() {
90 return Ok(Datum::Null);
91 }
92 let count = a.unwrap_map().iter().count();
93 match count.try_into() {
94 Ok(c) => Ok(Datum::Int32(c)),
95 Err(_) => Err(EvalError::Int32OutOfRange(count.to_string().into())),
96 }
97 }
98
99 fn output_type(&self, input_type: ColumnType) -> ColumnType {
100 ScalarType::Int32.nullable(input_type.nullable)
101 }
102
103 fn propagates_nulls(&self) -> bool {
104 true
105 }
106
107 fn introduces_nulls(&self) -> bool {
108 false
109 }
110
111 fn preserves_uniqueness(&self) -> bool {
112 false
113 }
114
115 fn inverse(&self) -> Option<crate::UnaryFunc> {
116 None
117 }
118
119 fn is_monotone(&self) -> bool {
120 false
121 }
122}
123
124impl fmt::Display for MapLength {
125 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126 f.write_str("map_length")
127 }
128}
129
130#[derive(
131 Arbitrary, Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect,
132)]
133pub struct MapBuildFromRecordList {
134 pub value_type: ScalarType,
135}
136
137impl LazyUnaryFunc for MapBuildFromRecordList {
138 fn eval<'a>(
139 &'a self,
140 datums: &[Datum<'a>],
141 temp_storage: &'a RowArena,
142 a: &'a MirScalarExpr,
143 ) -> Result<Datum<'a>, EvalError> {
144 let a = a.eval(datums, temp_storage)?;
145 if a.is_null() {
146 return Ok(Datum::Null);
147 }
148 let list = a.unwrap_list();
149 let mut map = std::collections::BTreeMap::new();
150
151 for i in list.iter() {
152 if i.is_null() {
153 continue;
154 }
155
156 for (k, v) in i.unwrap_list().iter().tuples() {
157 if k.is_null() {
158 continue;
159 }
160 map.insert(k.unwrap_str(), v);
161 }
162 }
163
164 let map = temp_storage.make_datum(|packer| packer.push_dict(map));
165 Ok(map)
166 }
167
168 fn output_type(&self, _input_type: ColumnType) -> ColumnType {
169 ScalarType::Map {
170 value_type: Box::new(self.value_type.clone()),
171 custom_id: None,
172 }
173 .nullable(true)
174 }
175
176 fn propagates_nulls(&self) -> bool {
177 true
178 }
179
180 fn introduces_nulls(&self) -> bool {
181 true
182 }
183
184 fn preserves_uniqueness(&self) -> bool {
185 false
186 }
187
188 fn inverse(&self) -> Option<crate::UnaryFunc> {
189 None
190 }
191
192 fn is_monotone(&self) -> bool {
193 false
194 }
195}
196
197impl fmt::Display for MapBuildFromRecordList {
198 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
199 f.write_str("map_build")
200 }
201}