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