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_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
78impl fmt::Display for CastRecordToString {
79 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80 f.write_str("recordtostr")
81 }
82}
83
84#[derive(
87 Ord,
88 PartialOrd,
89 Clone,
90 Debug,
91 Eq,
92 PartialEq,
93 Serialize,
94 Deserialize,
95 Hash,
96 MzReflect
97)]
98pub struct CastRecord1ToRecord2 {
99 pub return_ty: SqlScalarType,
100 pub cast_exprs: Box<[MirScalarExpr]>,
101}
102
103impl LazyUnaryFunc for CastRecord1ToRecord2 {
104 fn eval<'a>(
105 &'a self,
106 datums: &[Datum<'a>],
107 temp_storage: &'a RowArena,
108 a: &'a MirScalarExpr,
109 ) -> Result<Datum<'a>, EvalError> {
110 let a = a.eval(datums, temp_storage)?;
111 if a.is_null() {
112 return Ok(Datum::Null);
113 }
114 let mut cast_datums = Vec::new();
115 for (el, cast_expr) in a.unwrap_list().iter().zip_eq(&self.cast_exprs) {
116 cast_datums.push(cast_expr.eval(&[el], temp_storage)?);
117 }
118 Ok(temp_storage.make_datum(|packer| packer.push_list(cast_datums)))
119 }
120
121 fn output_type(&self, input_type: SqlColumnType) -> SqlColumnType {
122 self.return_ty
123 .without_modifiers()
124 .nullable(input_type.nullable)
125 }
126
127 fn propagates_nulls(&self) -> bool {
128 true
129 }
130
131 fn introduces_nulls(&self) -> bool {
132 false
133 }
134
135 fn preserves_uniqueness(&self) -> bool {
136 false
137 }
138
139 fn inverse(&self) -> Option<crate::UnaryFunc> {
140 None
142 }
143
144 fn is_monotone(&self) -> bool {
145 false
149 }
150}
151
152impl fmt::Display for CastRecord1ToRecord2 {
153 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154 f.write_str("record1torecord2")
155 }
156}
157
158#[derive(
159 Ord,
160 PartialOrd,
161 Clone,
162 Debug,
163 Eq,
164 PartialEq,
165 Serialize,
166 Deserialize,
167 Hash,
168 MzReflect
169)]
170pub struct RecordGet(pub usize);
171
172impl LazyUnaryFunc for RecordGet {
173 fn eval<'a>(
174 &'a self,
175 datums: &[Datum<'a>],
176 temp_storage: &'a RowArena,
177 a: &'a MirScalarExpr,
178 ) -> Result<Datum<'a>, EvalError> {
179 let a = a.eval(datums, temp_storage)?;
180 if a.is_null() {
181 return Ok(Datum::Null);
182 }
183 Ok(a.unwrap_list().iter().nth(self.0).unwrap())
184 }
185
186 fn output_type(&self, input_type: SqlColumnType) -> SqlColumnType {
187 match input_type.scalar_type {
188 SqlScalarType::Record { fields, .. } => {
189 let (_name, ty) = &fields[self.0];
190 let mut ty = ty.clone();
191 ty.nullable = ty.nullable || input_type.nullable;
192 ty
193 }
194 _ => unreachable!(
195 "RecordGet on non-record input: {:?}",
196 input_type.scalar_type
197 ),
198 }
199 }
200
201 fn propagates_nulls(&self) -> bool {
202 true
203 }
204
205 fn introduces_nulls(&self) -> bool {
206 true
208 }
209
210 fn preserves_uniqueness(&self) -> bool {
211 false
212 }
213
214 fn inverse(&self) -> Option<crate::UnaryFunc> {
215 None
216 }
217
218 fn is_monotone(&self) -> bool {
219 false
220 }
221}
222
223impl fmt::Display for RecordGet {
224 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
225 write!(f, "record_get[{}]", self.0)
226 }
227}