mz_expr/scalar/func/impls/
record.rs1use std::fmt;
11
12use itertools::Itertools;
13use mz_repr::{Datum, RowArena, SqlColumnType, SqlScalarType};
14use serde::{Deserialize, Serialize};
15
16use crate::scalar::func::{LazyUnaryFunc, stringify_datum};
17use crate::{Eval, EvalError, MirScalarExpr};
18
19#[derive(
20 Ord,
21 PartialOrd,
22 Clone,
23 Debug,
24 Eq,
25 PartialEq,
26 Serialize,
27 Deserialize,
28 Hash
29)]
30pub struct CastRecordToString {
31 pub ty: SqlScalarType,
32}
33
34impl LazyUnaryFunc for CastRecordToString {
35 fn eval<'a>(
36 &'a self,
37 datums: &[Datum<'a>],
38 temp_storage: &'a RowArena,
39 a: &'a impl Eval,
40 ) -> Result<Datum<'a>, EvalError> {
41 let a = a.eval(datums, temp_storage)?;
42 if a.is_null() {
43 return Ok(Datum::Null);
44 }
45 let mut buf = String::new();
46 stringify_datum(&mut buf, a, &self.ty)?;
47 Ok(Datum::String(temp_storage.push_string(buf)))
48 }
49
50 fn output_sql_type(&self, input_type: SqlColumnType) -> SqlColumnType {
51 SqlScalarType::String.nullable(input_type.nullable)
52 }
53
54 fn propagates_nulls(&self) -> bool {
55 true
56 }
57
58 fn introduces_nulls(&self) -> bool {
59 false
60 }
61
62 fn preserves_uniqueness(&self) -> bool {
63 true
64 }
65
66 fn inverse(&self) -> Option<crate::UnaryFunc> {
67 None
69 }
70
71 fn is_monotone(&self) -> bool {
72 false
73 }
74
75 fn is_eliminable_cast(&self) -> bool {
76 false
77 }
78}
79
80impl fmt::Display for CastRecordToString {
81 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
82 f.write_str("recordtostr")
83 }
84}
85
86#[derive(
89 Ord,
90 PartialOrd,
91 Clone,
92 Debug,
93 Eq,
94 PartialEq,
95 Serialize,
96 Deserialize,
97 Hash
98)]
99pub struct CastRecord1ToRecord2 {
100 pub return_ty: SqlScalarType,
101 pub cast_exprs: Box<[MirScalarExpr]>,
102}
103
104impl LazyUnaryFunc for CastRecord1ToRecord2 {
105 fn eval<'a>(
106 &'a self,
107 datums: &[Datum<'a>],
108 temp_storage: &'a RowArena,
109 a: &'a impl Eval,
110 ) -> Result<Datum<'a>, EvalError> {
111 let a = a.eval(datums, temp_storage)?;
112 if a.is_null() {
113 return Ok(Datum::Null);
114 }
115 let mut cast_datums = Vec::new();
116 for (el, cast_expr) in a.unwrap_list().iter().zip_eq(&self.cast_exprs) {
117 cast_datums.push(cast_expr.eval(&[el], temp_storage)?);
118 }
119 Ok(temp_storage.make_datum(|packer| packer.push_list(cast_datums)))
120 }
121
122 fn output_sql_type(&self, input_type: SqlColumnType) -> SqlColumnType {
123 self.return_ty
124 .without_modifiers()
125 .nullable(input_type.nullable)
126 }
127
128 fn propagates_nulls(&self) -> bool {
129 true
130 }
131
132 fn introduces_nulls(&self) -> bool {
133 false
134 }
135
136 fn preserves_uniqueness(&self) -> bool {
137 false
138 }
139
140 fn inverse(&self) -> Option<crate::UnaryFunc> {
141 None
143 }
144
145 fn is_monotone(&self) -> bool {
146 false
150 }
151
152 fn is_eliminable_cast(&self) -> bool {
153 false
154 }
155}
156
157impl fmt::Display for CastRecord1ToRecord2 {
158 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159 f.write_str("record1torecord2")
160 }
161}
162
163#[derive(
164 Ord,
165 PartialOrd,
166 Clone,
167 Debug,
168 Eq,
169 PartialEq,
170 Serialize,
171 Deserialize,
172 Hash
173)]
174pub struct RecordGet(pub usize);
175
176impl LazyUnaryFunc for RecordGet {
177 fn eval<'a>(
178 &'a self,
179 datums: &[Datum<'a>],
180 temp_storage: &'a RowArena,
181 a: &'a impl Eval,
182 ) -> Result<Datum<'a>, EvalError> {
183 let a = a.eval(datums, temp_storage)?;
184 if a.is_null() {
185 return Ok(Datum::Null);
186 }
187 Ok(a.unwrap_list().iter().nth(self.0).unwrap())
188 }
189
190 fn output_sql_type(&self, input_type: SqlColumnType) -> SqlColumnType {
191 match input_type.scalar_type {
192 SqlScalarType::Record { fields, .. } => {
193 let (_name, ty) = &fields[self.0];
194 let mut ty = ty.clone();
195 ty.nullable = ty.nullable || input_type.nullable;
196 ty
197 }
198 _ => unreachable!(
199 "RecordGet on non-record input: {:?}",
200 input_type.scalar_type
201 ),
202 }
203 }
204
205 fn propagates_nulls(&self) -> bool {
206 true
207 }
208
209 fn introduces_nulls(&self) -> bool {
210 true
212 }
213
214 fn preserves_uniqueness(&self) -> bool {
215 false
216 }
217
218 fn inverse(&self) -> Option<crate::UnaryFunc> {
219 None
220 }
221
222 fn is_monotone(&self) -> bool {
223 false
224 }
225
226 fn is_eliminable_cast(&self) -> bool {
227 false
228 }
229}
230
231impl fmt::Display for RecordGet {
232 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
233 write!(f, "record_get[{}]", self.0)
234 }
235}