1use mz_repr::{Datum, InputDatumType, OutputDatumType, ReprColumnType, RowArena, SqlColumnType};
13
14use crate::{Eval, EvalError};
15
16pub(crate) trait LazyBinaryFunc {
19 fn eval<'a>(
20 &'a self,
21 datums: &[Datum<'a>],
22 temp_storage: &'a RowArena,
23 exprs: &[&'a impl Eval],
24 ) -> Result<Datum<'a>, EvalError>;
25
26 fn output_sql_type(&self, input_types: &[SqlColumnType]) -> SqlColumnType;
28
29 fn output_type(&self, input_types: &[ReprColumnType]) -> ReprColumnType {
31 ReprColumnType::from(
32 &self.output_sql_type(
33 &input_types
34 .iter()
35 .map(SqlColumnType::from_repr)
36 .collect::<Vec<_>>(),
37 ),
38 )
39 }
40
41 fn propagates_nulls(&self) -> bool;
43
44 fn introduces_nulls(&self) -> bool;
46
47 fn could_error(&self) -> bool {
49 true
51 }
52
53 fn negate(&self) -> Option<crate::BinaryFunc>;
55
56 fn is_monotone(&self) -> (bool, bool);
69
70 fn is_infinity_monotone(&self) -> bool {
79 true
80 }
81
82 fn is_infix_op(&self) -> bool;
84}
85
86pub(crate) trait EagerBinaryFunc {
87 type Input<'a>: InputDatumType<'a, EvalError>;
88 type Output<'a>: OutputDatumType<'a, EvalError>;
89
90 fn call<'a>(&self, input: Self::Input<'a>, temp_storage: &'a RowArena) -> Self::Output<'a>;
91
92 fn output_sql_type(&self, input_types: &[SqlColumnType]) -> SqlColumnType;
94
95 #[allow(dead_code)]
97 fn output_type(&self, input_types: &[ReprColumnType]) -> ReprColumnType {
98 ReprColumnType::from(
99 &self.output_sql_type(
100 &input_types
101 .iter()
102 .map(SqlColumnType::from_repr)
103 .collect::<Vec<_>>(),
104 ),
105 )
106 }
107
108 fn propagates_nulls(&self) -> bool {
110 !Self::Input::nullable()
112 }
113
114 fn introduces_nulls(&self) -> bool {
116 Self::Output::nullable()
118 }
119
120 fn could_error(&self) -> bool {
122 Self::Output::fallible()
123 }
124
125 fn negate(&self) -> Option<crate::BinaryFunc> {
127 None
128 }
129
130 fn is_monotone(&self) -> (bool, bool) {
131 (false, false)
132 }
133
134 fn is_infinity_monotone(&self) -> bool {
135 true
136 }
137
138 fn is_infix_op(&self) -> bool {
139 false
140 }
141}
142
143struct EvalArgs<'a, 'd, E> {
145 exprs: std::array::IntoIter<&'a E, 2>,
146 datums: &'d [Datum<'a>],
147 temp_storage: &'a RowArena,
148}
149
150impl<'a, 'd, E: Eval> Iterator for EvalArgs<'a, 'd, E> {
151 type Item = Result<Datum<'a>, EvalError>;
152 #[inline]
153 fn next(&mut self) -> Option<Self::Item> {
154 self.exprs
155 .next()
156 .map(|expr| expr.eval(self.datums, self.temp_storage))
157 }
158}
159
160impl<T: EagerBinaryFunc> LazyBinaryFunc for T {
161 fn eval<'a>(
162 &'a self,
163 datums: &[Datum<'a>],
164 temp_storage: &'a RowArena,
165 exprs: &[&'a impl Eval],
166 ) -> Result<Datum<'a>, EvalError> {
167 let [expr_a, expr_b] = exprs else {
168 return Err(EvalError::Internal(
169 format!("binary function called with {} arguments", exprs.len()).into(),
170 ));
171 };
172 let mut datums = EvalArgs {
179 exprs: [*expr_a, *expr_b].into_iter(),
180 datums,
181 temp_storage,
182 };
183 let input = match T::Input::try_from_iter(&mut datums) {
184 Ok(input) => input,
186 Err(Ok(Some(datum))) if !datum.is_null() => {
188 return Err(EvalError::Internal("invalid input type".into()));
189 }
190 Err(Ok(None)) => {
191 return Err(EvalError::Internal("unexpectedly missing parameter".into()));
192 }
193 Err(Ok(Some(datum))) => return Ok(datum),
195 Err(Err(res)) => return Err(res),
196 };
197 if datums.next().is_some() {
198 return Err(EvalError::Internal("unconsumed input argument".into()));
199 }
200 self.call(input, temp_storage).into_result(temp_storage)
201 }
202
203 fn output_sql_type(&self, input_types: &[SqlColumnType]) -> SqlColumnType {
204 self.output_sql_type(input_types)
205 }
206
207 fn propagates_nulls(&self) -> bool {
208 self.propagates_nulls()
209 }
210
211 fn introduces_nulls(&self) -> bool {
212 self.introduces_nulls()
213 }
214
215 fn could_error(&self) -> bool {
216 self.could_error()
217 }
218
219 fn negate(&self) -> Option<crate::BinaryFunc> {
220 self.negate()
221 }
222
223 fn is_monotone(&self) -> (bool, bool) {
224 self.is_monotone()
225 }
226
227 fn is_infinity_monotone(&self) -> bool {
228 self.is_infinity_monotone()
229 }
230
231 fn is_infix_op(&self) -> bool {
232 self.is_infix_op()
233 }
234}
235
236pub use derive::BinaryFunc;
237
238mod derive {
239 use std::fmt;
240
241 use mz_repr::{Datum, ReprColumnType, RowArena, SqlColumnType};
242
243 use crate::scalar::func::binary::LazyBinaryFunc;
244 use crate::scalar::func::*;
245 use crate::{Eval, EvalError};
246
247 derive_binary! {
248 AddInt16(AddInt16),
249 AddInt32(AddInt32),
250 AddInt64(AddInt64),
251 AddUint16(AddUint16),
252 AddUint32(AddUint32),
253 AddUint64(AddUint64),
254 AddFloat32(AddFloat32),
255 AddFloat64(AddFloat64),
256 AddInterval(AddInterval),
257 AddTimestampInterval(AddTimestampInterval),
258 AddTimestampTzInterval(AddTimestampTzInterval),
259 AddDateInterval(AddDateInterval),
260 AddDateTime(AddDateTime),
261 AddTimeInterval(AddTimeInterval),
262 AddNumeric(AddNumeric),
263 AgeTimestamp(AgeTimestamp),
264 AgeTimestampTz(AgeTimestampTz),
265 BitAndInt16(BitAndInt16),
266 BitAndInt32(BitAndInt32),
267 BitAndInt64(BitAndInt64),
268 BitAndUint16(BitAndUint16),
269 BitAndUint32(BitAndUint32),
270 BitAndUint64(BitAndUint64),
271 BitOrInt16(BitOrInt16),
272 BitOrInt32(BitOrInt32),
273 BitOrInt64(BitOrInt64),
274 BitOrUint16(BitOrUint16),
275 BitOrUint32(BitOrUint32),
276 BitOrUint64(BitOrUint64),
277 BitXorInt16(BitXorInt16),
278 BitXorInt32(BitXorInt32),
279 BitXorInt64(BitXorInt64),
280 BitXorUint16(BitXorUint16),
281 BitXorUint32(BitXorUint32),
282 BitXorUint64(BitXorUint64),
283 BitShiftLeftInt16(BitShiftLeftInt16),
284 BitShiftLeftInt32(BitShiftLeftInt32),
285 BitShiftLeftInt64(BitShiftLeftInt64),
286 BitShiftLeftUint16(BitShiftLeftUint16),
287 BitShiftLeftUint32(BitShiftLeftUint32),
288 BitShiftLeftUint64(BitShiftLeftUint64),
289 BitShiftRightInt16(BitShiftRightInt16),
290 BitShiftRightInt32(BitShiftRightInt32),
291 BitShiftRightInt64(BitShiftRightInt64),
292 BitShiftRightUint16(BitShiftRightUint16),
293 BitShiftRightUint32(BitShiftRightUint32),
294 BitShiftRightUint64(BitShiftRightUint64),
295 SubInt16(SubInt16),
296 SubInt32(SubInt32),
297 SubInt64(SubInt64),
298 SubUint16(SubUint16),
299 SubUint32(SubUint32),
300 SubUint64(SubUint64),
301 SubFloat32(SubFloat32),
302 SubFloat64(SubFloat64),
303 SubInterval(SubInterval),
304 SubTimestamp(SubTimestamp),
305 SubTimestampTz(SubTimestampTz),
306 SubTimestampInterval(SubTimestampInterval),
307 SubTimestampTzInterval(SubTimestampTzInterval),
308 SubDate(SubDate),
309 SubDateInterval(SubDateInterval),
310 SubTime(SubTime),
311 SubTimeInterval(SubTimeInterval),
312 SubNumeric(SubNumeric),
313 MulInt16(MulInt16),
314 MulInt32(MulInt32),
315 MulInt64(MulInt64),
316 MulUint16(MulUint16),
317 MulUint32(MulUint32),
318 MulUint64(MulUint64),
319 MulFloat32(MulFloat32),
320 MulFloat64(MulFloat64),
321 MulNumeric(MulNumeric),
322 MulInterval(MulInterval),
323 DivInt16(DivInt16),
324 DivInt32(DivInt32),
325 DivInt64(DivInt64),
326 DivUint16(DivUint16),
327 DivUint32(DivUint32),
328 DivUint64(DivUint64),
329 DivFloat32(DivFloat32),
330 DivFloat64(DivFloat64),
331 DivNumeric(DivNumeric),
332 DivInterval(DivInterval),
333 ModInt16(ModInt16),
334 ModInt32(ModInt32),
335 ModInt64(ModInt64),
336 ModUint16(ModUint16),
337 ModUint32(ModUint32),
338 ModUint64(ModUint64),
339 ModFloat32(ModFloat32),
340 ModFloat64(ModFloat64),
341 ModNumeric(ModNumeric),
342 RoundNumeric(RoundNumericBinary),
343 Eq(Eq),
344 NotEq(NotEq),
345 Lt(Lt),
346 Lte(Lte),
347 Gt(Gt),
348 Gte(Gte),
349 LikeEscape(LikeEscape),
350 IsLikeMatchCaseInsensitive(IsLikeMatchCaseInsensitive),
351 IsLikeMatchCaseSensitive(IsLikeMatchCaseSensitive),
352 IsRegexpMatchCaseSensitive(IsRegexpMatchCaseSensitive),
353 IsRegexpMatchCaseInsensitive(IsRegexpMatchCaseInsensitive),
354 ToCharTimestamp(ToCharTimestampFormat),
355 ToCharTimestampTz(ToCharTimestampTzFormat),
356 DateBinTimestamp(DateBinTimestamp),
357 DateBinTimestampTz(DateBinTimestampTz),
358 ExtractInterval(DatePartIntervalNumeric),
359 ExtractTime(DatePartTimeNumeric),
360 ExtractTimestamp(DatePartTimestampTimestampNumeric),
361 ExtractTimestampTz(DatePartTimestampTimestampTzNumeric),
362 ExtractDate(ExtractDateUnits),
363 DatePartInterval(DatePartIntervalF64),
364 DatePartTime(DatePartTimeF64),
365 DatePartTimestamp(DatePartTimestampTimestampF64),
366 DatePartTimestampTz(DatePartTimestampTimestampTzF64),
367 DateTruncTimestamp(DateTruncUnitsTimestamp),
368 DateTruncTimestampTz(DateTruncUnitsTimestampTz),
369 DateTruncInterval(DateTruncInterval),
370 TimezoneTimestampBinary(TimezoneTimestampBinary),
371 TimezoneTimestampTzBinary(TimezoneTimestampTzBinary),
372 TimezoneIntervalTimestampBinary(TimezoneIntervalTimestampBinary),
373 TimezoneIntervalTimestampTzBinary(TimezoneIntervalTimestampTzBinary),
374 TimezoneIntervalTimeBinary(TimezoneIntervalTimeBinary),
375 TimezoneOffset(TimezoneOffset),
376 TextConcat(TextConcatBinary),
377 JsonbGetInt64(JsonbGetInt64),
378 JsonbGetInt64Stringify(JsonbGetInt64Stringify),
379 JsonbGetString(JsonbGetString),
380 JsonbGetStringStringify(JsonbGetStringStringify),
381 JsonbGetPath(JsonbGetPath),
382 JsonbGetPathStringify(JsonbGetPathStringify),
383 JsonbContainsString(JsonbContainsString),
384 JsonbConcat(JsonbConcat),
385 JsonbContainsJsonb(JsonbContainsJsonb),
386 JsonbDeleteInt64(JsonbDeleteInt64),
387 JsonbDeleteString(JsonbDeleteString),
388 MapContainsKey(MapContainsKey),
389 MapGetValue(MapGetValue),
390 MapContainsAllKeys(MapContainsAllKeys),
391 MapContainsAnyKeys(MapContainsAnyKeys),
392 MapContainsMap(MapContainsMap),
393 ConvertFrom(ConvertFrom),
394 Left(Left),
395 Position(Position),
396 Strpos(Strpos),
397 Right(Right),
398 RepeatString(RepeatString),
399 Normalize(Normalize),
400 Trim(Trim),
401 TrimLeading(TrimLeading),
402 TrimTrailing(TrimTrailing),
403 EncodedBytesCharLength(EncodedBytesCharLength),
404 ListLengthMax(ListLengthMax),
405 ArrayContains(ArrayContains),
406 ArrayContainsArray(ArrayContainsArray),
407 ArrayContainsArrayRev(ArrayContainsArrayRev),
408 ArrayLength(ArrayLength),
409 ArrayLower(ArrayLower),
410 ArrayRemove(ArrayRemove),
411 ArrayUpper(ArrayUpper),
412 ArrayArrayConcat(ArrayArrayConcat),
413 ListListConcat(ListListConcat),
414 ListElementConcat(ListElementConcat),
415 ElementListConcat(ElementListConcat),
416 ListRemove(ListRemove),
417 ListContainsList(ListContainsList),
418 ListContainsListRev(ListContainsListRev),
419 DigestString(DigestString),
420 DigestBytes(DigestBytes),
421 MzRenderTypmod(MzRenderTypmod),
422 Encode(Encode),
423 Decode(Decode),
424 LogNumeric(LogBaseNumeric),
425 Power(Power),
426 PowerNumeric(PowerNumeric),
427 GetBit(GetBit),
428 GetByte(GetByte),
429 ConstantTimeEqBytes(ConstantTimeEqBytes),
430 ConstantTimeEqString(ConstantTimeEqString),
431 RangeContainsDate(RangeContainsDate),
432 RangeContainsDateRev(RangeContainsDateRev),
433 RangeContainsI32(RangeContainsI32),
434 RangeContainsI32Rev(RangeContainsI32Rev),
435 RangeContainsI64(RangeContainsI64),
436 RangeContainsI64Rev(RangeContainsI64Rev),
437 RangeContainsNumeric(RangeContainsNumeric),
438 RangeContainsNumericRev(RangeContainsNumericRev),
439 RangeContainsRange(RangeContainsRange),
440 RangeContainsRangeRev(RangeContainsRangeRev),
441 RangeContainsTimestamp(RangeContainsTimestamp),
442 RangeContainsTimestampRev(RangeContainsTimestampRev),
443 RangeContainsTimestampTz(RangeContainsTimestampTz),
444 RangeContainsTimestampTzRev(RangeContainsTimestampTzRev),
445 RangeOverlaps(RangeOverlaps),
446 RangeAfter(RangeAfter),
447 RangeBefore(RangeBefore),
448 RangeOverleft(RangeOverleft),
449 RangeOverright(RangeOverright),
450 RangeAdjacent(RangeAdjacent),
451 RangeUnion(RangeUnion),
452 RangeIntersection(RangeIntersection),
453 RangeDifference(RangeDifference),
454 UuidGenerateV5(UuidGenerateV5),
455 MzAclItemContainsPrivilege(MzAclItemContainsPrivilege),
456 ParseIdent(ParseIdent),
457 PrettySql(PrettySql),
458 RegexpReplace(RegexpReplace),
459 StartsWith(StartsWith),
460 }
461}
462
463#[cfg(test)]
464mod test {
465 use mz_expr_derive::sqlfunc;
466 use mz_repr::SqlScalarType;
467
468 use crate::EvalError;
469 use crate::scalar::func::binary::LazyBinaryFunc;
470
471 #[sqlfunc(sqlname = "INFALLIBLE", is_infix_op = true, test = true)]
472 #[allow(dead_code)]
473 fn infallible1(a: f32, b: f32) -> f32 {
474 a + b
475 }
476
477 #[sqlfunc(test = true)]
478 #[allow(dead_code)]
479 fn infallible2(a: Option<f32>, b: Option<f32>) -> f32 {
480 a.unwrap_or_default() + b.unwrap_or_default()
481 }
482
483 #[sqlfunc(test = true)]
484 #[allow(dead_code)]
485 fn infallible3(a: f32, b: f32) -> Option<f32> {
486 Some(a + b)
487 }
488
489 #[mz_ore::test]
490 fn elision_rules_infallible() {
491 assert_eq!(format!("{}", Infallible1), "INFALLIBLE");
492 assert!(Infallible1.propagates_nulls());
493 assert!(!Infallible1.introduces_nulls());
494
495 assert!(!Infallible2.propagates_nulls());
496 assert!(!Infallible2.introduces_nulls());
497
498 assert!(Infallible3.propagates_nulls());
499 assert!(Infallible3.introduces_nulls());
500 }
501
502 #[mz_ore::test]
503 fn output_types_infallible() {
504 assert_eq!(
505 Infallible1.output_sql_type(&[
506 SqlScalarType::Float32.nullable(true),
507 SqlScalarType::Float32.nullable(true)
508 ]),
509 SqlScalarType::Float32.nullable(true)
510 );
511 assert_eq!(
512 Infallible1.output_sql_type(&[
513 SqlScalarType::Float32.nullable(true),
514 SqlScalarType::Float32.nullable(false)
515 ]),
516 SqlScalarType::Float32.nullable(true)
517 );
518 assert_eq!(
519 Infallible1.output_sql_type(&[
520 SqlScalarType::Float32.nullable(false),
521 SqlScalarType::Float32.nullable(true)
522 ]),
523 SqlScalarType::Float32.nullable(true)
524 );
525 assert_eq!(
526 Infallible1.output_sql_type(&[
527 SqlScalarType::Float32.nullable(false),
528 SqlScalarType::Float32.nullable(false)
529 ]),
530 SqlScalarType::Float32.nullable(false)
531 );
532
533 assert_eq!(
534 Infallible2.output_sql_type(&[
535 SqlScalarType::Float32.nullable(true),
536 SqlScalarType::Float32.nullable(true)
537 ]),
538 SqlScalarType::Float32.nullable(false)
539 );
540 assert_eq!(
541 Infallible2.output_sql_type(&[
542 SqlScalarType::Float32.nullable(true),
543 SqlScalarType::Float32.nullable(false)
544 ]),
545 SqlScalarType::Float32.nullable(false)
546 );
547 assert_eq!(
548 Infallible2.output_sql_type(&[
549 SqlScalarType::Float32.nullable(false),
550 SqlScalarType::Float32.nullable(true)
551 ]),
552 SqlScalarType::Float32.nullable(false)
553 );
554 assert_eq!(
555 Infallible2.output_sql_type(&[
556 SqlScalarType::Float32.nullable(false),
557 SqlScalarType::Float32.nullable(false)
558 ]),
559 SqlScalarType::Float32.nullable(false)
560 );
561
562 assert_eq!(
563 Infallible3.output_sql_type(&[
564 SqlScalarType::Float32.nullable(true),
565 SqlScalarType::Float32.nullable(true)
566 ]),
567 SqlScalarType::Float32.nullable(true)
568 );
569 assert_eq!(
570 Infallible3.output_sql_type(&[
571 SqlScalarType::Float32.nullable(true),
572 SqlScalarType::Float32.nullable(false)
573 ]),
574 SqlScalarType::Float32.nullable(true)
575 );
576 assert_eq!(
577 Infallible3.output_sql_type(&[
578 SqlScalarType::Float32.nullable(false),
579 SqlScalarType::Float32.nullable(true)
580 ]),
581 SqlScalarType::Float32.nullable(true)
582 );
583 assert_eq!(
584 Infallible3.output_sql_type(&[
585 SqlScalarType::Float32.nullable(false),
586 SqlScalarType::Float32.nullable(false)
587 ]),
588 SqlScalarType::Float32.nullable(true)
589 );
590 }
591
592 #[sqlfunc(test = true)]
593 #[allow(dead_code)]
594 fn fallible1(a: f32, b: f32) -> Result<f32, EvalError> {
595 Ok(a + b)
596 }
597
598 #[sqlfunc(test = true)]
599 #[allow(dead_code)]
600 fn fallible2(a: Option<f32>, b: Option<f32>) -> Result<f32, EvalError> {
601 Ok(a.unwrap_or_default() + b.unwrap_or_default())
602 }
603
604 #[sqlfunc(test = true)]
605 #[allow(dead_code)]
606 fn fallible3(a: f32, b: f32) -> Result<Option<f32>, EvalError> {
607 Ok(Some(a + b))
608 }
609
610 #[mz_ore::test]
611 fn elision_rules_fallible() {
612 assert!(Fallible1.propagates_nulls());
613 assert!(!Fallible1.introduces_nulls());
614
615 assert!(!Fallible2.propagates_nulls());
616 assert!(!Fallible2.introduces_nulls());
617
618 assert!(Fallible3.propagates_nulls());
619 assert!(Fallible3.introduces_nulls());
620 }
621
622 #[mz_ore::test]
623 fn output_types_fallible() {
624 assert_eq!(
625 Fallible1.output_sql_type(&[
626 SqlScalarType::Float32.nullable(true),
627 SqlScalarType::Float32.nullable(true)
628 ]),
629 SqlScalarType::Float32.nullable(true)
630 );
631 assert_eq!(
632 Fallible1.output_sql_type(&[
633 SqlScalarType::Float32.nullable(true),
634 SqlScalarType::Float32.nullable(false)
635 ]),
636 SqlScalarType::Float32.nullable(true)
637 );
638 assert_eq!(
639 Fallible1.output_sql_type(&[
640 SqlScalarType::Float32.nullable(false),
641 SqlScalarType::Float32.nullable(true)
642 ]),
643 SqlScalarType::Float32.nullable(true)
644 );
645 assert_eq!(
646 Fallible1.output_sql_type(&[
647 SqlScalarType::Float32.nullable(false),
648 SqlScalarType::Float32.nullable(false)
649 ]),
650 SqlScalarType::Float32.nullable(false)
651 );
652
653 assert_eq!(
654 Fallible2.output_sql_type(&[
655 SqlScalarType::Float32.nullable(true),
656 SqlScalarType::Float32.nullable(true)
657 ]),
658 SqlScalarType::Float32.nullable(false)
659 );
660 assert_eq!(
661 Fallible2.output_sql_type(&[
662 SqlScalarType::Float32.nullable(true),
663 SqlScalarType::Float32.nullable(false)
664 ]),
665 SqlScalarType::Float32.nullable(false)
666 );
667 assert_eq!(
668 Fallible2.output_sql_type(&[
669 SqlScalarType::Float32.nullable(false),
670 SqlScalarType::Float32.nullable(true)
671 ]),
672 SqlScalarType::Float32.nullable(false)
673 );
674 assert_eq!(
675 Fallible2.output_sql_type(&[
676 SqlScalarType::Float32.nullable(false),
677 SqlScalarType::Float32.nullable(false)
678 ]),
679 SqlScalarType::Float32.nullable(false)
680 );
681
682 assert_eq!(
683 Fallible3.output_sql_type(&[
684 SqlScalarType::Float32.nullable(true),
685 SqlScalarType::Float32.nullable(true)
686 ]),
687 SqlScalarType::Float32.nullable(true)
688 );
689 assert_eq!(
690 Fallible3.output_sql_type(&[
691 SqlScalarType::Float32.nullable(true),
692 SqlScalarType::Float32.nullable(false)
693 ]),
694 SqlScalarType::Float32.nullable(true)
695 );
696 assert_eq!(
697 Fallible3.output_sql_type(&[
698 SqlScalarType::Float32.nullable(false),
699 SqlScalarType::Float32.nullable(true)
700 ]),
701 SqlScalarType::Float32.nullable(true)
702 );
703 assert_eq!(
704 Fallible3.output_sql_type(&[
705 SqlScalarType::Float32.nullable(false),
706 SqlScalarType::Float32.nullable(false)
707 ]),
708 SqlScalarType::Float32.nullable(true)
709 );
710 }
711}