mz_expr/scalar/func/impls/
record.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 CastRecordToString {
25 pub ty: ScalarType,
26}
27
28impl LazyUnaryFunc for CastRecordToString {
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 CastRecordToString {
71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 f.write_str("recordtostr")
73 }
74}
75
76#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
79pub struct CastRecord1ToRecord2 {
80 pub return_ty: ScalarType,
81 pub cast_exprs: Box<[MirScalarExpr]>,
82}
83
84impl LazyUnaryFunc for CastRecord1ToRecord2 {
85 fn eval<'a>(
86 &'a self,
87 datums: &[Datum<'a>],
88 temp_storage: &'a RowArena,
89 a: &'a MirScalarExpr,
90 ) -> Result<Datum<'a>, EvalError> {
91 let a = a.eval(datums, temp_storage)?;
92 if a.is_null() {
93 return Ok(Datum::Null);
94 }
95 let mut cast_datums = Vec::new();
96 for (el, cast_expr) in a.unwrap_list().iter().zip_eq(&self.cast_exprs) {
97 cast_datums.push(cast_expr.eval(&[el], temp_storage)?);
98 }
99 Ok(temp_storage.make_datum(|packer| packer.push_list(cast_datums)))
100 }
101
102 fn output_type(&self, input_type: ColumnType) -> ColumnType {
103 self.return_ty
104 .without_modifiers()
105 .nullable(input_type.nullable)
106 }
107
108 fn propagates_nulls(&self) -> bool {
109 true
110 }
111
112 fn introduces_nulls(&self) -> bool {
113 false
114 }
115
116 fn preserves_uniqueness(&self) -> bool {
117 false
118 }
119
120 fn inverse(&self) -> Option<crate::UnaryFunc> {
121 None
123 }
124
125 fn is_monotone(&self) -> bool {
126 false
130 }
131}
132
133impl fmt::Display for CastRecord1ToRecord2 {
134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135 f.write_str("record1torecord2")
136 }
137}
138
139#[derive(
140 Arbitrary, Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect,
141)]
142pub struct RecordGet(pub usize);
143
144impl LazyUnaryFunc for RecordGet {
145 fn eval<'a>(
146 &'a self,
147 datums: &[Datum<'a>],
148 temp_storage: &'a RowArena,
149 a: &'a MirScalarExpr,
150 ) -> Result<Datum<'a>, EvalError> {
151 let a = a.eval(datums, temp_storage)?;
152 if a.is_null() {
153 return Ok(Datum::Null);
154 }
155 Ok(a.unwrap_list().iter().nth(self.0).unwrap())
156 }
157
158 fn output_type(&self, input_type: ColumnType) -> ColumnType {
159 match input_type.scalar_type {
160 ScalarType::Record { fields, .. } => {
161 let (_name, ty) = &fields[self.0];
162 let mut ty = ty.clone();
163 ty.nullable = ty.nullable || input_type.nullable;
164 ty
165 }
166 _ => unreachable!(
167 "RecordGet on non-record input: {:?}",
168 input_type.scalar_type
169 ),
170 }
171 }
172
173 fn propagates_nulls(&self) -> bool {
174 true
175 }
176
177 fn introduces_nulls(&self) -> bool {
178 true
180 }
181
182 fn preserves_uniqueness(&self) -> bool {
183 false
184 }
185
186 fn inverse(&self) -> Option<crate::UnaryFunc> {
187 None
188 }
189
190 fn is_monotone(&self) -> bool {
191 false
192 }
193}
194
195impl fmt::Display for RecordGet {
196 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197 write!(f, "record_get[{}]", self.0)
198 }
199}