mz_expr/scalar/
func.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9//
10// Portions of this file are derived from the PostgreSQL project. The original
11// source code is subject to the terms of the PostgreSQL license, a copy of
12// which can be found in the LICENSE file at the root of this repository.
13
14use std::borrow::Cow;
15use std::cmp::Ordering;
16use std::convert::{TryFrom, TryInto};
17use std::str::FromStr;
18use std::{fmt, iter, str};
19
20use ::encoding::DecoderTrap;
21use ::encoding::label::encoding_from_whatwg_label;
22use chrono::{DateTime, Duration, NaiveDate, NaiveDateTime, TimeZone, Timelike, Utc};
23use chrono_tz::{OffsetComponents, OffsetName, Tz};
24use dec::OrderedDecimal;
25use itertools::Itertools;
26use md5::{Digest, Md5};
27use mz_expr_derive::sqlfunc;
28use mz_lowertest::MzReflect;
29use mz_ore::cast::{self, CastFrom};
30use mz_ore::fmt::FormatBuffer;
31use mz_ore::lex::LexBuf;
32use mz_ore::option::OptionExt;
33use mz_ore::str::StrExt;
34use mz_pgrepr::Type;
35use mz_pgtz::timezone::{Timezone, TimezoneSpec};
36use mz_repr::adt::array::{Array, ArrayDimension};
37use mz_repr::adt::date::Date;
38use mz_repr::adt::interval::{Interval, RoundBehavior};
39use mz_repr::adt::jsonb::JsonbRef;
40use mz_repr::adt::mz_acl_item::{AclMode, MzAclItem};
41use mz_repr::adt::numeric::{self, Numeric};
42use mz_repr::adt::range::{Range, RangeOps};
43use mz_repr::adt::regex::Regex;
44use mz_repr::adt::timestamp::{CheckedTimestamp, TimestampLike};
45use mz_repr::{
46    ArrayRustType, Datum, DatumList, DatumMap, DatumType, ExcludeNull, Row, RowArena,
47    SqlColumnType, SqlScalarType, strconv,
48};
49use mz_sql_parser::ast::display::FormatMode;
50use mz_sql_pretty::{PrettyConfig, pretty_str};
51use num::traits::CheckedNeg;
52use serde::{Deserialize, Serialize};
53use sha1::Sha1;
54use sha2::{Sha224, Sha256, Sha384, Sha512};
55use subtle::ConstantTimeEq;
56
57use crate::func::binary::LazyBinaryFunc;
58use crate::scalar::func::format::DateTimeFormat;
59use crate::{EvalError, MirScalarExpr, like_pattern};
60
61#[macro_use]
62mod macros;
63mod binary;
64mod encoding;
65pub(crate) mod format;
66pub(crate) mod impls;
67mod unary;
68mod unmaterializable;
69mod variadic;
70
71pub use impls::*;
72pub use unary::{EagerUnaryFunc, LazyUnaryFunc, UnaryFunc};
73pub use unmaterializable::UnmaterializableFunc;
74pub use variadic::VariadicFunc;
75
76/// The maximum size of the result strings of certain string functions, such as `repeat` and `lpad`.
77/// Chosen to be the smallest number to keep our tests passing without changing. 100MiB is probably
78/// higher than what we want, but it's better than no limit.
79///
80/// Note: This number appears in our user-facing documentation in the function reference for every
81/// function where it applies.
82pub const MAX_STRING_FUNC_RESULT_BYTES: usize = 1024 * 1024 * 100;
83
84pub fn jsonb_stringify<'a>(a: Datum<'a>, temp_storage: &'a RowArena) -> Option<&'a str> {
85    match a {
86        Datum::JsonNull => None,
87        Datum::String(s) => Some(s),
88        _ => {
89            let s = cast_jsonb_to_string(JsonbRef::from_datum(a));
90            Some(temp_storage.push_string(s))
91        }
92    }
93}
94
95#[sqlfunc(
96    is_monotone = "(true, true)",
97    is_infix_op = true,
98    sqlname = "+",
99    propagates_nulls = true
100)]
101fn add_int16(a: i16, b: i16) -> Result<i16, EvalError> {
102    a.checked_add(b).ok_or(EvalError::NumericFieldOverflow)
103}
104
105#[sqlfunc(
106    is_monotone = "(true, true)",
107    is_infix_op = true,
108    sqlname = "+",
109    propagates_nulls = true
110)]
111fn add_int32(a: i32, b: i32) -> Result<i32, EvalError> {
112    a.checked_add(b).ok_or(EvalError::NumericFieldOverflow)
113}
114
115#[sqlfunc(
116    is_monotone = "(true, true)",
117    is_infix_op = true,
118    sqlname = "+",
119    propagates_nulls = true
120)]
121fn add_int64(a: i64, b: i64) -> Result<i64, EvalError> {
122    a.checked_add(b).ok_or(EvalError::NumericFieldOverflow)
123}
124
125#[sqlfunc(
126    is_monotone = "(true, true)",
127    is_infix_op = true,
128    sqlname = "+",
129    propagates_nulls = true
130)]
131fn add_uint16(a: u16, b: u16) -> Result<u16, EvalError> {
132    a.checked_add(b)
133        .ok_or_else(|| EvalError::UInt16OutOfRange(format!("{a} + {b}").into()))
134}
135
136#[sqlfunc(
137    is_monotone = "(true, true)",
138    is_infix_op = true,
139    sqlname = "+",
140    propagates_nulls = true
141)]
142fn add_uint32(a: u32, b: u32) -> Result<u32, EvalError> {
143    a.checked_add(b)
144        .ok_or_else(|| EvalError::UInt32OutOfRange(format!("{a} + {b}").into()))
145}
146
147#[sqlfunc(
148    is_monotone = "(true, true)",
149    is_infix_op = true,
150    sqlname = "+",
151    propagates_nulls = true
152)]
153fn add_uint64(a: u64, b: u64) -> Result<u64, EvalError> {
154    a.checked_add(b)
155        .ok_or_else(|| EvalError::UInt64OutOfRange(format!("{a} + {b}").into()))
156}
157
158#[sqlfunc(
159    is_monotone = "(true, true)",
160    is_infix_op = true,
161    sqlname = "+",
162    propagates_nulls = true
163)]
164fn add_float32(a: f32, b: f32) -> Result<f32, EvalError> {
165    let sum = a + b;
166    if sum.is_infinite() && !a.is_infinite() && !b.is_infinite() {
167        Err(EvalError::FloatOverflow)
168    } else {
169        Ok(sum)
170    }
171}
172
173#[sqlfunc(
174    is_monotone = "(true, true)",
175    is_infix_op = true,
176    sqlname = "+",
177    propagates_nulls = true
178)]
179fn add_float64(a: f64, b: f64) -> Result<f64, EvalError> {
180    let sum = a + b;
181    if sum.is_infinite() && !a.is_infinite() && !b.is_infinite() {
182        Err(EvalError::FloatOverflow)
183    } else {
184        Ok(sum)
185    }
186}
187
188#[sqlfunc(is_monotone = "(true, true)", is_infix_op = true, sqlname = "+")]
189fn add_timestamp_interval(
190    a: CheckedTimestamp<NaiveDateTime>,
191    b: Interval,
192) -> Result<CheckedTimestamp<NaiveDateTime>, EvalError> {
193    add_timestamplike_interval(a, b)
194}
195
196#[sqlfunc(is_monotone = "(true, true)", is_infix_op = true, sqlname = "+")]
197fn add_timestamp_tz_interval(
198    a: CheckedTimestamp<DateTime<Utc>>,
199    b: Interval,
200) -> Result<CheckedTimestamp<DateTime<Utc>>, EvalError> {
201    add_timestamplike_interval(a, b)
202}
203
204fn add_timestamplike_interval<T>(
205    a: CheckedTimestamp<T>,
206    b: Interval,
207) -> Result<CheckedTimestamp<T>, EvalError>
208where
209    T: TimestampLike,
210{
211    let dt = a.date_time();
212    let dt = add_timestamp_months(&dt, b.months)?;
213    let dt = dt
214        .checked_add_signed(b.duration_as_chrono())
215        .ok_or(EvalError::TimestampOutOfRange)?;
216    Ok(CheckedTimestamp::from_timestamplike(T::from_date_time(dt))?)
217}
218
219#[sqlfunc(is_monotone = "(true, true)", is_infix_op = true, sqlname = "-")]
220fn sub_timestamp_interval(
221    a: CheckedTimestamp<NaiveDateTime>,
222    b: Interval,
223) -> Result<CheckedTimestamp<NaiveDateTime>, EvalError> {
224    sub_timestamplike_interval(a, b)
225}
226
227#[sqlfunc(is_monotone = "(true, true)", is_infix_op = true, sqlname = "-")]
228fn sub_timestamp_tz_interval(
229    a: CheckedTimestamp<DateTime<Utc>>,
230    b: Interval,
231) -> Result<CheckedTimestamp<DateTime<Utc>>, EvalError> {
232    sub_timestamplike_interval(a, b)
233}
234
235fn sub_timestamplike_interval<T>(
236    a: CheckedTimestamp<T>,
237    b: Interval,
238) -> Result<CheckedTimestamp<T>, EvalError>
239where
240    T: TimestampLike,
241{
242    neg_interval_inner(b).and_then(|i| add_timestamplike_interval(a, i))
243}
244
245#[sqlfunc(is_monotone = "(true, true)", is_infix_op = true, sqlname = "+")]
246fn add_date_time(
247    date: Date,
248    time: chrono::NaiveTime,
249) -> Result<CheckedTimestamp<NaiveDateTime>, EvalError> {
250    let dt = NaiveDate::from(date)
251        .and_hms_nano_opt(time.hour(), time.minute(), time.second(), time.nanosecond())
252        .unwrap();
253    Ok(CheckedTimestamp::from_timestamplike(dt)?)
254}
255
256#[sqlfunc(is_monotone = "(true, true)", is_infix_op = true, sqlname = "+")]
257fn add_date_interval(
258    date: Date,
259    interval: Interval,
260) -> Result<CheckedTimestamp<NaiveDateTime>, EvalError> {
261    let dt = NaiveDate::from(date).and_hms_opt(0, 0, 0).unwrap();
262    let dt = add_timestamp_months(&dt, interval.months)?;
263    let dt = dt
264        .checked_add_signed(interval.duration_as_chrono())
265        .ok_or(EvalError::TimestampOutOfRange)?;
266    Ok(CheckedTimestamp::from_timestamplike(dt)?)
267}
268
269#[sqlfunc(
270    // <time> + <interval> wraps!
271    is_monotone = "(false, false)",
272    is_infix_op = true,
273    sqlname = "+",
274    propagates_nulls = true
275)]
276fn add_time_interval(time: chrono::NaiveTime, interval: Interval) -> chrono::NaiveTime {
277    let (t, _) = time.overflowing_add_signed(interval.duration_as_chrono());
278    t
279}
280
281#[sqlfunc(
282    is_monotone = "(true, false)",
283    output_type = "Numeric",
284    sqlname = "round",
285    propagates_nulls = true
286)]
287fn round_numeric_binary(a: OrderedDecimal<Numeric>, mut b: i32) -> Result<Numeric, EvalError> {
288    let mut a = a.0;
289    let mut cx = numeric::cx_datum();
290    let a_exp = a.exponent();
291    if a_exp > 0 && b > 0 || a_exp < 0 && -a_exp < b {
292        // This condition indicates:
293        // - a is a value without a decimal point, b is a positive number
294        // - a has a decimal point, but b is larger than its scale
295        // In both of these situations, right-pad the number with zeroes, which // is most easily done with rescale.
296
297        // Ensure rescale doesn't exceed max precision by putting a ceiling on
298        // b equal to the maximum remaining scale the value can support.
299        let max_remaining_scale = u32::from(numeric::NUMERIC_DATUM_MAX_PRECISION)
300            - (numeric::get_precision(&a) - numeric::get_scale(&a));
301        b = match i32::try_from(max_remaining_scale) {
302            Ok(max_remaining_scale) => std::cmp::min(b, max_remaining_scale),
303            Err(_) => b,
304        };
305        cx.rescale(&mut a, &numeric::Numeric::from(-b));
306    } else {
307        // To avoid invalid operations, clamp b to be within 1 more than the
308        // precision limit.
309        const MAX_P_LIMIT: i32 = 1 + cast::u8_to_i32(numeric::NUMERIC_DATUM_MAX_PRECISION);
310        b = std::cmp::min(MAX_P_LIMIT, b);
311        b = std::cmp::max(-MAX_P_LIMIT, b);
312        let mut b = numeric::Numeric::from(b);
313        // Shift by 10^b; this put digit to round to in the one's place.
314        cx.scaleb(&mut a, &b);
315        cx.round(&mut a);
316        // Negate exponent for shift back
317        cx.neg(&mut b);
318        cx.scaleb(&mut a, &b);
319    }
320
321    if cx.status().overflow() {
322        Err(EvalError::FloatOverflow)
323    } else if a.is_zero() {
324        // simpler than handling cases where exponent has gotten set to some
325        // value greater than the max precision, but all significant digits
326        // were rounded away.
327        Ok(numeric::Numeric::zero())
328    } else {
329        numeric::munge_numeric(&mut a).unwrap();
330        Ok(a)
331    }
332}
333
334#[sqlfunc(sqlname = "convert_from", propagates_nulls = true)]
335fn convert_from<'a>(a: &'a [u8], b: &str) -> Result<&'a str, EvalError> {
336    // Convert PostgreSQL-style encoding names[1] to WHATWG-style encoding names[2],
337    // which the encoding library uses[3].
338    // [1]: https://www.postgresql.org/docs/9.5/multibyte.html
339    // [2]: https://encoding.spec.whatwg.org/
340    // [3]: https://github.com/lifthrasiir/rust-encoding/blob/4e79c35ab6a351881a86dbff565c4db0085cc113/src/label.rs
341    let encoding_name = b.to_lowercase().replace('_', "-").into_boxed_str();
342
343    // Supporting other encodings is tracked by database-issues#797.
344    if encoding_from_whatwg_label(&encoding_name).map(|e| e.name()) != Some("utf-8") {
345        return Err(EvalError::InvalidEncodingName(encoding_name));
346    }
347
348    match str::from_utf8(a) {
349        Ok(from) => Ok(from),
350        Err(e) => Err(EvalError::InvalidByteSequence {
351            byte_sequence: e.to_string().into(),
352            encoding_name,
353        }),
354    }
355}
356
357#[sqlfunc]
358fn encode(bytes: &[u8], format: &str) -> Result<String, EvalError> {
359    let format = encoding::lookup_format(format)?;
360    Ok(format.encode(bytes))
361}
362
363#[sqlfunc]
364fn decode(string: &str, format: &str) -> Result<Vec<u8>, EvalError> {
365    let format = encoding::lookup_format(format)?;
366    let out = format.decode(string)?;
367    if out.len() > MAX_STRING_FUNC_RESULT_BYTES {
368        Err(EvalError::LengthTooLarge)
369    } else {
370        Ok(out)
371    }
372}
373
374#[sqlfunc(sqlname = "length", propagates_nulls = true)]
375fn encoded_bytes_char_length(a: &[u8], b: &str) -> Result<i32, EvalError> {
376    // Convert PostgreSQL-style encoding names[1] to WHATWG-style encoding names[2],
377    // which the encoding library uses[3].
378    // [1]: https://www.postgresql.org/docs/9.5/multibyte.html
379    // [2]: https://encoding.spec.whatwg.org/
380    // [3]: https://github.com/lifthrasiir/rust-encoding/blob/4e79c35ab6a351881a86dbff565c4db0085cc113/src/label.rs
381    let encoding_name = b.to_lowercase().replace('_', "-").into_boxed_str();
382
383    let enc = match encoding_from_whatwg_label(&encoding_name) {
384        Some(enc) => enc,
385        None => return Err(EvalError::InvalidEncodingName(encoding_name)),
386    };
387
388    let decoded_string = match enc.decode(a, DecoderTrap::Strict) {
389        Ok(s) => s,
390        Err(e) => {
391            return Err(EvalError::InvalidByteSequence {
392                byte_sequence: e.into(),
393                encoding_name,
394            });
395        }
396    };
397
398    let count = decoded_string.chars().count();
399    i32::try_from(count).map_err(|_| EvalError::Int32OutOfRange(count.to_string().into()))
400}
401
402// TODO(benesch): remove potentially dangerous usage of `as`.
403#[allow(clippy::as_conversions)]
404pub fn add_timestamp_months<T: TimestampLike>(
405    dt: &T,
406    mut months: i32,
407) -> Result<CheckedTimestamp<T>, EvalError> {
408    if months == 0 {
409        return Ok(CheckedTimestamp::from_timestamplike(dt.clone())?);
410    }
411
412    let (mut year, mut month, mut day) = (dt.year(), dt.month0() as i32, dt.day());
413    let years = months / 12;
414    year = year
415        .checked_add(years)
416        .ok_or(EvalError::TimestampOutOfRange)?;
417
418    months %= 12;
419    // positive modulus is easier to reason about
420    if months < 0 {
421        year -= 1;
422        months += 12;
423    }
424    year += (month + months) / 12;
425    month = (month + months) % 12;
426    // account for dt.month0
427    month += 1;
428
429    // handle going from January 31st to February by saturation
430    let mut new_d = chrono::NaiveDate::from_ymd_opt(year, month as u32, day);
431    while new_d.is_none() {
432        // If we have decremented day past 28 and are still receiving `None`,
433        // then we have generally overflowed `NaiveDate`.
434        if day < 28 {
435            return Err(EvalError::TimestampOutOfRange);
436        }
437        day -= 1;
438        new_d = chrono::NaiveDate::from_ymd_opt(year, month as u32, day);
439    }
440    let new_d = new_d.unwrap();
441
442    // Neither postgres nor mysql support leap seconds, so this should be safe.
443    //
444    // Both my testing and https://dba.stackexchange.com/a/105829 support the
445    // idea that we should ignore leap seconds
446    let new_dt = new_d
447        .and_hms_nano_opt(dt.hour(), dt.minute(), dt.second(), dt.nanosecond())
448        .unwrap();
449    let new_dt = T::from_date_time(new_dt);
450    Ok(CheckedTimestamp::from_timestamplike(new_dt)?)
451}
452
453#[sqlfunc(
454    is_monotone = "(true, true)",
455    is_infix_op = true,
456    sqlname = "+",
457    propagates_nulls = true
458)]
459fn add_numeric(
460    a: OrderedDecimal<Numeric>,
461    b: OrderedDecimal<Numeric>,
462) -> Result<Numeric, EvalError> {
463    let mut cx = numeric::cx_datum();
464    let mut a = a.0;
465    cx.add(&mut a, &b.0);
466    if cx.status().overflow() {
467        Err(EvalError::FloatOverflow)
468    } else {
469        Ok(a)
470    }
471}
472
473#[sqlfunc(
474    is_monotone = "(true, true)",
475    is_infix_op = true,
476    sqlname = "+",
477    propagates_nulls = true
478)]
479fn add_interval(a: Interval, b: Interval) -> Result<Interval, EvalError> {
480    a.checked_add(&b)
481        .ok_or_else(|| EvalError::IntervalOutOfRange(format!("{a} + {b}").into()))
482}
483
484#[sqlfunc(is_infix_op = true, sqlname = "&", propagates_nulls = true)]
485fn bit_and_int16(a: i16, b: i16) -> i16 {
486    a & b
487}
488
489#[sqlfunc(is_infix_op = true, sqlname = "&", propagates_nulls = true)]
490fn bit_and_int32(a: i32, b: i32) -> i32 {
491    a & b
492}
493
494#[sqlfunc(is_infix_op = true, sqlname = "&", propagates_nulls = true)]
495fn bit_and_int64(a: i64, b: i64) -> i64 {
496    a & b
497}
498
499#[sqlfunc(is_infix_op = true, sqlname = "&", propagates_nulls = true)]
500fn bit_and_uint16(a: u16, b: u16) -> u16 {
501    a & b
502}
503
504#[sqlfunc(is_infix_op = true, sqlname = "&", propagates_nulls = true)]
505fn bit_and_uint32(a: u32, b: u32) -> u32 {
506    a & b
507}
508
509#[sqlfunc(is_infix_op = true, sqlname = "&", propagates_nulls = true)]
510fn bit_and_uint64(a: u64, b: u64) -> u64 {
511    a & b
512}
513
514#[sqlfunc(is_infix_op = true, sqlname = "|", propagates_nulls = true)]
515fn bit_or_int16(a: i16, b: i16) -> i16 {
516    a | b
517}
518
519#[sqlfunc(is_infix_op = true, sqlname = "|", propagates_nulls = true)]
520fn bit_or_int32(a: i32, b: i32) -> i32 {
521    a | b
522}
523
524#[sqlfunc(is_infix_op = true, sqlname = "|", propagates_nulls = true)]
525fn bit_or_int64(a: i64, b: i64) -> i64 {
526    a | b
527}
528
529#[sqlfunc(is_infix_op = true, sqlname = "|", propagates_nulls = true)]
530fn bit_or_uint16(a: u16, b: u16) -> u16 {
531    a | b
532}
533
534#[sqlfunc(is_infix_op = true, sqlname = "|", propagates_nulls = true)]
535fn bit_or_uint32(a: u32, b: u32) -> u32 {
536    a | b
537}
538
539#[sqlfunc(is_infix_op = true, sqlname = "|", propagates_nulls = true)]
540fn bit_or_uint64(a: u64, b: u64) -> u64 {
541    a | b
542}
543
544#[sqlfunc(is_infix_op = true, sqlname = "#", propagates_nulls = true)]
545fn bit_xor_int16(a: i16, b: i16) -> i16 {
546    a ^ b
547}
548
549#[sqlfunc(is_infix_op = true, sqlname = "#", propagates_nulls = true)]
550fn bit_xor_int32(a: i32, b: i32) -> i32 {
551    a ^ b
552}
553
554#[sqlfunc(is_infix_op = true, sqlname = "#", propagates_nulls = true)]
555fn bit_xor_int64(a: i64, b: i64) -> i64 {
556    a ^ b
557}
558
559#[sqlfunc(is_infix_op = true, sqlname = "#", propagates_nulls = true)]
560fn bit_xor_uint16(a: u16, b: u16) -> u16 {
561    a ^ b
562}
563
564#[sqlfunc(is_infix_op = true, sqlname = "#", propagates_nulls = true)]
565fn bit_xor_uint32(a: u32, b: u32) -> u32 {
566    a ^ b
567}
568
569#[sqlfunc(is_infix_op = true, sqlname = "#", propagates_nulls = true)]
570fn bit_xor_uint64(a: u64, b: u64) -> u64 {
571    a ^ b
572}
573
574#[sqlfunc(is_infix_op = true, sqlname = "<<", propagates_nulls = true)]
575// TODO(benesch): remove potentially dangerous usage of `as`.
576#[allow(clippy::as_conversions)]
577fn bit_shift_left_int16(a: i16, b: i32) -> i16 {
578    // widen to i32 and then cast back to i16 in order emulate the C promotion rules used in by Postgres
579    // when the rhs in the 16-31 range, e.g. (1 << 17 should evaluate to 0)
580    // see https://github.com/postgres/postgres/blob/REL_14_STABLE/src/backend/utils/adt/int.c#L1460-L1476
581    let lhs: i32 = a as i32;
582    let rhs: u32 = b as u32;
583    lhs.wrapping_shl(rhs) as i16
584}
585
586#[sqlfunc(is_infix_op = true, sqlname = "<<", propagates_nulls = true)]
587// TODO(benesch): remove potentially dangerous usage of `as`.
588#[allow(clippy::as_conversions)]
589fn bit_shift_left_int32(lhs: i32, rhs: i32) -> i32 {
590    let rhs = rhs as u32;
591    lhs.wrapping_shl(rhs)
592}
593
594#[sqlfunc(is_infix_op = true, sqlname = "<<", propagates_nulls = true)]
595// TODO(benesch): remove potentially dangerous usage of `as`.
596#[allow(clippy::as_conversions)]
597fn bit_shift_left_int64(lhs: i64, rhs: i32) -> i64 {
598    let rhs = rhs as u32;
599    lhs.wrapping_shl(rhs)
600}
601
602#[sqlfunc(is_infix_op = true, sqlname = "<<", propagates_nulls = true)]
603// TODO(benesch): remove potentially dangerous usage of `as`.
604#[allow(clippy::as_conversions)]
605fn bit_shift_left_uint16(a: u16, b: u32) -> u16 {
606    // widen to u32 and then cast back to u16 in order emulate the C promotion rules used in by Postgres
607    // when the rhs in the 16-31 range, e.g. (1 << 17 should evaluate to 0)
608    // see https://github.com/postgres/postgres/blob/REL_14_STABLE/src/backend/utils/adt/int.c#L1460-L1476
609    let lhs: u32 = a as u32;
610    let rhs: u32 = b;
611    lhs.wrapping_shl(rhs) as u16
612}
613
614#[sqlfunc(is_infix_op = true, sqlname = "<<", propagates_nulls = true)]
615fn bit_shift_left_uint32(a: u32, b: u32) -> u32 {
616    let lhs = a;
617    let rhs = b;
618    lhs.wrapping_shl(rhs)
619}
620
621#[sqlfunc(
622    output_type = "u64",
623    is_infix_op = true,
624    sqlname = "<<",
625    propagates_nulls = true
626)]
627fn bit_shift_left_uint64(lhs: u64, rhs: u32) -> u64 {
628    lhs.wrapping_shl(rhs)
629}
630
631#[sqlfunc(is_infix_op = true, sqlname = ">>", propagates_nulls = true)]
632// TODO(benesch): remove potentially dangerous usage of `as`.
633#[allow(clippy::as_conversions)]
634fn bit_shift_right_int16(lhs: i16, rhs: i32) -> i16 {
635    // widen to i32 and then cast back to i16 in order emulate the C promotion rules used in by Postgres
636    // when the rhs in the 16-31 range, e.g. (-32767 >> 17 should evaluate to -1)
637    // see https://github.com/postgres/postgres/blob/REL_14_STABLE/src/backend/utils/adt/int.c#L1460-L1476
638    let lhs = lhs as i32;
639    let rhs = rhs as u32;
640    lhs.wrapping_shr(rhs) as i16
641}
642
643#[sqlfunc(is_infix_op = true, sqlname = ">>", propagates_nulls = true)]
644// TODO(benesch): remove potentially dangerous usage of `as`.
645#[allow(clippy::as_conversions)]
646fn bit_shift_right_int32(lhs: i32, rhs: i32) -> i32 {
647    lhs.wrapping_shr(rhs as u32)
648}
649
650#[sqlfunc(is_infix_op = true, sqlname = ">>", propagates_nulls = true)]
651// TODO(benesch): remove potentially dangerous usage of `as`.
652#[allow(clippy::as_conversions)]
653fn bit_shift_right_int64(lhs: i64, rhs: i32) -> i64 {
654    lhs.wrapping_shr(rhs as u32)
655}
656
657#[sqlfunc(is_infix_op = true, sqlname = ">>", propagates_nulls = true)]
658// TODO(benesch): remove potentially dangerous usage of `as`.
659#[allow(clippy::as_conversions)]
660fn bit_shift_right_uint16(lhs: u16, rhs: u32) -> u16 {
661    // widen to u32 and then cast back to u16 in order emulate the C promotion rules used in by Postgres
662    // when the rhs in the 16-31 range, e.g. (-32767 >> 17 should evaluate to -1)
663    // see https://github.com/postgres/postgres/blob/REL_14_STABLE/src/backend/utils/adt/int.c#L1460-L1476
664    let lhs = lhs as u32;
665    lhs.wrapping_shr(rhs) as u16
666}
667
668#[sqlfunc(is_infix_op = true, sqlname = ">>", propagates_nulls = true)]
669fn bit_shift_right_uint32(lhs: u32, rhs: u32) -> u32 {
670    lhs.wrapping_shr(rhs)
671}
672
673#[sqlfunc(is_infix_op = true, sqlname = ">>", propagates_nulls = true)]
674fn bit_shift_right_uint64(lhs: u64, rhs: u32) -> u64 {
675    lhs.wrapping_shr(rhs)
676}
677
678#[sqlfunc(
679    is_monotone = "(true, true)",
680    is_infix_op = true,
681    sqlname = "-",
682    propagates_nulls = true
683)]
684fn sub_int16(a: i16, b: i16) -> Result<i16, EvalError> {
685    a.checked_sub(b).ok_or(EvalError::NumericFieldOverflow)
686}
687
688#[sqlfunc(
689    is_monotone = "(true, true)",
690    is_infix_op = true,
691    sqlname = "-",
692    propagates_nulls = true
693)]
694fn sub_int32(a: i32, b: i32) -> Result<i32, EvalError> {
695    a.checked_sub(b).ok_or(EvalError::NumericFieldOverflow)
696}
697
698#[sqlfunc(
699    is_monotone = "(true, true)",
700    is_infix_op = true,
701    sqlname = "-",
702    propagates_nulls = true
703)]
704fn sub_int64(a: i64, b: i64) -> Result<i64, EvalError> {
705    a.checked_sub(b).ok_or(EvalError::NumericFieldOverflow)
706}
707
708#[sqlfunc(
709    is_monotone = "(true, true)",
710    is_infix_op = true,
711    sqlname = "-",
712    propagates_nulls = true
713)]
714fn sub_uint16(a: u16, b: u16) -> Result<u16, EvalError> {
715    a.checked_sub(b)
716        .ok_or_else(|| EvalError::UInt16OutOfRange(format!("{a} - {b}").into()))
717}
718
719#[sqlfunc(
720    is_monotone = "(true, true)",
721    is_infix_op = true,
722    sqlname = "-",
723    propagates_nulls = true
724)]
725fn sub_uint32(a: u32, b: u32) -> Result<u32, EvalError> {
726    a.checked_sub(b)
727        .ok_or_else(|| EvalError::UInt32OutOfRange(format!("{a} - {b}").into()))
728}
729
730#[sqlfunc(
731    is_monotone = "(true, true)",
732    is_infix_op = true,
733    sqlname = "-",
734    propagates_nulls = true
735)]
736fn sub_uint64(a: u64, b: u64) -> Result<u64, EvalError> {
737    a.checked_sub(b)
738        .ok_or_else(|| EvalError::UInt64OutOfRange(format!("{a} - {b}").into()))
739}
740
741#[sqlfunc(
742    is_monotone = "(true, true)",
743    is_infix_op = true,
744    sqlname = "-",
745    propagates_nulls = true
746)]
747fn sub_float32(a: f32, b: f32) -> Result<f32, EvalError> {
748    let difference = a - b;
749    if difference.is_infinite() && !a.is_infinite() && !b.is_infinite() {
750        Err(EvalError::FloatOverflow)
751    } else {
752        Ok(difference)
753    }
754}
755
756#[sqlfunc(
757    is_monotone = "(true, true)",
758    is_infix_op = true,
759    sqlname = "-",
760    propagates_nulls = true
761)]
762fn sub_float64(a: f64, b: f64) -> Result<f64, EvalError> {
763    let difference = a - b;
764    if difference.is_infinite() && !a.is_infinite() && !b.is_infinite() {
765        Err(EvalError::FloatOverflow)
766    } else {
767        Ok(difference)
768    }
769}
770
771#[sqlfunc(
772    is_monotone = "(true, true)",
773    is_infix_op = true,
774    sqlname = "-",
775    propagates_nulls = true
776)]
777fn sub_numeric(
778    a: OrderedDecimal<Numeric>,
779    b: OrderedDecimal<Numeric>,
780) -> Result<Numeric, EvalError> {
781    let mut cx = numeric::cx_datum();
782    let mut a = a.0;
783    cx.sub(&mut a, &b.0);
784    if cx.status().overflow() {
785        Err(EvalError::FloatOverflow)
786    } else {
787        Ok(a)
788    }
789}
790
791#[sqlfunc(
792    is_monotone = "(true, true)",
793    output_type = "Interval",
794    sqlname = "age",
795    propagates_nulls = true
796)]
797fn age_timestamp(
798    a: CheckedTimestamp<chrono::NaiveDateTime>,
799    b: CheckedTimestamp<chrono::NaiveDateTime>,
800) -> Result<Interval, EvalError> {
801    Ok(a.age(&b)?)
802}
803
804#[sqlfunc(is_monotone = "(true, true)", sqlname = "age", propagates_nulls = true)]
805fn age_timestamp_tz(
806    a: CheckedTimestamp<chrono::DateTime<Utc>>,
807    b: CheckedTimestamp<chrono::DateTime<Utc>>,
808) -> Result<Interval, EvalError> {
809    Ok(a.age(&b)?)
810}
811
812#[sqlfunc(is_monotone = "(true, true)", is_infix_op = true, sqlname = "-")]
813fn sub_timestamp(
814    a: CheckedTimestamp<NaiveDateTime>,
815    b: CheckedTimestamp<NaiveDateTime>,
816) -> Result<Interval, EvalError> {
817    Interval::from_chrono_duration(a - b)
818        .map_err(|e| EvalError::IntervalOutOfRange(e.to_string().into()))
819}
820
821#[sqlfunc(is_monotone = "(true, true)", is_infix_op = true, sqlname = "-")]
822fn sub_timestamp_tz(
823    a: CheckedTimestamp<chrono::DateTime<Utc>>,
824    b: CheckedTimestamp<chrono::DateTime<Utc>>,
825) -> Result<Interval, EvalError> {
826    Interval::from_chrono_duration(a - b)
827        .map_err(|e| EvalError::IntervalOutOfRange(e.to_string().into()))
828}
829
830#[sqlfunc(
831    is_monotone = "(true, true)",
832    is_infix_op = true,
833    sqlname = "-",
834    propagates_nulls = true
835)]
836fn sub_date(a: Date, b: Date) -> i32 {
837    a - b
838}
839
840#[sqlfunc(is_monotone = "(true, true)", is_infix_op = true, sqlname = "-")]
841fn sub_time(a: chrono::NaiveTime, b: chrono::NaiveTime) -> Result<Interval, EvalError> {
842    Interval::from_chrono_duration(a - b)
843        .map_err(|e| EvalError::IntervalOutOfRange(e.to_string().into()))
844}
845
846#[sqlfunc(
847    is_monotone = "(true, true)",
848    output_type = "Interval",
849    is_infix_op = true,
850    sqlname = "-",
851    propagates_nulls = true
852)]
853fn sub_interval(a: Interval, b: Interval) -> Result<Interval, EvalError> {
854    b.checked_neg()
855        .and_then(|b| b.checked_add(&a))
856        .ok_or_else(|| EvalError::IntervalOutOfRange(format!("{a} - {b}").into()))
857}
858
859#[sqlfunc(
860    is_monotone = "(true, true)",
861    is_infix_op = true,
862    sqlname = "-",
863    propagates_nulls = true
864)]
865fn sub_date_interval(
866    date: Date,
867    interval: Interval,
868) -> Result<CheckedTimestamp<NaiveDateTime>, EvalError> {
869    let dt = NaiveDate::from(date).and_hms_opt(0, 0, 0).unwrap();
870    let dt = interval
871        .months
872        .checked_neg()
873        .ok_or_else(|| EvalError::IntervalOutOfRange(interval.months.to_string().into()))
874        .and_then(|months| add_timestamp_months(&dt, months))?;
875    let dt = dt
876        .checked_sub_signed(interval.duration_as_chrono())
877        .ok_or(EvalError::TimestampOutOfRange)?;
878    Ok(dt.try_into()?)
879}
880
881#[sqlfunc(
882    is_monotone = "(false, false)",
883    is_infix_op = true,
884    sqlname = "-",
885    propagates_nulls = true
886)]
887fn sub_time_interval(time: chrono::NaiveTime, interval: Interval) -> chrono::NaiveTime {
888    let (t, _) = time.overflowing_sub_signed(interval.duration_as_chrono());
889    t
890}
891
892#[sqlfunc(
893    is_monotone = "(true, true)",
894    is_infix_op = true,
895    sqlname = "*",
896    propagates_nulls = true
897)]
898fn mul_int16(a: i16, b: i16) -> Result<i16, EvalError> {
899    a.checked_mul(b).ok_or(EvalError::NumericFieldOverflow)
900}
901
902#[sqlfunc(
903    is_monotone = "(true, true)",
904    is_infix_op = true,
905    sqlname = "*",
906    propagates_nulls = true
907)]
908fn mul_int32(a: i32, b: i32) -> Result<i32, EvalError> {
909    a.checked_mul(b).ok_or(EvalError::NumericFieldOverflow)
910}
911
912#[sqlfunc(
913    is_monotone = "(true, true)",
914    is_infix_op = true,
915    sqlname = "*",
916    propagates_nulls = true
917)]
918fn mul_int64(a: i64, b: i64) -> Result<i64, EvalError> {
919    a.checked_mul(b).ok_or(EvalError::NumericFieldOverflow)
920}
921
922#[sqlfunc(
923    is_monotone = "(true, true)",
924    is_infix_op = true,
925    sqlname = "*",
926    propagates_nulls = true
927)]
928fn mul_uint16(a: u16, b: u16) -> Result<u16, EvalError> {
929    a.checked_mul(b)
930        .ok_or_else(|| EvalError::UInt16OutOfRange(format!("{a} * {b}").into()))
931}
932
933#[sqlfunc(
934    is_monotone = "(true, true)",
935    is_infix_op = true,
936    sqlname = "*",
937    propagates_nulls = true
938)]
939fn mul_uint32(a: u32, b: u32) -> Result<u32, EvalError> {
940    a.checked_mul(b)
941        .ok_or_else(|| EvalError::UInt32OutOfRange(format!("{a} * {b}").into()))
942}
943
944#[sqlfunc(
945    is_monotone = "(true, true)",
946    is_infix_op = true,
947    sqlname = "*",
948    propagates_nulls = true
949)]
950fn mul_uint64(a: u64, b: u64) -> Result<u64, EvalError> {
951    a.checked_mul(b)
952        .ok_or_else(|| EvalError::UInt64OutOfRange(format!("{a} * {b}").into()))
953}
954
955#[sqlfunc(
956    is_monotone = (true, true),
957    is_infix_op = true,
958    sqlname = "*",
959    propagates_nulls = true
960)]
961fn mul_float32(a: f32, b: f32) -> Result<f32, EvalError> {
962    let product = a * b;
963    if product.is_infinite() && !a.is_infinite() && !b.is_infinite() {
964        Err(EvalError::FloatOverflow)
965    } else if product == 0.0f32 && a != 0.0f32 && b != 0.0f32 {
966        Err(EvalError::FloatUnderflow)
967    } else {
968        Ok(product)
969    }
970}
971
972#[sqlfunc(
973    is_monotone = "(true, true)",
974    is_infix_op = true,
975    sqlname = "*",
976    propagates_nulls = true
977)]
978fn mul_float64(a: f64, b: f64) -> Result<f64, EvalError> {
979    let product = a * b;
980    if product.is_infinite() && !a.is_infinite() && !b.is_infinite() {
981        Err(EvalError::FloatOverflow)
982    } else if product == 0.0f64 && a != 0.0f64 && b != 0.0f64 {
983        Err(EvalError::FloatUnderflow)
984    } else {
985        Ok(product)
986    }
987}
988
989#[sqlfunc(
990    is_monotone = "(true, true)",
991    is_infix_op = true,
992    sqlname = "*",
993    propagates_nulls = true
994)]
995fn mul_numeric(mut a: Numeric, b: Numeric) -> Result<Numeric, EvalError> {
996    let mut cx = numeric::cx_datum();
997    cx.mul(&mut a, &b);
998    let cx_status = cx.status();
999    if cx_status.overflow() {
1000        Err(EvalError::FloatOverflow)
1001    } else if cx_status.subnormal() {
1002        Err(EvalError::FloatUnderflow)
1003    } else {
1004        numeric::munge_numeric(&mut a).unwrap();
1005        Ok(a)
1006    }
1007}
1008
1009#[sqlfunc(
1010    is_monotone = "(false, false)",
1011    is_infix_op = true,
1012    sqlname = "*",
1013    propagates_nulls = true
1014)]
1015fn mul_interval(a: Interval, b: f64) -> Result<Interval, EvalError> {
1016    a.checked_mul(b)
1017        .ok_or_else(|| EvalError::IntervalOutOfRange(format!("{a} * {b}").into()))
1018}
1019
1020#[sqlfunc(
1021    is_monotone = "(true, false)",
1022    is_infix_op = true,
1023    sqlname = "/",
1024    propagates_nulls = true
1025)]
1026fn div_int16(a: i16, b: i16) -> Result<i16, EvalError> {
1027    if b == 0 {
1028        Err(EvalError::DivisionByZero)
1029    } else {
1030        a.checked_div(b)
1031            .ok_or_else(|| EvalError::Int16OutOfRange(format!("{a} / {b}").into()))
1032    }
1033}
1034
1035#[sqlfunc(
1036    is_monotone = "(true, false)",
1037    is_infix_op = true,
1038    sqlname = "/",
1039    propagates_nulls = true
1040)]
1041fn div_int32(a: i32, b: i32) -> Result<i32, EvalError> {
1042    if b == 0 {
1043        Err(EvalError::DivisionByZero)
1044    } else {
1045        a.checked_div(b)
1046            .ok_or_else(|| EvalError::Int32OutOfRange(format!("{a} / {b}").into()))
1047    }
1048}
1049
1050#[sqlfunc(
1051    is_monotone = "(true, false)",
1052    is_infix_op = true,
1053    sqlname = "/",
1054    propagates_nulls = true
1055)]
1056fn div_int64(a: i64, b: i64) -> Result<i64, EvalError> {
1057    if b == 0 {
1058        Err(EvalError::DivisionByZero)
1059    } else {
1060        a.checked_div(b)
1061            .ok_or_else(|| EvalError::Int64OutOfRange(format!("{a} / {b}").into()))
1062    }
1063}
1064
1065#[sqlfunc(
1066    is_monotone = "(true, false)",
1067    is_infix_op = true,
1068    sqlname = "/",
1069    propagates_nulls = true
1070)]
1071fn div_uint16(a: u16, b: u16) -> Result<u16, EvalError> {
1072    if b == 0 {
1073        Err(EvalError::DivisionByZero)
1074    } else {
1075        Ok(a / b)
1076    }
1077}
1078
1079#[sqlfunc(
1080    is_monotone = "(true, false)",
1081    is_infix_op = true,
1082    sqlname = "/",
1083    propagates_nulls = true
1084)]
1085fn div_uint32(a: u32, b: u32) -> Result<u32, EvalError> {
1086    if b == 0 {
1087        Err(EvalError::DivisionByZero)
1088    } else {
1089        Ok(a / b)
1090    }
1091}
1092
1093#[sqlfunc(
1094    is_monotone = "(true, false)",
1095    is_infix_op = true,
1096    sqlname = "/",
1097    propagates_nulls = true
1098)]
1099fn div_uint64(a: u64, b: u64) -> Result<u64, EvalError> {
1100    if b == 0 {
1101        Err(EvalError::DivisionByZero)
1102    } else {
1103        Ok(a / b)
1104    }
1105}
1106
1107#[sqlfunc(
1108    is_monotone = "(true, false)",
1109    is_infix_op = true,
1110    sqlname = "/",
1111    propagates_nulls = true
1112)]
1113fn div_float32(a: f32, b: f32) -> Result<f32, EvalError> {
1114    if b == 0.0f32 && !a.is_nan() {
1115        Err(EvalError::DivisionByZero)
1116    } else {
1117        let quotient = a / b;
1118        if quotient.is_infinite() && !a.is_infinite() {
1119            Err(EvalError::FloatOverflow)
1120        } else if quotient == 0.0f32 && a != 0.0f32 && !b.is_infinite() {
1121            Err(EvalError::FloatUnderflow)
1122        } else {
1123            Ok(quotient)
1124        }
1125    }
1126}
1127
1128#[sqlfunc(
1129    is_monotone = "(true, false)",
1130    is_infix_op = true,
1131    sqlname = "/",
1132    propagates_nulls = true
1133)]
1134fn div_float64(a: f64, b: f64) -> Result<f64, EvalError> {
1135    if b == 0.0f64 && !a.is_nan() {
1136        Err(EvalError::DivisionByZero)
1137    } else {
1138        let quotient = a / b;
1139        if quotient.is_infinite() && !a.is_infinite() {
1140            Err(EvalError::FloatOverflow)
1141        } else if quotient == 0.0f64 && a != 0.0f64 && !b.is_infinite() {
1142            Err(EvalError::FloatUnderflow)
1143        } else {
1144            Ok(quotient)
1145        }
1146    }
1147}
1148
1149#[sqlfunc(
1150    is_monotone = "(true, false)",
1151    is_infix_op = true,
1152    sqlname = "/",
1153    propagates_nulls = true
1154)]
1155fn div_numeric(mut a: Numeric, b: Numeric) -> Result<Numeric, EvalError> {
1156    let mut cx = numeric::cx_datum();
1157
1158    cx.div(&mut a, &b);
1159    let cx_status = cx.status();
1160
1161    // checking the status for division by zero errors is insufficient because
1162    // the underlying library treats 0/0 as undefined and not division by zero.
1163    if b.is_zero() {
1164        Err(EvalError::DivisionByZero)
1165    } else if cx_status.overflow() {
1166        Err(EvalError::FloatOverflow)
1167    } else if cx_status.subnormal() {
1168        Err(EvalError::FloatUnderflow)
1169    } else {
1170        numeric::munge_numeric(&mut a).unwrap();
1171        Ok(a)
1172    }
1173}
1174
1175#[sqlfunc(
1176    is_monotone = "(false, false)",
1177    is_infix_op = true,
1178    sqlname = "/",
1179    propagates_nulls = true
1180)]
1181fn div_interval(a: Interval, b: f64) -> Result<Interval, EvalError> {
1182    if b == 0.0 {
1183        Err(EvalError::DivisionByZero)
1184    } else {
1185        a.checked_div(b)
1186            .ok_or_else(|| EvalError::IntervalOutOfRange(format!("{a} / {b}").into()))
1187    }
1188}
1189
1190#[sqlfunc(is_infix_op = true, sqlname = "%", propagates_nulls = true)]
1191fn mod_int16(a: i16, b: i16) -> Result<i16, EvalError> {
1192    if b == 0 {
1193        Err(EvalError::DivisionByZero)
1194    } else {
1195        Ok(a.checked_rem(b).unwrap_or(0))
1196    }
1197}
1198
1199#[sqlfunc(is_infix_op = true, sqlname = "%", propagates_nulls = true)]
1200fn mod_int32(a: i32, b: i32) -> Result<i32, EvalError> {
1201    if b == 0 {
1202        Err(EvalError::DivisionByZero)
1203    } else {
1204        Ok(a.checked_rem(b).unwrap_or(0))
1205    }
1206}
1207
1208#[sqlfunc(is_infix_op = true, sqlname = "%", propagates_nulls = true)]
1209fn mod_int64(a: i64, b: i64) -> Result<i64, EvalError> {
1210    if b == 0 {
1211        Err(EvalError::DivisionByZero)
1212    } else {
1213        Ok(a.checked_rem(b).unwrap_or(0))
1214    }
1215}
1216
1217#[sqlfunc(is_infix_op = true, sqlname = "%", propagates_nulls = true)]
1218fn mod_uint16(a: u16, b: u16) -> Result<u16, EvalError> {
1219    if b == 0 {
1220        Err(EvalError::DivisionByZero)
1221    } else {
1222        Ok(a % b)
1223    }
1224}
1225
1226#[sqlfunc(is_infix_op = true, sqlname = "%", propagates_nulls = true)]
1227fn mod_uint32(a: u32, b: u32) -> Result<u32, EvalError> {
1228    if b == 0 {
1229        Err(EvalError::DivisionByZero)
1230    } else {
1231        Ok(a % b)
1232    }
1233}
1234
1235#[sqlfunc(is_infix_op = true, sqlname = "%", propagates_nulls = true)]
1236fn mod_uint64(a: u64, b: u64) -> Result<u64, EvalError> {
1237    if b == 0 {
1238        Err(EvalError::DivisionByZero)
1239    } else {
1240        Ok(a % b)
1241    }
1242}
1243
1244#[sqlfunc(is_infix_op = true, sqlname = "%", propagates_nulls = true)]
1245fn mod_float32(a: f32, b: f32) -> Result<f32, EvalError> {
1246    if b == 0.0 {
1247        Err(EvalError::DivisionByZero)
1248    } else {
1249        Ok(a % b)
1250    }
1251}
1252
1253#[sqlfunc(is_infix_op = true, sqlname = "%", propagates_nulls = true)]
1254fn mod_float64(a: f64, b: f64) -> Result<f64, EvalError> {
1255    if b == 0.0 {
1256        Err(EvalError::DivisionByZero)
1257    } else {
1258        Ok(a % b)
1259    }
1260}
1261
1262#[sqlfunc(is_infix_op = true, sqlname = "%", propagates_nulls = true)]
1263fn mod_numeric(mut a: Numeric, b: Numeric) -> Result<Numeric, EvalError> {
1264    if b.is_zero() {
1265        return Err(EvalError::DivisionByZero);
1266    }
1267    let mut cx = numeric::cx_datum();
1268    // Postgres does _not_ use IEEE 754-style remainder
1269    cx.rem(&mut a, &b);
1270    numeric::munge_numeric(&mut a).unwrap();
1271    Ok(a)
1272}
1273
1274fn neg_interval_inner(a: Interval) -> Result<Interval, EvalError> {
1275    a.checked_neg()
1276        .ok_or_else(|| EvalError::IntervalOutOfRange(a.to_string().into()))
1277}
1278
1279fn log_guard_numeric(val: &Numeric, function_name: &str) -> Result<(), EvalError> {
1280    if val.is_negative() {
1281        return Err(EvalError::NegativeOutOfDomain(function_name.into()));
1282    }
1283    if val.is_zero() {
1284        return Err(EvalError::ZeroOutOfDomain(function_name.into()));
1285    }
1286    Ok(())
1287}
1288
1289#[sqlfunc(sqlname = "log", propagates_nulls = true)]
1290fn log_base_numeric(mut a: Numeric, mut b: Numeric) -> Result<Numeric, EvalError> {
1291    log_guard_numeric(&a, "log")?;
1292    log_guard_numeric(&b, "log")?;
1293    let mut cx = numeric::cx_datum();
1294    cx.ln(&mut a);
1295    cx.ln(&mut b);
1296    cx.div(&mut b, &a);
1297    if a.is_zero() {
1298        Err(EvalError::DivisionByZero)
1299    } else {
1300        // This division can result in slightly wrong answers due to the
1301        // limitation of dividing irrational numbers. To correct that, see if
1302        // rounding off the value from its `numeric::NUMERIC_DATUM_MAX_PRECISION
1303        // - 1`th position results in an integral value.
1304        cx.set_precision(usize::from(numeric::NUMERIC_DATUM_MAX_PRECISION - 1))
1305            .expect("reducing precision below max always succeeds");
1306        let mut integral_check = b.clone();
1307
1308        // `reduce` rounds to the context's final digit when the number of
1309        // digits in its argument exceeds its precision. We've contrived that to
1310        // happen by shrinking the context's precision by 1.
1311        cx.reduce(&mut integral_check);
1312
1313        // Reduced integral values always have a non-negative exponent.
1314        let mut b = if integral_check.exponent() >= 0 {
1315            // We believe our result should have been an integral
1316            integral_check
1317        } else {
1318            b
1319        };
1320
1321        numeric::munge_numeric(&mut b).unwrap();
1322        Ok(b)
1323    }
1324}
1325
1326#[sqlfunc(propagates_nulls = true)]
1327fn power(a: f64, b: f64) -> Result<f64, EvalError> {
1328    if a == 0.0 && b.is_sign_negative() {
1329        return Err(EvalError::Undefined(
1330            "zero raised to a negative power".into(),
1331        ));
1332    }
1333    if a.is_sign_negative() && b.fract() != 0.0 {
1334        // Equivalent to PG error:
1335        // > a negative number raised to a non-integer power yields a complex result
1336        return Err(EvalError::ComplexOutOfRange("pow".into()));
1337    }
1338    let res = a.powf(b);
1339    if res.is_infinite() {
1340        return Err(EvalError::FloatOverflow);
1341    }
1342    if res == 0.0 && a != 0.0 {
1343        return Err(EvalError::FloatUnderflow);
1344    }
1345    Ok(res)
1346}
1347
1348#[sqlfunc(propagates_nulls = true)]
1349fn uuid_generate_v5(a: uuid::Uuid, b: &str) -> uuid::Uuid {
1350    uuid::Uuid::new_v5(&a, b.as_bytes())
1351}
1352
1353#[sqlfunc(output_type = "Numeric", propagates_nulls = true)]
1354fn power_numeric(mut a: Numeric, b: Numeric) -> Result<Numeric, EvalError> {
1355    if a.is_zero() {
1356        if b.is_zero() {
1357            return Ok(Numeric::from(1));
1358        }
1359        if b.is_negative() {
1360            return Err(EvalError::Undefined(
1361                "zero raised to a negative power".into(),
1362            ));
1363        }
1364    }
1365    if a.is_negative() && b.exponent() < 0 {
1366        // Equivalent to PG error:
1367        // > a negative number raised to a non-integer power yields a complex result
1368        return Err(EvalError::ComplexOutOfRange("pow".into()));
1369    }
1370    let mut cx = numeric::cx_datum();
1371    cx.pow(&mut a, &b);
1372    let cx_status = cx.status();
1373    if cx_status.overflow() || (cx_status.invalid_operation() && !b.is_negative()) {
1374        Err(EvalError::FloatOverflow)
1375    } else if cx_status.subnormal() || cx_status.invalid_operation() {
1376        Err(EvalError::FloatUnderflow)
1377    } else {
1378        numeric::munge_numeric(&mut a).unwrap();
1379        Ok(a)
1380    }
1381}
1382
1383#[sqlfunc(propagates_nulls = true)]
1384fn get_bit(bytes: &[u8], index: i32) -> Result<i32, EvalError> {
1385    let err = EvalError::IndexOutOfRange {
1386        provided: index,
1387        valid_end: i32::try_from(bytes.len().saturating_mul(8)).unwrap() - 1,
1388    };
1389
1390    let index = usize::try_from(index).map_err(|_| err.clone())?;
1391
1392    let byte_index = index / 8;
1393    let bit_index = index % 8;
1394
1395    let i = bytes
1396        .get(byte_index)
1397        .map(|b| (*b >> bit_index) & 1)
1398        .ok_or(err)?;
1399    assert!(i == 0 || i == 1);
1400    Ok(i32::from(i))
1401}
1402
1403#[sqlfunc(propagates_nulls = true)]
1404fn get_byte(bytes: &[u8], index: i32) -> Result<i32, EvalError> {
1405    let err = EvalError::IndexOutOfRange {
1406        provided: index,
1407        valid_end: i32::try_from(bytes.len()).unwrap() - 1,
1408    };
1409    let i: &u8 = bytes
1410        .get(usize::try_from(index).map_err(|_| err.clone())?)
1411        .ok_or(err)?;
1412    Ok(i32::from(*i))
1413}
1414
1415#[sqlfunc(sqlname = "constant_time_compare_bytes", propagates_nulls = true)]
1416pub fn constant_time_eq_bytes(a: &[u8], b: &[u8]) -> bool {
1417    bool::from(a.ct_eq(b))
1418}
1419
1420#[sqlfunc(sqlname = "constant_time_compare_strings", propagates_nulls = true)]
1421pub fn constant_time_eq_string(a: &str, b: &str) -> bool {
1422    bool::from(a.as_bytes().ct_eq(b.as_bytes()))
1423}
1424
1425fn contains_range_elem<'a, R: RangeOps<'a>>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a>
1426where
1427    <R as TryFrom<Datum<'a>>>::Error: std::fmt::Debug,
1428{
1429    let range = a.unwrap_range();
1430    let elem = R::try_from(b).expect("type checking must produce correct R");
1431    Datum::from(range.contains_elem(&elem))
1432}
1433
1434#[sqlfunc(is_infix_op = true, sqlname = "@>", propagates_nulls = true)]
1435fn range_contains_i32<'a>(a: Range<Datum<'a>>, b: i32) -> bool {
1436    a.contains_elem(&b)
1437}
1438
1439#[sqlfunc(is_infix_op = true, sqlname = "@>", propagates_nulls = true)]
1440fn range_contains_i64<'a>(a: Range<Datum<'a>>, elem: i64) -> bool {
1441    a.contains_elem(&elem)
1442}
1443
1444#[sqlfunc(is_infix_op = true, sqlname = "@>", propagates_nulls = true)]
1445fn range_contains_date<'a>(a: Range<Datum<'a>>, elem: Date) -> bool {
1446    a.contains_elem(&elem)
1447}
1448
1449#[sqlfunc(is_infix_op = true, sqlname = "@>", propagates_nulls = true)]
1450fn range_contains_numeric<'a>(a: Range<Datum<'a>>, elem: OrderedDecimal<Numeric>) -> bool {
1451    a.contains_elem(&elem)
1452}
1453
1454#[sqlfunc(is_infix_op = true, sqlname = "@>", propagates_nulls = true)]
1455fn range_contains_timestamp<'a>(
1456    a: Range<Datum<'a>>,
1457    elem: CheckedTimestamp<NaiveDateTime>,
1458) -> bool {
1459    a.contains_elem(&elem)
1460}
1461
1462#[sqlfunc(is_infix_op = true, sqlname = "@>", propagates_nulls = true)]
1463fn range_contains_timestamp_tz<'a>(
1464    a: Range<Datum<'a>>,
1465    elem: CheckedTimestamp<DateTime<Utc>>,
1466) -> bool {
1467    a.contains_elem(&elem)
1468}
1469
1470#[sqlfunc(is_infix_op = true, sqlname = "<@", propagates_nulls = true)]
1471fn range_contains_i32_rev<'a>(a: Range<Datum<'a>>, b: i32) -> bool {
1472    a.contains_elem(&b)
1473}
1474
1475#[sqlfunc(is_infix_op = true, sqlname = "<@", propagates_nulls = true)]
1476fn range_contains_i64_rev<'a>(a: Range<Datum<'a>>, elem: i64) -> bool {
1477    a.contains_elem(&elem)
1478}
1479
1480#[sqlfunc(is_infix_op = true, sqlname = "<@", propagates_nulls = true)]
1481fn range_contains_date_rev<'a>(a: Range<Datum<'a>>, elem: Date) -> bool {
1482    a.contains_elem(&elem)
1483}
1484
1485#[sqlfunc(is_infix_op = true, sqlname = "<@", propagates_nulls = true)]
1486fn range_contains_numeric_rev<'a>(a: Range<Datum<'a>>, elem: OrderedDecimal<Numeric>) -> bool {
1487    a.contains_elem(&elem)
1488}
1489
1490#[sqlfunc(is_infix_op = true, sqlname = "<@", propagates_nulls = true)]
1491fn range_contains_timestamp_rev<'a>(
1492    a: Range<Datum<'a>>,
1493    elem: CheckedTimestamp<NaiveDateTime>,
1494) -> bool {
1495    a.contains_elem(&elem)
1496}
1497
1498#[sqlfunc(is_infix_op = true, sqlname = "<@", propagates_nulls = true)]
1499fn range_contains_timestamp_tz_rev<'a>(
1500    a: Range<Datum<'a>>,
1501    elem: CheckedTimestamp<DateTime<Utc>>,
1502) -> bool {
1503    a.contains_elem(&elem)
1504}
1505
1506/// Macro to define binary function for various range operations.
1507/// Parameters:
1508/// 1. Unique binary function symbol.
1509/// 2. Range function symbol.
1510/// 3. SQL name for the function.
1511macro_rules! range_fn {
1512    ($fn:expr, $range_fn:expr, $sqlname:expr) => {
1513        paste::paste! {
1514
1515            #[sqlfunc(
1516                output_type = "bool",
1517                is_infix_op = true,
1518                sqlname = $sqlname,
1519                propagates_nulls = true
1520            )]
1521            fn [< range_ $fn >]<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a>
1522            {
1523                if a.is_null() || b.is_null() { return Datum::Null }
1524                let l = a.unwrap_range();
1525                let r = b.unwrap_range();
1526                Datum::from(Range::<Datum<'a>>::$range_fn(&l, &r))
1527            }
1528        }
1529    };
1530}
1531
1532// RangeContainsRange is either @> or <@ depending on the order of the arguments.
1533// It doesn't influence the result, but it does influence the display string.
1534range_fn!(contains_range, contains_range, "@>");
1535range_fn!(contains_range_rev, contains_range, "<@");
1536range_fn!(overlaps, overlaps, "&&");
1537range_fn!(after, after, ">>");
1538range_fn!(before, before, "<<");
1539range_fn!(overleft, overleft, "&<");
1540range_fn!(overright, overright, "&>");
1541range_fn!(adjacent, adjacent, "-|-");
1542
1543#[sqlfunc(
1544    output_type_expr = "input_type_a.scalar_type.without_modifiers().nullable(true)",
1545    is_infix_op = true,
1546    sqlname = "+",
1547    propagates_nulls = true,
1548    introduces_nulls = false
1549)]
1550fn range_union<'a>(
1551    l: Range<Datum<'a>>,
1552    r: Range<Datum<'a>>,
1553    temp_storage: &'a RowArena,
1554) -> Result<Datum<'a>, EvalError> {
1555    l.union(&r)?.into_result(temp_storage)
1556}
1557
1558#[sqlfunc(
1559    output_type_expr = "input_type_a.scalar_type.without_modifiers().nullable(true)",
1560    is_infix_op = true,
1561    sqlname = "*",
1562    propagates_nulls = true,
1563    introduces_nulls = false
1564)]
1565fn range_intersection<'a>(
1566    l: Range<Datum<'a>>,
1567    r: Range<Datum<'a>>,
1568    temp_storage: &'a RowArena,
1569) -> Result<Datum<'a>, EvalError> {
1570    l.intersection(&r).into_result(temp_storage)
1571}
1572
1573#[sqlfunc(
1574    output_type_expr = "input_type_a.scalar_type.without_modifiers().nullable(true)",
1575    is_infix_op = true,
1576    sqlname = "-",
1577    propagates_nulls = true,
1578    introduces_nulls = false
1579)]
1580fn range_difference<'a>(
1581    l: Range<Datum<'a>>,
1582    r: Range<Datum<'a>>,
1583    temp_storage: &'a RowArena,
1584) -> Result<Datum<'a>, EvalError> {
1585    l.difference(&r)?.into_result(temp_storage)
1586}
1587
1588#[sqlfunc(is_infix_op = true, sqlname = "=", negate = "Some(NotEq.into())")]
1589fn eq<'a>(a: ExcludeNull<Datum<'a>>, b: ExcludeNull<Datum<'a>>) -> bool {
1590    // SQL equality demands that if either input is null, then the result should be null. However,
1591    // we don't need to handle this case here; it is handled when `BinaryFunc::eval` checks
1592    // `propagates_nulls`.
1593    a == b
1594}
1595
1596#[sqlfunc(is_infix_op = true, sqlname = "!=", negate = "Some(Eq.into())")]
1597fn not_eq<'a>(a: ExcludeNull<Datum<'a>>, b: ExcludeNull<Datum<'a>>) -> bool {
1598    a != b
1599}
1600
1601#[sqlfunc(
1602    is_monotone = "(true, true)",
1603    is_infix_op = true,
1604    sqlname = "<",
1605    negate = "Some(Gte.into())"
1606)]
1607fn lt<'a>(a: ExcludeNull<Datum<'a>>, b: ExcludeNull<Datum<'a>>) -> bool {
1608    a < b
1609}
1610
1611#[sqlfunc(
1612    is_monotone = "(true, true)",
1613    is_infix_op = true,
1614    sqlname = "<=",
1615    negate = "Some(Gt.into())"
1616)]
1617fn lte<'a>(a: ExcludeNull<Datum<'a>>, b: ExcludeNull<Datum<'a>>) -> bool {
1618    a <= b
1619}
1620
1621#[sqlfunc(
1622    is_monotone = "(true, true)",
1623    is_infix_op = true,
1624    sqlname = ">",
1625    negate = "Some(Lte.into())"
1626)]
1627fn gt<'a>(a: ExcludeNull<Datum<'a>>, b: ExcludeNull<Datum<'a>>) -> bool {
1628    a > b
1629}
1630
1631#[sqlfunc(
1632    is_monotone = "(true, true)",
1633    is_infix_op = true,
1634    sqlname = ">=",
1635    negate = "Some(Lt.into())"
1636)]
1637fn gte<'a>(a: ExcludeNull<Datum<'a>>, b: ExcludeNull<Datum<'a>>) -> bool {
1638    a >= b
1639}
1640
1641#[sqlfunc(sqlname = "tocharts", propagates_nulls = true)]
1642fn to_char_timestamp_format(ts: CheckedTimestamp<chrono::NaiveDateTime>, format: &str) -> String {
1643    let fmt = DateTimeFormat::compile(format);
1644    fmt.render(&*ts)
1645}
1646
1647#[sqlfunc(sqlname = "tochartstz", propagates_nulls = true)]
1648fn to_char_timestamp_tz_format(
1649    ts: CheckedTimestamp<chrono::DateTime<Utc>>,
1650    format: &str,
1651) -> String {
1652    let fmt = DateTimeFormat::compile(format);
1653    fmt.render(&*ts)
1654}
1655
1656#[sqlfunc(sqlname = "->", is_infix_op = true)]
1657fn jsonb_get_int64<'a>(a: JsonbRef<'a>, i: i64) -> Option<JsonbRef<'a>> {
1658    match a.into_datum() {
1659        Datum::List(list) => {
1660            let i = if i >= 0 {
1661                usize::cast_from(i.unsigned_abs())
1662            } else {
1663                // index backwards from the end
1664                let i = usize::cast_from(i.unsigned_abs());
1665                (list.iter().count()).wrapping_sub(i)
1666            };
1667            let v = list.iter().nth(i)?;
1668            // `v` should be valid jsonb because it came from a jsonb list, but we don't
1669            // panic on mismatch to avoid bringing down the whole system on corrupt data.
1670            // Instead, we'll return None.
1671            JsonbRef::try_from_result(Ok::<_, ()>(v)).ok()
1672        }
1673        Datum::Map(_) => None,
1674        _ => {
1675            // I have no idea why postgres does this, but we're stuck with it
1676            (i == 0 || i == -1).then_some(a)
1677        }
1678    }
1679}
1680
1681#[sqlfunc(sqlname = "->>", is_infix_op = true)]
1682fn jsonb_get_int64_stringify<'a>(
1683    a: JsonbRef<'a>,
1684    i: i64,
1685    temp_storage: &'a RowArena,
1686) -> Option<&'a str> {
1687    let json = jsonb_get_int64(a, i)?;
1688    jsonb_stringify(json.into_datum(), temp_storage)
1689}
1690
1691#[sqlfunc(sqlname = "->", is_infix_op = true)]
1692fn jsonb_get_string<'a>(a: JsonbRef<'a>, k: &str) -> Option<JsonbRef<'a>> {
1693    let dict = DatumMap::try_from_result(Ok::<_, ()>(a.into_datum())).ok()?;
1694    let v = dict.iter().find(|(k2, _v)| k == *k2).map(|(_k, v)| v)?;
1695    JsonbRef::try_from_result(Ok::<_, ()>(v)).ok()
1696}
1697
1698#[sqlfunc(sqlname = "->>", is_infix_op = true)]
1699fn jsonb_get_string_stringify<'a>(
1700    a: JsonbRef<'a>,
1701    k: &str,
1702    temp_storage: &'a RowArena,
1703) -> Option<&'a str> {
1704    let v = jsonb_get_string(a, k)?;
1705    jsonb_stringify(v.into_datum(), temp_storage)
1706}
1707
1708#[sqlfunc(sqlname = "#>", is_infix_op = true)]
1709fn jsonb_get_path<'a>(mut json: JsonbRef<'a>, b: Array<'a>) -> Option<JsonbRef<'a>> {
1710    let path = b.elements();
1711    for key in path.iter() {
1712        let key = match key {
1713            Datum::String(s) => s,
1714            Datum::Null => return None,
1715            _ => unreachable!("keys in jsonb_get_path known to be strings"),
1716        };
1717        let v = match json.into_datum() {
1718            Datum::Map(map) => map.iter().find(|(k, _)| key == *k).map(|(_k, v)| v),
1719            Datum::List(list) => {
1720                let i = strconv::parse_int64(key).ok()?;
1721                let i = if i >= 0 {
1722                    usize::cast_from(i.unsigned_abs())
1723                } else {
1724                    // index backwards from the end
1725                    let i = usize::cast_from(i.unsigned_abs());
1726                    (list.iter().count()).wrapping_sub(i)
1727                };
1728                list.iter().nth(i)
1729            }
1730            _ => return None,
1731        }?;
1732        json = JsonbRef::try_from_result(Ok::<_, ()>(v)).ok()?;
1733    }
1734    Some(json)
1735}
1736
1737#[sqlfunc(sqlname = "#>>", is_infix_op = true)]
1738fn jsonb_get_path_stringify<'a>(
1739    a: JsonbRef<'a>,
1740    b: Array<'a>,
1741    temp_storage: &'a RowArena,
1742) -> Option<&'a str> {
1743    let json = jsonb_get_path(a, b)?;
1744    jsonb_stringify(json.into_datum(), temp_storage)
1745}
1746
1747#[sqlfunc(is_infix_op = true, sqlname = "?", propagates_nulls = true)]
1748fn jsonb_contains_string<'a>(a: Datum<'a>, k: &str) -> bool {
1749    // https://www.postgresql.org/docs/current/datatype-json.html#JSON-CONTAINMENT
1750    match a {
1751        Datum::List(list) => list.iter().any(|k2| Datum::from(k) == k2),
1752        Datum::Map(dict) => dict.iter().any(|(k2, _v)| k == k2),
1753        Datum::String(string) => string == k,
1754        _ => false,
1755    }
1756}
1757
1758#[sqlfunc(is_infix_op = true, sqlname = "?", propagates_nulls = true)]
1759// Map keys are always text.
1760fn map_contains_key<'a>(map: DatumMap<'a>, k: &str) -> bool {
1761    map.iter().any(|(k2, _v)| k == k2)
1762}
1763
1764#[sqlfunc(is_infix_op = true, sqlname = "?&")]
1765fn map_contains_all_keys<'a>(map: DatumMap<'a>, keys: Array<'a>) -> bool {
1766    keys.elements()
1767        .iter()
1768        .all(|key| !key.is_null() && map.iter().any(|(k, _v)| k == key.unwrap_str()))
1769}
1770
1771#[sqlfunc(is_infix_op = true, sqlname = "?|", propagates_nulls = true)]
1772fn map_contains_any_keys<'a>(map: DatumMap<'a>, keys: Array<'a>) -> bool {
1773    keys.elements()
1774        .iter()
1775        .any(|key| !key.is_null() && map.iter().any(|(k, _v)| k == key.unwrap_str()))
1776}
1777
1778#[sqlfunc(is_infix_op = true, sqlname = "@>", propagates_nulls = true)]
1779fn map_contains_map<'a>(map_a: DatumMap<'a>, b: DatumMap<'a>) -> bool {
1780    b.iter().all(|(b_key, b_val)| {
1781        map_a
1782            .iter()
1783            .any(|(a_key, a_val)| (a_key == b_key) && (a_val == b_val))
1784    })
1785}
1786
1787#[sqlfunc(
1788    output_type_expr = "input_type_a.scalar_type.unwrap_map_value_type().clone().nullable(true)",
1789    is_infix_op = true,
1790    sqlname = "->",
1791    propagates_nulls = true,
1792    introduces_nulls = true
1793)]
1794fn map_get_value<'a>(a: DatumMap<'a>, target_key: &str) -> Datum<'a> {
1795    match a.iter().find(|(key, _v)| target_key == *key) {
1796        Some((_k, v)) => v,
1797        None => Datum::Null,
1798    }
1799}
1800
1801#[sqlfunc(is_infix_op = true, sqlname = "@>")]
1802fn list_contains_list<'a>(a: ExcludeNull<DatumList<'a>>, b: ExcludeNull<DatumList<'a>>) -> bool {
1803    // NULL is never equal to NULL. If NULL is an element of b, b cannot be contained in a, even if a contains NULL.
1804    if b.iter().contains(&Datum::Null) {
1805        false
1806    } else {
1807        b.iter()
1808            .all(|item_b| a.iter().any(|item_a| item_a == item_b))
1809    }
1810}
1811
1812#[sqlfunc(is_infix_op = true, sqlname = "<@")]
1813fn list_contains_list_rev<'a>(
1814    a: ExcludeNull<DatumList<'a>>,
1815    b: ExcludeNull<DatumList<'a>>,
1816) -> bool {
1817    list_contains_list(b, a)
1818}
1819
1820// TODO(jamii) nested loops are possibly not the fastest way to do this
1821#[sqlfunc(is_infix_op = true, sqlname = "@>")]
1822fn jsonb_contains_jsonb<'a>(a: JsonbRef<'a>, b: JsonbRef<'a>) -> bool {
1823    // https://www.postgresql.org/docs/current/datatype-json.html#JSON-CONTAINMENT
1824    fn contains(a: Datum, b: Datum, at_top_level: bool) -> bool {
1825        match (a, b) {
1826            (Datum::JsonNull, Datum::JsonNull) => true,
1827            (Datum::False, Datum::False) => true,
1828            (Datum::True, Datum::True) => true,
1829            (Datum::Numeric(a), Datum::Numeric(b)) => a == b,
1830            (Datum::String(a), Datum::String(b)) => a == b,
1831            (Datum::List(a), Datum::List(b)) => b
1832                .iter()
1833                .all(|b_elem| a.iter().any(|a_elem| contains(a_elem, b_elem, false))),
1834            (Datum::Map(a), Datum::Map(b)) => b.iter().all(|(b_key, b_val)| {
1835                a.iter()
1836                    .any(|(a_key, a_val)| (a_key == b_key) && contains(a_val, b_val, false))
1837            }),
1838
1839            // fun special case
1840            (Datum::List(a), b) => {
1841                at_top_level && a.iter().any(|a_elem| contains(a_elem, b, false))
1842            }
1843
1844            _ => false,
1845        }
1846    }
1847    contains(a.into_datum(), b.into_datum(), true)
1848}
1849
1850#[sqlfunc(is_infix_op = true, sqlname = "||")]
1851fn jsonb_concat<'a>(
1852    a: JsonbRef<'a>,
1853    b: JsonbRef<'a>,
1854    temp_storage: &'a RowArena,
1855) -> Option<JsonbRef<'a>> {
1856    let res = match (a.into_datum(), b.into_datum()) {
1857        (Datum::Map(dict_a), Datum::Map(dict_b)) => {
1858            let mut pairs = dict_b.iter().chain(dict_a.iter()).collect::<Vec<_>>();
1859            // stable sort, so if keys collide dedup prefers dict_b
1860            pairs.sort_by(|(k1, _v1), (k2, _v2)| k1.cmp(k2));
1861            pairs.dedup_by(|(k1, _v1), (k2, _v2)| k1 == k2);
1862            temp_storage.make_datum(|packer| packer.push_dict(pairs))
1863        }
1864        (Datum::List(list_a), Datum::List(list_b)) => {
1865            let elems = list_a.iter().chain(list_b.iter());
1866            temp_storage.make_datum(|packer| packer.push_list(elems))
1867        }
1868        (Datum::List(list_a), b) => {
1869            let elems = list_a.iter().chain(Some(b));
1870            temp_storage.make_datum(|packer| packer.push_list(elems))
1871        }
1872        (a, Datum::List(list_b)) => {
1873            let elems = Some(a).into_iter().chain(list_b.iter());
1874            temp_storage.make_datum(|packer| packer.push_list(elems))
1875        }
1876        _ => return None,
1877    };
1878    Some(JsonbRef::from_datum(res))
1879}
1880
1881#[sqlfunc(
1882    output_type_expr = "SqlScalarType::Jsonb.nullable(true)",
1883    is_infix_op = true,
1884    sqlname = "-",
1885    propagates_nulls = true,
1886    introduces_nulls = true
1887)]
1888fn jsonb_delete_int64<'a>(a: Datum<'a>, i: i64, temp_storage: &'a RowArena) -> Datum<'a> {
1889    match a {
1890        Datum::List(list) => {
1891            let i = if i >= 0 {
1892                usize::cast_from(i.unsigned_abs())
1893            } else {
1894                // index backwards from the end
1895                let i = usize::cast_from(i.unsigned_abs());
1896                (list.iter().count()).wrapping_sub(i)
1897            };
1898            let elems = list
1899                .iter()
1900                .enumerate()
1901                .filter(|(i2, _e)| i != *i2)
1902                .map(|(_, e)| e);
1903            temp_storage.make_datum(|packer| packer.push_list(elems))
1904        }
1905        _ => Datum::Null,
1906    }
1907}
1908
1909#[sqlfunc(
1910    output_type_expr = "SqlScalarType::Jsonb.nullable(true)",
1911    is_infix_op = true,
1912    sqlname = "-",
1913    propagates_nulls = true,
1914    introduces_nulls = true
1915)]
1916fn jsonb_delete_string<'a>(a: Datum<'a>, k: &str, temp_storage: &'a RowArena) -> Datum<'a> {
1917    match a {
1918        Datum::List(list) => {
1919            let elems = list.iter().filter(|e| Datum::from(k) != *e);
1920            temp_storage.make_datum(|packer| packer.push_list(elems))
1921        }
1922        Datum::Map(dict) => {
1923            let pairs = dict.iter().filter(|(k2, _v)| k != *k2);
1924            temp_storage.make_datum(|packer| packer.push_dict(pairs))
1925        }
1926        _ => Datum::Null,
1927    }
1928}
1929
1930#[sqlfunc(
1931    sqlname = "extractiv",
1932    propagates_nulls = true,
1933    introduces_nulls = false
1934)]
1935fn date_part_interval_numeric(units: &str, b: Interval) -> Result<Numeric, EvalError> {
1936    match units.parse() {
1937        Ok(units) => Ok(date_part_interval_inner::<Numeric>(units, b)?),
1938        Err(_) => Err(EvalError::UnknownUnits(units.into())),
1939    }
1940}
1941
1942#[sqlfunc(
1943    sqlname = "date_partiv",
1944    propagates_nulls = true,
1945    introduces_nulls = false
1946)]
1947fn date_part_interval_f64(units: &str, b: Interval) -> Result<f64, EvalError> {
1948    match units.parse() {
1949        Ok(units) => Ok(date_part_interval_inner::<f64>(units, b)?),
1950        Err(_) => Err(EvalError::UnknownUnits(units.into())),
1951    }
1952}
1953
1954#[sqlfunc(
1955    sqlname = "extractt",
1956    propagates_nulls = true,
1957    introduces_nulls = false
1958)]
1959fn date_part_time_numeric(units: &str, b: chrono::NaiveTime) -> Result<Numeric, EvalError> {
1960    match units.parse() {
1961        Ok(units) => Ok(date_part_time_inner::<Numeric>(units, b)?),
1962        Err(_) => Err(EvalError::UnknownUnits(units.into())),
1963    }
1964}
1965
1966#[sqlfunc(
1967    sqlname = "date_partt",
1968    propagates_nulls = true,
1969    introduces_nulls = false
1970)]
1971fn date_part_time_f64(units: &str, b: chrono::NaiveTime) -> Result<f64, EvalError> {
1972    match units.parse() {
1973        Ok(units) => Ok(date_part_time_inner::<f64>(units, b)?),
1974        Err(_) => Err(EvalError::UnknownUnits(units.into())),
1975    }
1976}
1977
1978#[sqlfunc(sqlname = "extractts", propagates_nulls = true)]
1979fn date_part_timestamp_timestamp_numeric(
1980    units: &str,
1981    ts: CheckedTimestamp<NaiveDateTime>,
1982) -> Result<Numeric, EvalError> {
1983    match units.parse() {
1984        Ok(units) => Ok(date_part_timestamp_inner::<_, Numeric>(units, &*ts)?),
1985        Err(_) => Err(EvalError::UnknownUnits(units.into())),
1986    }
1987}
1988
1989#[sqlfunc(sqlname = "extracttstz", propagates_nulls = true)]
1990fn date_part_timestamp_timestamp_tz_numeric(
1991    units: &str,
1992    ts: CheckedTimestamp<DateTime<Utc>>,
1993) -> Result<Numeric, EvalError> {
1994    match units.parse() {
1995        Ok(units) => Ok(date_part_timestamp_inner::<_, Numeric>(units, &*ts)?),
1996        Err(_) => Err(EvalError::UnknownUnits(units.into())),
1997    }
1998}
1999
2000#[sqlfunc(sqlname = "date_partts", propagates_nulls = true)]
2001fn date_part_timestamp_timestamp_f64(
2002    units: &str,
2003    ts: CheckedTimestamp<NaiveDateTime>,
2004) -> Result<f64, EvalError> {
2005    match units.parse() {
2006        Ok(units) => date_part_timestamp_inner(units, &*ts),
2007        Err(_) => Err(EvalError::UnknownUnits(units.into())),
2008    }
2009}
2010
2011#[sqlfunc(sqlname = "date_parttstz", propagates_nulls = true)]
2012fn date_part_timestamp_timestamp_tz_f64(
2013    units: &str,
2014    ts: CheckedTimestamp<DateTime<Utc>>,
2015) -> Result<f64, EvalError> {
2016    match units.parse() {
2017        Ok(units) => date_part_timestamp_inner(units, &*ts),
2018        Err(_) => Err(EvalError::UnknownUnits(units.into())),
2019    }
2020}
2021
2022#[sqlfunc(sqlname = "extractd", propagates_nulls = true)]
2023fn extract_date_units(units: &str, b: Date) -> Result<Numeric, EvalError> {
2024    match units.parse() {
2025        Ok(units) => Ok(extract_date_inner(units, b.into())?),
2026        Err(_) => Err(EvalError::UnknownUnits(units.into())),
2027    }
2028}
2029
2030pub fn date_bin<T>(
2031    stride: Interval,
2032    source: CheckedTimestamp<T>,
2033    origin: CheckedTimestamp<T>,
2034) -> Result<CheckedTimestamp<T>, EvalError>
2035where
2036    T: TimestampLike,
2037{
2038    if stride.months != 0 {
2039        return Err(EvalError::DateBinOutOfRange(
2040            "timestamps cannot be binned into intervals containing months or years".into(),
2041        ));
2042    }
2043
2044    let stride_ns = match stride.duration_as_chrono().num_nanoseconds() {
2045        Some(ns) if ns <= 0 => Err(EvalError::DateBinOutOfRange(
2046            "stride must be greater than zero".into(),
2047        )),
2048        Some(ns) => Ok(ns),
2049        None => Err(EvalError::DateBinOutOfRange(
2050            format!("stride cannot exceed {}/{} nanoseconds", i64::MAX, i64::MIN,).into(),
2051        )),
2052    }?;
2053
2054    // Make sure the returned timestamp is at the start of the bin, even if the
2055    // origin is in the future. We do this here because `T` is not `Copy` and
2056    // gets moved by its subtraction operation.
2057    let sub_stride = origin > source;
2058
2059    let tm_diff = (source - origin.clone()).num_nanoseconds().ok_or_else(|| {
2060        EvalError::DateBinOutOfRange(
2061            "source and origin must not differ more than 2^63 nanoseconds".into(),
2062        )
2063    })?;
2064
2065    let mut tm_delta = tm_diff - tm_diff % stride_ns;
2066
2067    if sub_stride {
2068        tm_delta -= stride_ns;
2069    }
2070
2071    let res = origin
2072        .checked_add_signed(Duration::nanoseconds(tm_delta))
2073        .ok_or(EvalError::TimestampOutOfRange)?;
2074    Ok(CheckedTimestamp::from_timestamplike(res)?)
2075}
2076
2077#[sqlfunc(is_monotone = "(true, true)", sqlname = "bin_unix_epoch_timestamp")]
2078fn date_bin_timestamp(
2079    stride: Interval,
2080    source: CheckedTimestamp<NaiveDateTime>,
2081) -> Result<CheckedTimestamp<NaiveDateTime>, EvalError> {
2082    let origin =
2083        CheckedTimestamp::from_timestamplike(DateTime::from_timestamp(0, 0).unwrap().naive_utc())
2084            .expect("must fit");
2085    date_bin(stride, source, origin)
2086}
2087
2088#[sqlfunc(is_monotone = "(true, true)", sqlname = "bin_unix_epoch_timestamptz")]
2089fn date_bin_timestamp_tz(
2090    stride: Interval,
2091    source: CheckedTimestamp<DateTime<Utc>>,
2092) -> Result<CheckedTimestamp<DateTime<Utc>>, EvalError> {
2093    let origin = CheckedTimestamp::from_timestamplike(DateTime::from_timestamp(0, 0).unwrap())
2094        .expect("must fit");
2095    date_bin(stride, source, origin)
2096}
2097
2098#[sqlfunc(sqlname = "date_truncts", propagates_nulls = true)]
2099fn date_trunc_units_timestamp(
2100    units: &str,
2101    ts: CheckedTimestamp<NaiveDateTime>,
2102) -> Result<CheckedTimestamp<NaiveDateTime>, EvalError> {
2103    match units.parse() {
2104        Ok(units) => Ok(date_trunc_inner(units, &*ts)?.try_into()?),
2105        Err(_) => Err(EvalError::UnknownUnits(units.into())),
2106    }
2107}
2108
2109#[sqlfunc(sqlname = "date_trunctstz", propagates_nulls = true)]
2110fn date_trunc_units_timestamp_tz(
2111    units: &str,
2112    ts: CheckedTimestamp<DateTime<Utc>>,
2113) -> Result<CheckedTimestamp<DateTime<Utc>>, EvalError> {
2114    match units.parse() {
2115        Ok(units) => Ok(date_trunc_inner(units, &*ts)?.try_into()?),
2116        Err(_) => Err(EvalError::UnknownUnits(units.into())),
2117    }
2118}
2119
2120#[sqlfunc(sqlname = "date_trunciv", propagates_nulls = true)]
2121fn date_trunc_interval(units: &str, mut interval: Interval) -> Result<Interval, EvalError> {
2122    let dtf = units
2123        .parse()
2124        .map_err(|_| EvalError::UnknownUnits(units.into()))?;
2125
2126    interval
2127        .truncate_low_fields(dtf, Some(0), RoundBehavior::Truncate)
2128        .expect(
2129            "truncate_low_fields should not fail with max_precision 0 and RoundBehavior::Truncate",
2130        );
2131    Ok(interval)
2132}
2133
2134/// Parses a named timezone like `EST` or `America/New_York`, or a fixed-offset timezone like `-05:00`.
2135///
2136/// The interpretation of fixed offsets depend on whether the POSIX or ISO 8601 standard is being
2137/// used.
2138pub(crate) fn parse_timezone(tz: &str, spec: TimezoneSpec) -> Result<Timezone, EvalError> {
2139    Timezone::parse(tz, spec).map_err(|_| EvalError::InvalidTimezone(tz.into()))
2140}
2141
2142/// Converts the time datum `b`, which is assumed to be in UTC, to the timezone that the interval datum `a` is assumed
2143/// to represent. The interval is not allowed to hold months, but there are no limits on the amount of seconds.
2144/// The interval acts like a `chrono::FixedOffset`, without the `-86,400 < x < 86,400` limitation.
2145fn timezone_interval_time(a: Datum<'_>, b: Datum<'_>) -> Result<Datum<'static>, EvalError> {
2146    let interval = a.unwrap_interval();
2147    if interval.months != 0 {
2148        Err(EvalError::InvalidTimezoneInterval)
2149    } else {
2150        Ok(b.unwrap_time()
2151            .overflowing_add_signed(interval.duration_as_chrono())
2152            .0
2153            .into())
2154    }
2155}
2156
2157/// Converts the timestamp datum `b`, which is assumed to be in the time of the timezone datum `a` to a timestamptz
2158/// in UTC. The interval is not allowed to hold months, but there are no limits on the amount of seconds.
2159/// The interval acts like a `chrono::FixedOffset`, without the `-86,400 < x < 86,400` limitation.
2160fn timezone_interval_timestamp(a: Datum<'_>, b: Datum<'_>) -> Result<Datum<'static>, EvalError> {
2161    let interval = a.unwrap_interval();
2162    if interval.months != 0 {
2163        Err(EvalError::InvalidTimezoneInterval)
2164    } else {
2165        match b
2166            .unwrap_timestamp()
2167            .checked_sub_signed(interval.duration_as_chrono())
2168        {
2169            Some(sub) => Ok(DateTime::from_naive_utc_and_offset(sub, Utc).try_into()?),
2170            None => Err(EvalError::TimestampOutOfRange),
2171        }
2172    }
2173}
2174
2175/// Converts the UTC timestamptz datum `b`, to the local timestamp of the timezone datum `a`.
2176/// The interval is not allowed to hold months, but there are no limits on the amount of seconds.
2177/// The interval acts like a `chrono::FixedOffset`, without the `-86,400 < x < 86,400` limitation.
2178fn timezone_interval_timestamptz(a: Datum<'_>, b: Datum<'_>) -> Result<Datum<'static>, EvalError> {
2179    let interval = a.unwrap_interval();
2180    if interval.months != 0 {
2181        return Err(EvalError::InvalidTimezoneInterval);
2182    }
2183    match b
2184        .unwrap_timestamptz()
2185        .naive_utc()
2186        .checked_add_signed(interval.duration_as_chrono())
2187    {
2188        Some(dt) => Ok(dt.try_into()?),
2189        None => Err(EvalError::TimestampOutOfRange),
2190    }
2191}
2192
2193#[sqlfunc(
2194    output_type_expr = r#"SqlScalarType::Record {
2195                fields: [
2196                    ("abbrev".into(), SqlScalarType::String.nullable(false)),
2197                    ("base_utc_offset".into(), SqlScalarType::Interval.nullable(false)),
2198                    ("dst_offset".into(), SqlScalarType::Interval.nullable(false)),
2199                ].into(),
2200                custom_id: None,
2201            }.nullable(true)"#,
2202    propagates_nulls = true,
2203    introduces_nulls = false
2204)]
2205fn timezone_offset<'a>(
2206    tz_str: &str,
2207    b: CheckedTimestamp<chrono::DateTime<Utc>>,
2208    temp_storage: &'a RowArena,
2209) -> Result<Datum<'a>, EvalError> {
2210    let tz = match Tz::from_str_insensitive(tz_str) {
2211        Ok(tz) => tz,
2212        Err(_) => return Err(EvalError::InvalidIanaTimezoneId(tz_str.into())),
2213    };
2214    let offset = tz.offset_from_utc_datetime(&b.naive_utc());
2215    Ok(temp_storage.make_datum(|packer| {
2216        packer.push_list_with(|packer| {
2217            packer.push(Datum::from(offset.abbreviation()));
2218            packer.push(Datum::from(offset.base_utc_offset()));
2219            packer.push(Datum::from(offset.dst_offset()));
2220        });
2221    }))
2222}
2223
2224/// Determines if an mz_aclitem contains one of the specified privileges. This will return true if
2225/// any of the listed privileges are contained in the mz_aclitem.
2226#[sqlfunc(
2227    sqlname = "mz_aclitem_contains_privilege",
2228    output_type = "bool",
2229    propagates_nulls = true
2230)]
2231fn mz_acl_item_contains_privilege(
2232    mz_acl_item: MzAclItem,
2233    privileges: &str,
2234) -> Result<bool, EvalError> {
2235    let acl_mode = AclMode::parse_multiple_privileges(privileges)
2236        .map_err(|e: anyhow::Error| EvalError::InvalidPrivileges(e.to_string().into()))?;
2237    let contains = !mz_acl_item.acl_mode.intersection(acl_mode).is_empty();
2238    Ok(contains)
2239}
2240
2241#[sqlfunc]
2242// transliterated from postgres/src/backend/utils/adt/misc.c
2243fn parse_ident<'a>(ident: &'a str, strict: bool) -> Result<ArrayRustType<Cow<'a, str>>, EvalError> {
2244    fn is_ident_start(c: char) -> bool {
2245        matches!(c, 'A'..='Z' | 'a'..='z' | '_' | '\u{80}'..=char::MAX)
2246    }
2247
2248    fn is_ident_cont(c: char) -> bool {
2249        matches!(c, '0'..='9' | '$') || is_ident_start(c)
2250    }
2251
2252    let mut elems = vec![];
2253    let buf = &mut LexBuf::new(ident);
2254
2255    let mut after_dot = false;
2256
2257    buf.take_while(|ch| ch.is_ascii_whitespace());
2258
2259    loop {
2260        let mut missing_ident = true;
2261
2262        let c = buf.next();
2263
2264        if c == Some('"') {
2265            let s = buf.take_while(|ch| !matches!(ch, '"'));
2266
2267            if buf.next() != Some('"') {
2268                return Err(EvalError::InvalidIdentifier {
2269                    ident: ident.into(),
2270                    detail: Some("String has unclosed double quotes.".into()),
2271                });
2272            }
2273            elems.push(Cow::Borrowed(s));
2274            missing_ident = false;
2275        } else if c.map(is_ident_start).unwrap_or(false) {
2276            buf.prev();
2277            let s = buf.take_while(is_ident_cont);
2278            elems.push(Cow::Owned(s.to_ascii_lowercase()));
2279            missing_ident = false;
2280        }
2281
2282        if missing_ident {
2283            if c == Some('.') {
2284                return Err(EvalError::InvalidIdentifier {
2285                    ident: ident.into(),
2286                    detail: Some("No valid identifier before \".\".".into()),
2287                });
2288            } else if after_dot {
2289                return Err(EvalError::InvalidIdentifier {
2290                    ident: ident.into(),
2291                    detail: Some("No valid identifier after \".\".".into()),
2292                });
2293            } else {
2294                return Err(EvalError::InvalidIdentifier {
2295                    ident: ident.into(),
2296                    detail: None,
2297                });
2298            }
2299        }
2300
2301        buf.take_while(|ch| ch.is_ascii_whitespace());
2302
2303        match buf.next() {
2304            Some('.') => {
2305                after_dot = true;
2306
2307                buf.take_while(|ch| ch.is_ascii_whitespace());
2308            }
2309            Some(_) if strict => {
2310                return Err(EvalError::InvalidIdentifier {
2311                    ident: ident.into(),
2312                    detail: None,
2313                });
2314            }
2315            _ => break,
2316        }
2317    }
2318
2319    Ok(elems.into())
2320}
2321
2322fn regexp_split_to_array_re<'a>(
2323    text: &str,
2324    regexp: &Regex,
2325    temp_storage: &'a RowArena,
2326) -> Result<Datum<'a>, EvalError> {
2327    let found = mz_regexp::regexp_split_to_array(text, regexp);
2328    let mut row = Row::default();
2329    let mut packer = row.packer();
2330    packer.try_push_array(
2331        &[ArrayDimension {
2332            lower_bound: 1,
2333            length: found.len(),
2334        }],
2335        found.into_iter().map(Datum::String),
2336    )?;
2337    Ok(temp_storage.push_unary_row(row))
2338}
2339
2340#[sqlfunc(propagates_nulls = true)]
2341fn pretty_sql<'a>(sql: &str, width: i32, temp_storage: &'a RowArena) -> Result<&'a str, EvalError> {
2342    let width =
2343        usize::try_from(width).map_err(|_| EvalError::PrettyError("invalid width".into()))?;
2344    let pretty = pretty_str(
2345        sql,
2346        PrettyConfig {
2347            width,
2348            format_mode: FormatMode::Simple,
2349        },
2350    )
2351    .map_err(|e| EvalError::PrettyError(e.to_string().into()))?;
2352    let pretty = temp_storage.push_string(pretty);
2353    Ok(pretty)
2354}
2355
2356#[sqlfunc(propagates_nulls = true)]
2357fn starts_with(a: &str, b: &str) -> bool {
2358    a.starts_with(b)
2359}
2360
2361#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
2362pub enum BinaryFunc {
2363    AddInt16(AddInt16),
2364    AddInt32(AddInt32),
2365    AddInt64(AddInt64),
2366    AddUint16(AddUint16),
2367    AddUint32(AddUint32),
2368    AddUint64(AddUint64),
2369    AddFloat32(AddFloat32),
2370    AddFloat64(AddFloat64),
2371    AddInterval(AddInterval),
2372    AddTimestampInterval(AddTimestampInterval),
2373    AddTimestampTzInterval(AddTimestampTzInterval),
2374    AddDateInterval(AddDateInterval),
2375    AddDateTime(AddDateTime),
2376    AddTimeInterval(AddTimeInterval),
2377    AddNumeric(AddNumeric),
2378    AgeTimestamp(AgeTimestamp),
2379    AgeTimestampTz(AgeTimestampTz),
2380    BitAndInt16(BitAndInt16),
2381    BitAndInt32(BitAndInt32),
2382    BitAndInt64(BitAndInt64),
2383    BitAndUint16(BitAndUint16),
2384    BitAndUint32(BitAndUint32),
2385    BitAndUint64(BitAndUint64),
2386    BitOrInt16(BitOrInt16),
2387    BitOrInt32(BitOrInt32),
2388    BitOrInt64(BitOrInt64),
2389    BitOrUint16(BitOrUint16),
2390    BitOrUint32(BitOrUint32),
2391    BitOrUint64(BitOrUint64),
2392    BitXorInt16(BitXorInt16),
2393    BitXorInt32(BitXorInt32),
2394    BitXorInt64(BitXorInt64),
2395    BitXorUint16(BitXorUint16),
2396    BitXorUint32(BitXorUint32),
2397    BitXorUint64(BitXorUint64),
2398    BitShiftLeftInt16(BitShiftLeftInt16),
2399    BitShiftLeftInt32(BitShiftLeftInt32),
2400    BitShiftLeftInt64(BitShiftLeftInt64),
2401    BitShiftLeftUint16(BitShiftLeftUint16),
2402    BitShiftLeftUint32(BitShiftLeftUint32),
2403    BitShiftLeftUint64(BitShiftLeftUint64),
2404    BitShiftRightInt16(BitShiftRightInt16),
2405    BitShiftRightInt32(BitShiftRightInt32),
2406    BitShiftRightInt64(BitShiftRightInt64),
2407    BitShiftRightUint16(BitShiftRightUint16),
2408    BitShiftRightUint32(BitShiftRightUint32),
2409    BitShiftRightUint64(BitShiftRightUint64),
2410    SubInt16(SubInt16),
2411    SubInt32(SubInt32),
2412    SubInt64(SubInt64),
2413    SubUint16(SubUint16),
2414    SubUint32(SubUint32),
2415    SubUint64(SubUint64),
2416    SubFloat32(SubFloat32),
2417    SubFloat64(SubFloat64),
2418    SubInterval(SubInterval),
2419    SubTimestamp(SubTimestamp),
2420    SubTimestampTz(SubTimestampTz),
2421    SubTimestampInterval(SubTimestampInterval),
2422    SubTimestampTzInterval(SubTimestampTzInterval),
2423    SubDate(SubDate),
2424    SubDateInterval(SubDateInterval),
2425    SubTime(SubTime),
2426    SubTimeInterval(SubTimeInterval),
2427    SubNumeric(SubNumeric),
2428    MulInt16(MulInt16),
2429    MulInt32(MulInt32),
2430    MulInt64(MulInt64),
2431    MulUint16(MulUint16),
2432    MulUint32(MulUint32),
2433    MulUint64(MulUint64),
2434    MulFloat32(MulFloat32),
2435    MulFloat64(MulFloat64),
2436    MulNumeric(MulNumeric),
2437    MulInterval(MulInterval),
2438    DivInt16(DivInt16),
2439    DivInt32(DivInt32),
2440    DivInt64(DivInt64),
2441    DivUint16(DivUint16),
2442    DivUint32(DivUint32),
2443    DivUint64(DivUint64),
2444    DivFloat32(DivFloat32),
2445    DivFloat64(DivFloat64),
2446    DivNumeric(DivNumeric),
2447    DivInterval(DivInterval),
2448    ModInt16(ModInt16),
2449    ModInt32(ModInt32),
2450    ModInt64(ModInt64),
2451    ModUint16(ModUint16),
2452    ModUint32(ModUint32),
2453    ModUint64(ModUint64),
2454    ModFloat32(ModFloat32),
2455    ModFloat64(ModFloat64),
2456    ModNumeric(ModNumeric),
2457    RoundNumeric(RoundNumericBinary),
2458    Eq(Eq),
2459    NotEq(NotEq),
2460    Lt(Lt),
2461    Lte(Lte),
2462    Gt(Gt),
2463    Gte(Gte),
2464    LikeEscape(LikeEscape),
2465    IsLikeMatchCaseInsensitive(IsLikeMatchCaseInsensitive),
2466    IsLikeMatchCaseSensitive(IsLikeMatchCaseSensitive),
2467    IsRegexpMatch { case_insensitive: bool },
2468    ToCharTimestamp(ToCharTimestampFormat),
2469    ToCharTimestampTz(ToCharTimestampTzFormat),
2470    DateBinTimestamp(DateBinTimestamp),
2471    DateBinTimestampTz(DateBinTimestampTz),
2472    ExtractInterval(DatePartIntervalNumeric),
2473    ExtractTime(DatePartTimeNumeric),
2474    ExtractTimestamp(DatePartTimestampTimestampNumeric),
2475    ExtractTimestampTz(DatePartTimestampTimestampTzNumeric),
2476    ExtractDate(ExtractDateUnits),
2477    DatePartInterval(DatePartIntervalF64),
2478    DatePartTime(DatePartTimeF64),
2479    DatePartTimestamp(DatePartTimestampTimestampF64),
2480    DatePartTimestampTz(DatePartTimestampTimestampTzF64),
2481    DateTruncTimestamp(DateTruncUnitsTimestamp),
2482    DateTruncTimestampTz(DateTruncUnitsTimestampTz),
2483    DateTruncInterval(DateTruncInterval),
2484    TimezoneTimestamp,
2485    TimezoneTimestampTz,
2486    TimezoneIntervalTimestamp,
2487    TimezoneIntervalTimestampTz,
2488    TimezoneIntervalTime,
2489    TimezoneOffset(TimezoneOffset),
2490    TextConcat(TextConcatBinary),
2491    JsonbGetInt64(JsonbGetInt64),
2492    JsonbGetInt64Stringify(JsonbGetInt64Stringify),
2493    JsonbGetString(JsonbGetString),
2494    JsonbGetStringStringify(JsonbGetStringStringify),
2495    JsonbGetPath(JsonbGetPath),
2496    JsonbGetPathStringify(JsonbGetPathStringify),
2497    JsonbContainsString(JsonbContainsString),
2498    JsonbConcat(JsonbConcat),
2499    JsonbContainsJsonb(JsonbContainsJsonb),
2500    JsonbDeleteInt64(JsonbDeleteInt64),
2501    JsonbDeleteString(JsonbDeleteString),
2502    MapContainsKey(MapContainsKey),
2503    MapGetValue(MapGetValue),
2504    MapContainsAllKeys(MapContainsAllKeys),
2505    MapContainsAnyKeys(MapContainsAnyKeys),
2506    MapContainsMap(MapContainsMap),
2507    ConvertFrom(ConvertFrom),
2508    Left(Left),
2509    Position(Position),
2510    Right(Right),
2511    RepeatString,
2512    Normalize,
2513    Trim(Trim),
2514    TrimLeading(TrimLeading),
2515    TrimTrailing(TrimTrailing),
2516    EncodedBytesCharLength(EncodedBytesCharLength),
2517    ListLengthMax(ListLengthMax),
2518    ArrayContains(ArrayContains),
2519    ArrayContainsArray(ArrayContainsArray),
2520    ArrayContainsArrayRev(ArrayContainsArrayRev),
2521    ArrayLength(ArrayLength),
2522    ArrayLower(ArrayLower),
2523    ArrayRemove(ArrayRemove),
2524    ArrayUpper(ArrayUpper),
2525    ArrayArrayConcat(ArrayArrayConcat),
2526    ListListConcat(ListListConcat),
2527    ListElementConcat(ListElementConcat),
2528    ElementListConcat(ElementListConcat),
2529    ListRemove(ListRemove),
2530    ListContainsList(ListContainsList),
2531    ListContainsListRev(ListContainsListRev),
2532    DigestString(DigestString),
2533    DigestBytes(DigestBytes),
2534    MzRenderTypmod(MzRenderTypmod),
2535    Encode(Encode),
2536    Decode(Decode),
2537    LogNumeric(LogBaseNumeric),
2538    Power(Power),
2539    PowerNumeric(PowerNumeric),
2540    GetBit(GetBit),
2541    GetByte(GetByte),
2542    ConstantTimeEqBytes(ConstantTimeEqBytes),
2543    ConstantTimeEqString(ConstantTimeEqString),
2544    RangeContainsElem { elem_type: SqlScalarType, rev: bool },
2545    RangeContainsRange(RangeContainsRange),
2546    RangeContainsRangeRev(RangeContainsRangeRev),
2547    RangeOverlaps(RangeOverlaps),
2548    RangeAfter(RangeAfter),
2549    RangeBefore(RangeBefore),
2550    RangeOverleft(RangeOverleft),
2551    RangeOverright(RangeOverright),
2552    RangeAdjacent(RangeAdjacent),
2553    RangeUnion(RangeUnion),
2554    RangeIntersection(RangeIntersection),
2555    RangeDifference(RangeDifference),
2556    UuidGenerateV5(UuidGenerateV5),
2557    MzAclItemContainsPrivilege(MzAclItemContainsPrivilege),
2558    ParseIdent(ParseIdent),
2559    PrettySql(PrettySql),
2560    RegexpReplace { regex: Regex, limit: usize },
2561    StartsWith(StartsWith),
2562}
2563
2564impl BinaryFunc {
2565    pub fn eval<'a>(
2566        &'a self,
2567        datums: &[Datum<'a>],
2568        temp_storage: &'a RowArena,
2569        a_expr: &'a MirScalarExpr,
2570        b_expr: &'a MirScalarExpr,
2571    ) -> Result<Datum<'a>, EvalError> {
2572        match self {
2573            BinaryFunc::AddInt16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2574            BinaryFunc::AddInt32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2575            BinaryFunc::AddInt64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2576            BinaryFunc::AddUint16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2577            BinaryFunc::AddUint32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2578            BinaryFunc::AddUint64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2579            BinaryFunc::AddFloat32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2580            BinaryFunc::AddFloat64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2581            BinaryFunc::AddInterval(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2582            BinaryFunc::AddTimestampInterval(s) => {
2583                return s.eval(datums, temp_storage, a_expr, b_expr);
2584            }
2585            BinaryFunc::AddTimestampTzInterval(s) => {
2586                return s.eval(datums, temp_storage, a_expr, b_expr);
2587            }
2588            BinaryFunc::AddDateTime(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2589            BinaryFunc::AddDateInterval(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2590            BinaryFunc::AddTimeInterval(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2591            BinaryFunc::AddNumeric(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2592            BinaryFunc::AgeTimestamp(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2593            BinaryFunc::AgeTimestampTz(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2594            BinaryFunc::BitAndInt16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2595            BinaryFunc::BitAndInt32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2596            BinaryFunc::BitAndInt64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2597            BinaryFunc::BitAndUint16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2598            BinaryFunc::BitAndUint32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2599            BinaryFunc::BitAndUint64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2600            BinaryFunc::BitOrInt16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2601            BinaryFunc::BitOrInt32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2602            BinaryFunc::BitOrInt64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2603            BinaryFunc::BitOrUint16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2604            BinaryFunc::BitOrUint32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2605            BinaryFunc::BitOrUint64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2606            BinaryFunc::BitXorInt16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2607            BinaryFunc::BitXorInt32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2608            BinaryFunc::BitXorInt64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2609            BinaryFunc::BitXorUint16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2610            BinaryFunc::BitXorUint32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2611            BinaryFunc::BitXorUint64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2612            BinaryFunc::BitShiftLeftInt16(s) => {
2613                return s.eval(datums, temp_storage, a_expr, b_expr);
2614            }
2615            BinaryFunc::BitShiftLeftInt32(s) => {
2616                return s.eval(datums, temp_storage, a_expr, b_expr);
2617            }
2618            BinaryFunc::BitShiftLeftInt64(s) => {
2619                return s.eval(datums, temp_storage, a_expr, b_expr);
2620            }
2621            BinaryFunc::BitShiftLeftUint16(s) => {
2622                return s.eval(datums, temp_storage, a_expr, b_expr);
2623            }
2624            BinaryFunc::BitShiftLeftUint32(s) => {
2625                return s.eval(datums, temp_storage, a_expr, b_expr);
2626            }
2627            BinaryFunc::BitShiftLeftUint64(s) => {
2628                return s.eval(datums, temp_storage, a_expr, b_expr);
2629            }
2630            BinaryFunc::BitShiftRightInt16(s) => {
2631                return s.eval(datums, temp_storage, a_expr, b_expr);
2632            }
2633            BinaryFunc::BitShiftRightInt32(s) => {
2634                return s.eval(datums, temp_storage, a_expr, b_expr);
2635            }
2636            BinaryFunc::BitShiftRightInt64(s) => {
2637                return s.eval(datums, temp_storage, a_expr, b_expr);
2638            }
2639            BinaryFunc::BitShiftRightUint16(s) => {
2640                return s.eval(datums, temp_storage, a_expr, b_expr);
2641            }
2642            BinaryFunc::BitShiftRightUint32(s) => {
2643                return s.eval(datums, temp_storage, a_expr, b_expr);
2644            }
2645            BinaryFunc::BitShiftRightUint64(s) => {
2646                return s.eval(datums, temp_storage, a_expr, b_expr);
2647            }
2648            BinaryFunc::SubInt16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2649            BinaryFunc::SubInt32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2650            BinaryFunc::SubInt64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2651            BinaryFunc::SubUint16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2652            BinaryFunc::SubUint32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2653            BinaryFunc::SubUint64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2654            BinaryFunc::SubFloat32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2655            BinaryFunc::SubFloat64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2656            BinaryFunc::SubTimestamp(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2657            BinaryFunc::SubTimestampTz(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2658            BinaryFunc::SubTimestampInterval(s) => {
2659                return s.eval(datums, temp_storage, a_expr, b_expr);
2660            }
2661            BinaryFunc::SubTimestampTzInterval(s) => {
2662                return s.eval(datums, temp_storage, a_expr, b_expr);
2663            }
2664            BinaryFunc::SubInterval(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2665            BinaryFunc::SubDate(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2666            BinaryFunc::SubDateInterval(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2667            BinaryFunc::SubTime(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2668            BinaryFunc::SubTimeInterval(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2669            BinaryFunc::SubNumeric(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2670            BinaryFunc::MulInt16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2671            BinaryFunc::MulInt32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2672            BinaryFunc::MulInt64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2673            BinaryFunc::MulUint16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2674            BinaryFunc::MulUint32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2675            BinaryFunc::MulUint64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2676            BinaryFunc::MulFloat32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2677            BinaryFunc::MulFloat64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2678            BinaryFunc::MulNumeric(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2679            BinaryFunc::MulInterval(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2680            BinaryFunc::DivInt16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2681            BinaryFunc::DivInt32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2682            BinaryFunc::DivInt64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2683            BinaryFunc::DivUint16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2684            BinaryFunc::DivUint32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2685            BinaryFunc::DivUint64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2686            BinaryFunc::DivFloat32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2687            BinaryFunc::DivFloat64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2688            BinaryFunc::DivNumeric(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2689            BinaryFunc::DivInterval(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2690            BinaryFunc::ModInt16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2691            BinaryFunc::ModInt32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2692            BinaryFunc::ModInt64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2693            BinaryFunc::ModUint16(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2694            BinaryFunc::ModUint32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2695            BinaryFunc::ModUint64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2696            BinaryFunc::ModFloat32(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2697            BinaryFunc::ModFloat64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2698            BinaryFunc::ModNumeric(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2699            BinaryFunc::Eq(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2700            BinaryFunc::NotEq(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2701            BinaryFunc::Lt(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2702            BinaryFunc::Lte(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2703            BinaryFunc::Gt(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2704            BinaryFunc::Gte(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2705            BinaryFunc::LikeEscape(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2706            BinaryFunc::IsLikeMatchCaseInsensitive(s) => {
2707                return s.eval(datums, temp_storage, a_expr, b_expr);
2708            }
2709            BinaryFunc::IsLikeMatchCaseSensitive(s) => {
2710                return s.eval(datums, temp_storage, a_expr, b_expr);
2711            }
2712            // BinaryFunc::IsRegexpMatch { case_insensitive } => {
2713            //     is_regexp_match_dynamic(a, b, *case_insensitive)
2714            // }
2715            BinaryFunc::ToCharTimestamp(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2716            BinaryFunc::ToCharTimestampTz(s) => {
2717                return s.eval(datums, temp_storage, a_expr, b_expr);
2718            }
2719            BinaryFunc::DateBinTimestamp(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2720            BinaryFunc::DateBinTimestampTz(s) => {
2721                return s.eval(datums, temp_storage, a_expr, b_expr);
2722            }
2723            BinaryFunc::ExtractInterval(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2724            BinaryFunc::ExtractTime(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2725            BinaryFunc::ExtractTimestamp(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2726            BinaryFunc::ExtractTimestampTz(s) => {
2727                return s.eval(datums, temp_storage, a_expr, b_expr);
2728            }
2729            BinaryFunc::ExtractDate(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2730            BinaryFunc::DatePartInterval(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2731            BinaryFunc::DatePartTime(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2732            BinaryFunc::DatePartTimestamp(s) => {
2733                return s.eval(datums, temp_storage, a_expr, b_expr);
2734            }
2735            BinaryFunc::DatePartTimestampTz(s) => {
2736                return s.eval(datums, temp_storage, a_expr, b_expr);
2737            }
2738            BinaryFunc::DateTruncTimestamp(s) => {
2739                return s.eval(datums, temp_storage, a_expr, b_expr);
2740            }
2741            BinaryFunc::DateTruncInterval(s) => {
2742                return s.eval(datums, temp_storage, a_expr, b_expr);
2743            }
2744            BinaryFunc::DateTruncTimestampTz(s) => {
2745                return s.eval(datums, temp_storage, a_expr, b_expr);
2746            }
2747            // BinaryFunc::TimezoneTimestamp(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2748            // BinaryFunc::TimezoneTimestampTz(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2749            // BinaryFunc::TimezoneIntervalTimestamp(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2750            // BinaryFunc::TimezoneIntervalTimestampTz(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2751            // BinaryFunc::TimezoneIntervalTime(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2752            BinaryFunc::TimezoneOffset(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2753            BinaryFunc::TextConcat(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2754            BinaryFunc::JsonbGetInt64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2755            BinaryFunc::JsonbGetInt64Stringify(s) => {
2756                return s.eval(datums, temp_storage, a_expr, b_expr);
2757            }
2758            BinaryFunc::JsonbGetString(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2759            BinaryFunc::JsonbGetStringStringify(s) => {
2760                return s.eval(datums, temp_storage, a_expr, b_expr);
2761            }
2762            BinaryFunc::JsonbGetPath(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2763            BinaryFunc::JsonbGetPathStringify(s) => {
2764                return s.eval(datums, temp_storage, a_expr, b_expr);
2765            }
2766            BinaryFunc::JsonbContainsString(s) => {
2767                return s.eval(datums, temp_storage, a_expr, b_expr);
2768            }
2769            BinaryFunc::JsonbConcat(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2770            BinaryFunc::JsonbContainsJsonb(s) => {
2771                return s.eval(datums, temp_storage, a_expr, b_expr);
2772            }
2773            BinaryFunc::JsonbDeleteInt64(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2774            BinaryFunc::JsonbDeleteString(s) => {
2775                return s.eval(datums, temp_storage, a_expr, b_expr);
2776            }
2777            BinaryFunc::MapContainsKey(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2778            BinaryFunc::MapGetValue(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2779            BinaryFunc::MapContainsAllKeys(s) => {
2780                return s.eval(datums, temp_storage, a_expr, b_expr);
2781            }
2782            BinaryFunc::MapContainsAnyKeys(s) => {
2783                return s.eval(datums, temp_storage, a_expr, b_expr);
2784            }
2785            BinaryFunc::MapContainsMap(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2786            BinaryFunc::RoundNumeric(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2787            BinaryFunc::ConvertFrom(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2788            BinaryFunc::Encode(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2789            BinaryFunc::Decode(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2790            BinaryFunc::Left(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2791            BinaryFunc::Position(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2792            BinaryFunc::Right(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2793            BinaryFunc::Trim(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2794            BinaryFunc::TrimLeading(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2795            BinaryFunc::TrimTrailing(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2796            BinaryFunc::EncodedBytesCharLength(s) => {
2797                return s.eval(datums, temp_storage, a_expr, b_expr);
2798            }
2799            BinaryFunc::ListLengthMax(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2800            BinaryFunc::ArrayLength(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2801            BinaryFunc::ArrayContains(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2802            BinaryFunc::ArrayContainsArray(s) => {
2803                return s.eval(datums, temp_storage, a_expr, b_expr);
2804            }
2805            BinaryFunc::ArrayContainsArrayRev(s) => {
2806                return s.eval(datums, temp_storage, a_expr, b_expr);
2807            }
2808            BinaryFunc::ArrayLower(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2809            BinaryFunc::ArrayRemove(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2810            BinaryFunc::ArrayUpper(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2811            BinaryFunc::ArrayArrayConcat(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2812            BinaryFunc::ListListConcat(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2813            BinaryFunc::ListElementConcat(s) => {
2814                return s.eval(datums, temp_storage, a_expr, b_expr);
2815            }
2816            BinaryFunc::ElementListConcat(s) => {
2817                return s.eval(datums, temp_storage, a_expr, b_expr);
2818            }
2819            BinaryFunc::ListRemove(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2820            BinaryFunc::ListContainsList(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2821            BinaryFunc::ListContainsListRev(s) => {
2822                return s.eval(datums, temp_storage, a_expr, b_expr);
2823            }
2824            BinaryFunc::DigestString(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2825            BinaryFunc::DigestBytes(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2826            BinaryFunc::MzRenderTypmod(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2827            BinaryFunc::LogNumeric(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2828            BinaryFunc::Power(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2829            BinaryFunc::PowerNumeric(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2830            // BinaryFunc::RepeatString(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2831            // BinaryFunc::Normalize(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2832            BinaryFunc::GetBit(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2833            BinaryFunc::GetByte(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2834            BinaryFunc::ConstantTimeEqBytes(s) => {
2835                return s.eval(datums, temp_storage, a_expr, b_expr);
2836            }
2837            BinaryFunc::ConstantTimeEqString(s) => {
2838                return s.eval(datums, temp_storage, a_expr, b_expr);
2839            }
2840            // BinaryFunc::RangeContainsElem { elem_type, rev: _ } => Ok(match elem_type {
2841            //     SqlScalarType::Int32 => contains_range_elem::<i32>(a, b),
2842            //     SqlScalarType::Int64 => contains_range_elem::<i64>(a, b),
2843            //     SqlScalarType::Date => contains_range_elem::<Date>(a, b),
2844            //     SqlScalarType::Numeric { .. } => {
2845            //         contains_range_elem::<OrderedDecimal<Numeric>>(a, b)
2846            //     }
2847            //     SqlScalarType::Timestamp { .. } => {
2848            //         contains_range_elem::<CheckedTimestamp<NaiveDateTime>>(a, b)
2849            //     }
2850            //     SqlScalarType::TimestampTz { .. } => {
2851            //         contains_range_elem::<CheckedTimestamp<DateTime<Utc>>>(a, b)
2852            //     }
2853            //     _ => unreachable!(),
2854            // }),
2855            BinaryFunc::RangeContainsRange(s) => {
2856                return s.eval(datums, temp_storage, a_expr, b_expr);
2857            }
2858            BinaryFunc::RangeContainsRangeRev(s) => {
2859                return s.eval(datums, temp_storage, a_expr, b_expr);
2860            }
2861            BinaryFunc::RangeOverlaps(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2862            BinaryFunc::RangeAfter(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2863            BinaryFunc::RangeBefore(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2864            BinaryFunc::RangeOverleft(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2865            BinaryFunc::RangeOverright(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2866            BinaryFunc::RangeAdjacent(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2867            BinaryFunc::RangeUnion(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2868            BinaryFunc::RangeIntersection(s) => {
2869                return s.eval(datums, temp_storage, a_expr, b_expr);
2870            }
2871            BinaryFunc::RangeDifference(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2872            BinaryFunc::UuidGenerateV5(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2873            BinaryFunc::MzAclItemContainsPrivilege(s) => {
2874                return s.eval(datums, temp_storage, a_expr, b_expr);
2875            }
2876            BinaryFunc::ParseIdent(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2877            BinaryFunc::PrettySql(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2878            // BinaryFunc::RegexpReplace { regex, limit } => {
2879            //     regexp_replace_static(a, b, regex, *limit, temp_storage)
2880            // }
2881            BinaryFunc::StartsWith(s) => return s.eval(datums, temp_storage, a_expr, b_expr),
2882            _ => { /* fall through */ }
2883        }
2884
2885        let a = a_expr.eval(datums, temp_storage)?;
2886        let b = b_expr.eval(datums, temp_storage)?;
2887        if self.propagates_nulls() && (a.is_null() || b.is_null()) {
2888            return Ok(Datum::Null);
2889        }
2890        match self {
2891            BinaryFunc::IsRegexpMatch { case_insensitive } => {
2892                is_regexp_match_dynamic(a, b, *case_insensitive)
2893            }
2894            BinaryFunc::TimezoneTimestamp => parse_timezone(a.unwrap_str(), TimezoneSpec::Posix)
2895                .and_then(|tz| timezone_timestamp(tz, b.unwrap_timestamp().into()).map(Into::into)),
2896            BinaryFunc::TimezoneTimestampTz => parse_timezone(a.unwrap_str(), TimezoneSpec::Posix)
2897                .and_then(|tz| {
2898                    Ok(timezone_timestamptz(tz, b.unwrap_timestamptz().into())?.try_into()?)
2899                }),
2900            BinaryFunc::TimezoneIntervalTimestamp => timezone_interval_timestamp(a, b),
2901            BinaryFunc::TimezoneIntervalTimestampTz => timezone_interval_timestamptz(a, b),
2902            BinaryFunc::TimezoneIntervalTime => timezone_interval_time(a, b),
2903            BinaryFunc::RepeatString => repeat_string(a, b, temp_storage),
2904            BinaryFunc::Normalize => normalize_with_form(a, b, temp_storage),
2905            BinaryFunc::RangeContainsElem { elem_type, rev: _ } => Ok(match elem_type {
2906                SqlScalarType::Int32 => contains_range_elem::<i32>(a, b),
2907                SqlScalarType::Int64 => contains_range_elem::<i64>(a, b),
2908                SqlScalarType::Date => contains_range_elem::<Date>(a, b),
2909                SqlScalarType::Numeric { .. } => {
2910                    contains_range_elem::<OrderedDecimal<Numeric>>(a, b)
2911                }
2912                SqlScalarType::Timestamp { .. } => {
2913                    contains_range_elem::<CheckedTimestamp<NaiveDateTime>>(a, b)
2914                }
2915                SqlScalarType::TimestampTz { .. } => {
2916                    contains_range_elem::<CheckedTimestamp<DateTime<Utc>>>(a, b)
2917                }
2918                _ => unreachable!(),
2919            }),
2920            BinaryFunc::RegexpReplace { regex, limit } => {
2921                regexp_replace_static(a, b, regex, *limit, temp_storage)
2922            }
2923            _ => unreachable!(),
2924        }
2925    }
2926
2927    pub fn output_type(
2928        &self,
2929        input1_type: SqlColumnType,
2930        input2_type: SqlColumnType,
2931    ) -> SqlColumnType {
2932        use BinaryFunc::*;
2933        let in_nullable = input1_type.nullable || input2_type.nullable;
2934        match self {
2935            AddInt16(s) => s.output_type(input1_type, input2_type),
2936            AddInt32(s) => s.output_type(input1_type, input2_type),
2937            AddInt64(s) => s.output_type(input1_type, input2_type),
2938            AddUint16(s) => s.output_type(input1_type, input2_type),
2939            AddUint32(s) => s.output_type(input1_type, input2_type),
2940            AddUint64(s) => s.output_type(input1_type, input2_type),
2941            AddFloat32(s) => s.output_type(input1_type, input2_type),
2942            AddFloat64(s) => s.output_type(input1_type, input2_type),
2943            AddInterval(s) => s.output_type(input1_type, input2_type),
2944
2945            Eq(s) => s.output_type(input1_type, input2_type),
2946            NotEq(s) => s.output_type(input1_type, input2_type),
2947            Lt(s) => s.output_type(input1_type, input2_type),
2948            Lte(s) => s.output_type(input1_type, input2_type),
2949            Gt(s) => s.output_type(input1_type, input2_type),
2950            Gte(s) => s.output_type(input1_type, input2_type),
2951            ArrayContains(s) => s.output_type(input1_type, input2_type),
2952            ArrayContainsArray(s) => s.output_type(input1_type, input2_type),
2953            ArrayContainsArrayRev(s) => s.output_type(input1_type, input2_type),
2954            // like and regexp produce errors on invalid like-strings or regexes
2955            IsLikeMatchCaseInsensitive(s) => s.output_type(input1_type, input2_type),
2956            IsLikeMatchCaseSensitive(s) => s.output_type(input1_type, input2_type),
2957            IsRegexpMatch { .. } => SqlScalarType::Bool.nullable(in_nullable),
2958
2959            ToCharTimestamp(s) => s.output_type(input1_type, input2_type),
2960            ToCharTimestampTz(s) => s.output_type(input1_type, input2_type),
2961            ConvertFrom(s) => s.output_type(input1_type, input2_type),
2962            Left(s) => s.output_type(input1_type, input2_type),
2963            Right(s) => s.output_type(input1_type, input2_type),
2964            Trim(s) => s.output_type(input1_type, input2_type),
2965            TrimLeading(s) => s.output_type(input1_type, input2_type),
2966            TrimTrailing(s) => s.output_type(input1_type, input2_type),
2967            LikeEscape(s) => s.output_type(input1_type, input2_type),
2968
2969            SubInt16(s) => s.output_type(input1_type, input2_type),
2970            MulInt16(s) => s.output_type(input1_type, input2_type),
2971            DivInt16(s) => s.output_type(input1_type, input2_type),
2972            ModInt16(s) => s.output_type(input1_type, input2_type),
2973            BitAndInt16(s) => s.output_type(input1_type, input2_type),
2974            BitOrInt16(s) => s.output_type(input1_type, input2_type),
2975            BitXorInt16(s) => s.output_type(input1_type, input2_type),
2976            BitShiftLeftInt16(s) => s.output_type(input1_type, input2_type),
2977            BitShiftRightInt16(s) => s.output_type(input1_type, input2_type),
2978
2979            SubInt32(s) => s.output_type(input1_type, input2_type),
2980            MulInt32(s) => s.output_type(input1_type, input2_type),
2981            DivInt32(s) => s.output_type(input1_type, input2_type),
2982            ModInt32(s) => s.output_type(input1_type, input2_type),
2983            BitAndInt32(s) => s.output_type(input1_type, input2_type),
2984            BitOrInt32(s) => s.output_type(input1_type, input2_type),
2985            BitXorInt32(s) => s.output_type(input1_type, input2_type),
2986            BitShiftLeftInt32(s) => s.output_type(input1_type, input2_type),
2987            BitShiftRightInt32(s) => s.output_type(input1_type, input2_type),
2988            EncodedBytesCharLength(s) => s.output_type(input1_type, input2_type),
2989            SubDate(s) => s.output_type(input1_type, input2_type),
2990
2991            SubInt64(s) => s.output_type(input1_type, input2_type),
2992            MulInt64(s) => s.output_type(input1_type, input2_type),
2993            DivInt64(s) => s.output_type(input1_type, input2_type),
2994            ModInt64(s) => s.output_type(input1_type, input2_type),
2995            BitAndInt64(s) => s.output_type(input1_type, input2_type),
2996            BitOrInt64(s) => s.output_type(input1_type, input2_type),
2997            BitXorInt64(s) => s.output_type(input1_type, input2_type),
2998            BitShiftLeftInt64(s) => s.output_type(input1_type, input2_type),
2999            BitShiftRightInt64(s) => s.output_type(input1_type, input2_type),
3000
3001            SubUint16(s) => s.output_type(input1_type, input2_type),
3002            MulUint16(s) => s.output_type(input1_type, input2_type),
3003            DivUint16(s) => s.output_type(input1_type, input2_type),
3004            ModUint16(s) => s.output_type(input1_type, input2_type),
3005            BitAndUint16(s) => s.output_type(input1_type, input2_type),
3006            BitOrUint16(s) => s.output_type(input1_type, input2_type),
3007            BitXorUint16(s) => s.output_type(input1_type, input2_type),
3008            BitShiftLeftUint16(s) => s.output_type(input1_type, input2_type),
3009            BitShiftRightUint16(s) => s.output_type(input1_type, input2_type),
3010
3011            SubUint32(s) => s.output_type(input1_type, input2_type),
3012            MulUint32(s) => s.output_type(input1_type, input2_type),
3013            DivUint32(s) => s.output_type(input1_type, input2_type),
3014            ModUint32(s) => s.output_type(input1_type, input2_type),
3015            BitAndUint32(s) => s.output_type(input1_type, input2_type),
3016            BitOrUint32(s) => s.output_type(input1_type, input2_type),
3017            BitXorUint32(s) => s.output_type(input1_type, input2_type),
3018            BitShiftLeftUint32(s) => s.output_type(input1_type, input2_type),
3019            BitShiftRightUint32(s) => s.output_type(input1_type, input2_type),
3020
3021            SubUint64(s) => s.output_type(input1_type, input2_type),
3022            MulUint64(s) => s.output_type(input1_type, input2_type),
3023            DivUint64(s) => s.output_type(input1_type, input2_type),
3024            ModUint64(s) => s.output_type(input1_type, input2_type),
3025            BitAndUint64(s) => s.output_type(input1_type, input2_type),
3026            BitOrUint64(s) => s.output_type(input1_type, input2_type),
3027            BitXorUint64(s) => s.output_type(input1_type, input2_type),
3028            BitShiftLeftUint64(s) => s.output_type(input1_type, input2_type),
3029            BitShiftRightUint64(s) => s.output_type(input1_type, input2_type),
3030
3031            SubFloat32(s) => s.output_type(input1_type, input2_type),
3032            MulFloat32(s) => s.output_type(input1_type, input2_type),
3033            DivFloat32(s) => s.output_type(input1_type, input2_type),
3034            ModFloat32(s) => s.output_type(input1_type, input2_type),
3035
3036            SubFloat64(s) => s.output_type(input1_type, input2_type),
3037            MulFloat64(s) => s.output_type(input1_type, input2_type),
3038            DivFloat64(s) => s.output_type(input1_type, input2_type),
3039            ModFloat64(s) => s.output_type(input1_type, input2_type),
3040
3041            SubInterval(s) => s.output_type(input1_type, input2_type),
3042            SubTimestamp(s) => s.output_type(input1_type, input2_type),
3043            SubTimestampTz(s) => s.output_type(input1_type, input2_type),
3044            MulInterval(s) => s.output_type(input1_type, input2_type),
3045            DivInterval(s) => s.output_type(input1_type, input2_type),
3046
3047            AgeTimestamp(s) => s.output_type(input1_type, input2_type),
3048            AgeTimestampTz(s) => s.output_type(input1_type, input2_type),
3049
3050            AddTimestampInterval(s) => s.output_type(input1_type, input2_type),
3051            SubTimestampInterval(s) => s.output_type(input1_type, input2_type),
3052            AddTimestampTzInterval(s) => s.output_type(input1_type, input2_type),
3053            SubTimestampTzInterval(s) => s.output_type(input1_type, input2_type),
3054            AddTimeInterval(s) => s.output_type(input1_type, input2_type),
3055            SubTimeInterval(s) => s.output_type(input1_type, input2_type),
3056
3057            AddDateInterval(s) => s.output_type(input1_type, input2_type),
3058            SubDateInterval(s) => s.output_type(input1_type, input2_type),
3059            AddDateTime(s) => s.output_type(input1_type, input2_type),
3060            DateBinTimestamp(s) => s.output_type(input1_type, input2_type),
3061            DateTruncTimestamp(s) => s.output_type(input1_type, input2_type),
3062
3063            DateTruncInterval(s) => s.output_type(input1_type, input2_type),
3064
3065            TimezoneTimestampTz | TimezoneIntervalTimestampTz => {
3066                SqlScalarType::Timestamp { precision: None }.nullable(in_nullable)
3067            }
3068
3069            ExtractInterval(s) => s.output_type(input1_type, input2_type),
3070            ExtractTime(s) => s.output_type(input1_type, input2_type),
3071            ExtractTimestamp(s) => s.output_type(input1_type, input2_type),
3072            ExtractTimestampTz(s) => s.output_type(input1_type, input2_type),
3073            ExtractDate(s) => s.output_type(input1_type, input2_type),
3074
3075            DatePartInterval(s) => s.output_type(input1_type, input2_type),
3076            DatePartTime(s) => s.output_type(input1_type, input2_type),
3077            DatePartTimestamp(s) => s.output_type(input1_type, input2_type),
3078            DatePartTimestampTz(s) => s.output_type(input1_type, input2_type),
3079
3080            DateBinTimestampTz(s) => s.output_type(input1_type, input2_type),
3081            DateTruncTimestampTz(s) => s.output_type(input1_type, input2_type),
3082
3083            TimezoneTimestamp | TimezoneIntervalTimestamp => {
3084                SqlScalarType::TimestampTz { precision: None }.nullable(in_nullable)
3085            }
3086
3087            TimezoneIntervalTime => SqlScalarType::Time.nullable(in_nullable),
3088
3089            TimezoneOffset(s) => s.output_type(input1_type, input2_type),
3090
3091            SubTime(s) => s.output_type(input1_type, input2_type),
3092
3093            MzRenderTypmod(s) => s.output_type(input1_type, input2_type),
3094            TextConcat(s) => s.output_type(input1_type, input2_type),
3095
3096            JsonbGetInt64Stringify(s) => s.output_type(input1_type, input2_type),
3097            JsonbGetStringStringify(s) => s.output_type(input1_type, input2_type),
3098            JsonbGetPathStringify(s) => s.output_type(input1_type, input2_type),
3099
3100            JsonbGetInt64(s) => s.output_type(input1_type, input2_type),
3101            JsonbGetString(s) => s.output_type(input1_type, input2_type),
3102            JsonbGetPath(s) => s.output_type(input1_type, input2_type),
3103            JsonbConcat(s) => s.output_type(input1_type, input2_type),
3104            JsonbDeleteInt64(s) => s.output_type(input1_type, input2_type),
3105            JsonbDeleteString(s) => s.output_type(input1_type, input2_type),
3106
3107            JsonbContainsString(s) => s.output_type(input1_type, input2_type),
3108            JsonbContainsJsonb(s) => s.output_type(input1_type, input2_type),
3109            MapContainsKey(s) => s.output_type(input1_type, input2_type),
3110            MapContainsAllKeys(s) => s.output_type(input1_type, input2_type),
3111            MapContainsAnyKeys(s) => s.output_type(input1_type, input2_type),
3112            MapContainsMap(s) => s.output_type(input1_type, input2_type),
3113
3114            MapGetValue(s) => s.output_type(input1_type, input2_type),
3115
3116            ArrayLength(s) => s.output_type(input1_type, input2_type),
3117            ArrayLower(s) => s.output_type(input1_type, input2_type),
3118            ArrayUpper(s) => s.output_type(input1_type, input2_type),
3119
3120            ListLengthMax(s) => s.output_type(input1_type, input2_type),
3121
3122            ArrayArrayConcat(s) => s.output_type(input1_type, input2_type),
3123            ArrayRemove(s) => s.output_type(input1_type, input2_type),
3124            ListListConcat(s) => s.output_type(input1_type, input2_type),
3125            ListElementConcat(s) => s.output_type(input1_type, input2_type),
3126            ListRemove(s) => s.output_type(input1_type, input2_type),
3127
3128            ElementListConcat(s) => s.output_type(input1_type, input2_type),
3129
3130            ListContainsList(s) => s.output_type(input1_type, input2_type),
3131            ListContainsListRev(s) => s.output_type(input1_type, input2_type),
3132
3133            DigestString(s) => s.output_type(input1_type, input2_type),
3134            DigestBytes(s) => s.output_type(input1_type, input2_type),
3135            Position(s) => s.output_type(input1_type, input2_type),
3136            Encode(s) => s.output_type(input1_type, input2_type),
3137            Decode(s) => s.output_type(input1_type, input2_type),
3138            Power(s) => s.output_type(input1_type, input2_type),
3139            RepeatString | Normalize => input1_type.scalar_type.nullable(in_nullable),
3140
3141            AddNumeric(s) => s.output_type(input1_type, input2_type),
3142            DivNumeric(s) => s.output_type(input1_type, input2_type),
3143            LogNumeric(s) => s.output_type(input1_type, input2_type),
3144            ModNumeric(s) => s.output_type(input1_type, input2_type),
3145            MulNumeric(s) => s.output_type(input1_type, input2_type),
3146            PowerNumeric(s) => s.output_type(input1_type, input2_type),
3147            RoundNumeric(s) => s.output_type(input1_type, input2_type),
3148            SubNumeric(s) => s.output_type(input1_type, input2_type),
3149
3150            GetBit(s) => s.output_type(input1_type, input2_type),
3151            GetByte(s) => s.output_type(input1_type, input2_type),
3152
3153            ConstantTimeEqBytes(s) => s.output_type(input1_type, input2_type),
3154            ConstantTimeEqString(s) => s.output_type(input1_type, input2_type),
3155
3156            UuidGenerateV5(s) => s.output_type(input1_type, input2_type),
3157
3158            RangeContainsElem { .. } => SqlScalarType::Bool.nullable(in_nullable),
3159            RangeContainsRange(s) => s.output_type(input1_type, input2_type),
3160            RangeContainsRangeRev(s) => s.output_type(input1_type, input2_type),
3161            RangeOverlaps(s) => s.output_type(input1_type, input2_type),
3162            RangeAfter(s) => s.output_type(input1_type, input2_type),
3163            RangeBefore(s) => s.output_type(input1_type, input2_type),
3164            RangeOverleft(s) => s.output_type(input1_type, input2_type),
3165            RangeOverright(s) => s.output_type(input1_type, input2_type),
3166            RangeAdjacent(s) => s.output_type(input1_type, input2_type),
3167
3168            RangeUnion(s) => s.output_type(input1_type, input2_type),
3169            RangeIntersection(s) => s.output_type(input1_type, input2_type),
3170            RangeDifference(s) => s.output_type(input1_type, input2_type),
3171
3172            MzAclItemContainsPrivilege(s) => s.output_type(input1_type, input2_type),
3173
3174            ParseIdent(s) => s.output_type(input1_type, input2_type),
3175            PrettySql(s) => s.output_type(input1_type, input2_type),
3176            RegexpReplace { .. } => SqlScalarType::String.nullable(in_nullable),
3177
3178            StartsWith(s) => s.output_type(input1_type, input2_type),
3179        }
3180    }
3181
3182    /// Whether the function output is NULL if any of its inputs are NULL.
3183    pub fn propagates_nulls(&self) -> bool {
3184        match self {
3185            BinaryFunc::AddDateInterval(s) => s.propagates_nulls(),
3186            BinaryFunc::AddDateTime(s) => s.propagates_nulls(),
3187            BinaryFunc::AddFloat32(s) => s.propagates_nulls(),
3188            BinaryFunc::AddFloat64(s) => s.propagates_nulls(),
3189            BinaryFunc::AddInt16(s) => s.propagates_nulls(),
3190            BinaryFunc::AddInt32(s) => s.propagates_nulls(),
3191            BinaryFunc::AddInt64(s) => s.propagates_nulls(),
3192            BinaryFunc::AddInterval(s) => s.propagates_nulls(),
3193            BinaryFunc::AddNumeric(s) => s.propagates_nulls(),
3194            BinaryFunc::AddTimeInterval(s) => s.propagates_nulls(),
3195            BinaryFunc::AddTimestampInterval(s) => s.propagates_nulls(),
3196            BinaryFunc::AddTimestampTzInterval(s) => s.propagates_nulls(),
3197            BinaryFunc::AddUint16(s) => s.propagates_nulls(),
3198            BinaryFunc::AddUint32(s) => s.propagates_nulls(),
3199            BinaryFunc::AddUint64(s) => s.propagates_nulls(),
3200            BinaryFunc::AgeTimestamp(s) => s.propagates_nulls(),
3201            BinaryFunc::AgeTimestampTz(s) => s.propagates_nulls(),
3202            BinaryFunc::ArrayArrayConcat(s) => s.propagates_nulls(),
3203            BinaryFunc::ArrayContains(s) => s.propagates_nulls(),
3204            BinaryFunc::ArrayContainsArray(s) => s.propagates_nulls(),
3205            BinaryFunc::ArrayContainsArrayRev(s) => s.propagates_nulls(),
3206            BinaryFunc::ArrayLength(s) => s.propagates_nulls(),
3207            BinaryFunc::ArrayLower(s) => s.propagates_nulls(),
3208            BinaryFunc::ArrayRemove(s) => s.propagates_nulls(),
3209            BinaryFunc::ArrayUpper(s) => s.propagates_nulls(),
3210            BinaryFunc::BitAndInt16(s) => s.propagates_nulls(),
3211            BinaryFunc::BitAndInt32(s) => s.propagates_nulls(),
3212            BinaryFunc::BitAndInt64(s) => s.propagates_nulls(),
3213            BinaryFunc::BitAndUint16(s) => s.propagates_nulls(),
3214            BinaryFunc::BitAndUint32(s) => s.propagates_nulls(),
3215            BinaryFunc::BitAndUint64(s) => s.propagates_nulls(),
3216            BinaryFunc::BitOrInt16(s) => s.propagates_nulls(),
3217            BinaryFunc::BitOrInt32(s) => s.propagates_nulls(),
3218            BinaryFunc::BitOrInt64(s) => s.propagates_nulls(),
3219            BinaryFunc::BitOrUint16(s) => s.propagates_nulls(),
3220            BinaryFunc::BitOrUint32(s) => s.propagates_nulls(),
3221            BinaryFunc::BitOrUint64(s) => s.propagates_nulls(),
3222            BinaryFunc::BitShiftLeftInt16(s) => s.propagates_nulls(),
3223            BinaryFunc::BitShiftLeftInt32(s) => s.propagates_nulls(),
3224            BinaryFunc::BitShiftLeftInt64(s) => s.propagates_nulls(),
3225            BinaryFunc::BitShiftLeftUint16(s) => s.propagates_nulls(),
3226            BinaryFunc::BitShiftLeftUint32(s) => s.propagates_nulls(),
3227            BinaryFunc::BitShiftLeftUint64(s) => s.propagates_nulls(),
3228            BinaryFunc::BitShiftRightInt16(s) => s.propagates_nulls(),
3229            BinaryFunc::BitShiftRightInt32(s) => s.propagates_nulls(),
3230            BinaryFunc::BitShiftRightInt64(s) => s.propagates_nulls(),
3231            BinaryFunc::BitShiftRightUint16(s) => s.propagates_nulls(),
3232            BinaryFunc::BitShiftRightUint32(s) => s.propagates_nulls(),
3233            BinaryFunc::BitShiftRightUint64(s) => s.propagates_nulls(),
3234            BinaryFunc::BitXorInt16(s) => s.propagates_nulls(),
3235            BinaryFunc::BitXorInt32(s) => s.propagates_nulls(),
3236            BinaryFunc::BitXorInt64(s) => s.propagates_nulls(),
3237            BinaryFunc::BitXorUint16(s) => s.propagates_nulls(),
3238            BinaryFunc::BitXorUint32(s) => s.propagates_nulls(),
3239            BinaryFunc::BitXorUint64(s) => s.propagates_nulls(),
3240            BinaryFunc::ConstantTimeEqBytes(s) => s.propagates_nulls(),
3241            BinaryFunc::ConstantTimeEqString(s) => s.propagates_nulls(),
3242            BinaryFunc::ConvertFrom(s) => s.propagates_nulls(),
3243            BinaryFunc::DateBinTimestamp(s) => s.propagates_nulls(),
3244            BinaryFunc::DateBinTimestampTz(s) => s.propagates_nulls(),
3245            BinaryFunc::DatePartInterval(s) => s.propagates_nulls(),
3246            BinaryFunc::DatePartTime(s) => s.propagates_nulls(),
3247            BinaryFunc::DatePartTimestamp(s) => s.propagates_nulls(),
3248            BinaryFunc::DatePartTimestampTz(s) => s.propagates_nulls(),
3249            BinaryFunc::DateTruncInterval(s) => s.propagates_nulls(),
3250            BinaryFunc::DateTruncTimestamp(s) => s.propagates_nulls(),
3251            BinaryFunc::DateTruncTimestampTz(s) => s.propagates_nulls(),
3252            BinaryFunc::Decode(s) => s.propagates_nulls(),
3253            BinaryFunc::DigestBytes(s) => s.propagates_nulls(),
3254            BinaryFunc::DigestString(s) => s.propagates_nulls(),
3255            BinaryFunc::DivFloat32(s) => s.propagates_nulls(),
3256            BinaryFunc::DivFloat64(s) => s.propagates_nulls(),
3257            BinaryFunc::DivInt16(s) => s.propagates_nulls(),
3258            BinaryFunc::DivInt32(s) => s.propagates_nulls(),
3259            BinaryFunc::DivInt64(s) => s.propagates_nulls(),
3260            BinaryFunc::DivInterval(s) => s.propagates_nulls(),
3261            BinaryFunc::DivNumeric(s) => s.propagates_nulls(),
3262            BinaryFunc::DivUint16(s) => s.propagates_nulls(),
3263            BinaryFunc::DivUint32(s) => s.propagates_nulls(),
3264            BinaryFunc::DivUint64(s) => s.propagates_nulls(),
3265            BinaryFunc::ElementListConcat(s) => s.propagates_nulls(),
3266            BinaryFunc::Encode(s) => s.propagates_nulls(),
3267            BinaryFunc::EncodedBytesCharLength(s) => s.propagates_nulls(),
3268            BinaryFunc::Eq(s) => s.propagates_nulls(),
3269            BinaryFunc::ExtractDate(s) => s.propagates_nulls(),
3270            BinaryFunc::ExtractInterval(s) => s.propagates_nulls(),
3271            BinaryFunc::ExtractTime(s) => s.propagates_nulls(),
3272            BinaryFunc::ExtractTimestamp(s) => s.propagates_nulls(),
3273            BinaryFunc::ExtractTimestampTz(s) => s.propagates_nulls(),
3274            BinaryFunc::GetBit(s) => s.propagates_nulls(),
3275            BinaryFunc::GetByte(s) => s.propagates_nulls(),
3276            BinaryFunc::Gt(s) => s.propagates_nulls(),
3277            BinaryFunc::Gte(s) => s.propagates_nulls(),
3278            BinaryFunc::IsLikeMatchCaseInsensitive(s) => s.propagates_nulls(),
3279            BinaryFunc::IsLikeMatchCaseSensitive(s) => s.propagates_nulls(),
3280            BinaryFunc::IsRegexpMatch { .. } => true,
3281            BinaryFunc::JsonbConcat(s) => s.propagates_nulls(),
3282            BinaryFunc::JsonbContainsJsonb(s) => s.propagates_nulls(),
3283            BinaryFunc::JsonbContainsString(s) => s.propagates_nulls(),
3284            BinaryFunc::JsonbDeleteInt64(s) => s.propagates_nulls(),
3285            BinaryFunc::JsonbDeleteString(s) => s.propagates_nulls(),
3286            BinaryFunc::JsonbGetInt64(s) => s.propagates_nulls(),
3287            BinaryFunc::JsonbGetInt64Stringify(s) => s.propagates_nulls(),
3288            BinaryFunc::JsonbGetPath(s) => s.propagates_nulls(),
3289            BinaryFunc::JsonbGetPathStringify(s) => s.propagates_nulls(),
3290            BinaryFunc::JsonbGetString(s) => s.propagates_nulls(),
3291            BinaryFunc::JsonbGetStringStringify(s) => s.propagates_nulls(),
3292            BinaryFunc::Left(s) => s.propagates_nulls(),
3293            BinaryFunc::LikeEscape(s) => s.propagates_nulls(),
3294            BinaryFunc::ListContainsList(s) => s.propagates_nulls(),
3295            BinaryFunc::ListContainsListRev(s) => s.propagates_nulls(),
3296            BinaryFunc::ListElementConcat(s) => s.propagates_nulls(),
3297            BinaryFunc::ListLengthMax(s) => s.propagates_nulls(),
3298            BinaryFunc::ListListConcat(s) => s.propagates_nulls(),
3299            BinaryFunc::ListRemove(s) => s.propagates_nulls(),
3300            BinaryFunc::LogNumeric(s) => s.propagates_nulls(),
3301            BinaryFunc::Lt(s) => s.propagates_nulls(),
3302            BinaryFunc::Lte(s) => s.propagates_nulls(),
3303            BinaryFunc::MapContainsAllKeys(s) => s.propagates_nulls(),
3304            BinaryFunc::MapContainsAnyKeys(s) => s.propagates_nulls(),
3305            BinaryFunc::MapContainsKey(s) => s.propagates_nulls(),
3306            BinaryFunc::MapContainsMap(s) => s.propagates_nulls(),
3307            BinaryFunc::MapGetValue(s) => s.propagates_nulls(),
3308            BinaryFunc::ModFloat32(s) => s.propagates_nulls(),
3309            BinaryFunc::ModFloat64(s) => s.propagates_nulls(),
3310            BinaryFunc::ModInt16(s) => s.propagates_nulls(),
3311            BinaryFunc::ModInt32(s) => s.propagates_nulls(),
3312            BinaryFunc::ModInt64(s) => s.propagates_nulls(),
3313            BinaryFunc::ModNumeric(s) => s.propagates_nulls(),
3314            BinaryFunc::ModUint16(s) => s.propagates_nulls(),
3315            BinaryFunc::ModUint32(s) => s.propagates_nulls(),
3316            BinaryFunc::ModUint64(s) => s.propagates_nulls(),
3317            BinaryFunc::MulFloat32(s) => s.propagates_nulls(),
3318            BinaryFunc::MulFloat64(s) => s.propagates_nulls(),
3319            BinaryFunc::MulInt16(s) => s.propagates_nulls(),
3320            BinaryFunc::MulInt32(s) => s.propagates_nulls(),
3321            BinaryFunc::MulInt64(s) => s.propagates_nulls(),
3322            BinaryFunc::MulInterval(s) => s.propagates_nulls(),
3323            BinaryFunc::MulNumeric(s) => s.propagates_nulls(),
3324            BinaryFunc::MulUint16(s) => s.propagates_nulls(),
3325            BinaryFunc::MulUint32(s) => s.propagates_nulls(),
3326            BinaryFunc::MulUint64(s) => s.propagates_nulls(),
3327            BinaryFunc::MzAclItemContainsPrivilege(s) => s.propagates_nulls(),
3328            BinaryFunc::MzRenderTypmod(s) => s.propagates_nulls(),
3329            BinaryFunc::Normalize => true,
3330            BinaryFunc::NotEq(s) => s.propagates_nulls(),
3331            BinaryFunc::ParseIdent(s) => s.propagates_nulls(),
3332            BinaryFunc::Position(s) => s.propagates_nulls(),
3333            BinaryFunc::Power(s) => s.propagates_nulls(),
3334            BinaryFunc::PowerNumeric(s) => s.propagates_nulls(),
3335            BinaryFunc::PrettySql(s) => s.propagates_nulls(),
3336            BinaryFunc::RangeAdjacent(s) => s.propagates_nulls(),
3337            BinaryFunc::RangeAfter(s) => s.propagates_nulls(),
3338            BinaryFunc::RangeBefore(s) => s.propagates_nulls(),
3339            BinaryFunc::RangeContainsElem { .. } => true,
3340            BinaryFunc::RangeContainsRange(s) => s.propagates_nulls(),
3341            BinaryFunc::RangeContainsRangeRev(s) => s.propagates_nulls(),
3342            BinaryFunc::RangeDifference(s) => s.propagates_nulls(),
3343            BinaryFunc::RangeIntersection(s) => s.propagates_nulls(),
3344            BinaryFunc::RangeOverlaps(s) => s.propagates_nulls(),
3345            BinaryFunc::RangeOverleft(s) => s.propagates_nulls(),
3346            BinaryFunc::RangeOverright(s) => s.propagates_nulls(),
3347            BinaryFunc::RangeUnion(s) => s.propagates_nulls(),
3348            BinaryFunc::RegexpReplace { .. } => true,
3349            BinaryFunc::RepeatString => true,
3350            BinaryFunc::Right(s) => s.propagates_nulls(),
3351            BinaryFunc::RoundNumeric(s) => s.propagates_nulls(),
3352            BinaryFunc::StartsWith(s) => s.propagates_nulls(),
3353            BinaryFunc::SubDate(s) => s.propagates_nulls(),
3354            BinaryFunc::SubDateInterval(s) => s.propagates_nulls(),
3355            BinaryFunc::SubFloat32(s) => s.propagates_nulls(),
3356            BinaryFunc::SubFloat64(s) => s.propagates_nulls(),
3357            BinaryFunc::SubInt16(s) => s.propagates_nulls(),
3358            BinaryFunc::SubInt32(s) => s.propagates_nulls(),
3359            BinaryFunc::SubInt64(s) => s.propagates_nulls(),
3360            BinaryFunc::SubInterval(s) => s.propagates_nulls(),
3361            BinaryFunc::SubNumeric(s) => s.propagates_nulls(),
3362            BinaryFunc::SubTime(s) => s.propagates_nulls(),
3363            BinaryFunc::SubTimeInterval(s) => s.propagates_nulls(),
3364            BinaryFunc::SubTimestamp(s) => s.propagates_nulls(),
3365            BinaryFunc::SubTimestampInterval(s) => s.propagates_nulls(),
3366            BinaryFunc::SubTimestampTz(s) => s.propagates_nulls(),
3367            BinaryFunc::SubTimestampTzInterval(s) => s.propagates_nulls(),
3368            BinaryFunc::SubUint16(s) => s.propagates_nulls(),
3369            BinaryFunc::SubUint32(s) => s.propagates_nulls(),
3370            BinaryFunc::SubUint64(s) => s.propagates_nulls(),
3371            BinaryFunc::TextConcat(s) => s.propagates_nulls(),
3372            BinaryFunc::TimezoneIntervalTime => true,
3373            BinaryFunc::TimezoneIntervalTimestamp => true,
3374            BinaryFunc::TimezoneIntervalTimestampTz => true,
3375            BinaryFunc::TimezoneOffset(s) => s.propagates_nulls(),
3376            BinaryFunc::TimezoneTimestamp => true,
3377            BinaryFunc::TimezoneTimestampTz => true,
3378            BinaryFunc::ToCharTimestamp(s) => s.propagates_nulls(),
3379            BinaryFunc::ToCharTimestampTz(s) => s.propagates_nulls(),
3380            BinaryFunc::Trim(s) => s.propagates_nulls(),
3381            BinaryFunc::TrimLeading(s) => s.propagates_nulls(),
3382            BinaryFunc::TrimTrailing(s) => s.propagates_nulls(),
3383            BinaryFunc::UuidGenerateV5(s) => s.propagates_nulls(),
3384        }
3385    }
3386
3387    /// Whether the function might return NULL even if none of its inputs are
3388    /// NULL.
3389    ///
3390    /// This is presently conservative, and may indicate that a function
3391    /// introduces nulls even when it does not.
3392    pub fn introduces_nulls(&self) -> bool {
3393        use BinaryFunc::*;
3394        match self {
3395            AddDateInterval(s) => s.introduces_nulls(),
3396            AddDateTime(s) => s.introduces_nulls(),
3397            AddFloat32(s) => s.introduces_nulls(),
3398            AddFloat64(s) => s.introduces_nulls(),
3399            AddInt16(s) => s.introduces_nulls(),
3400            AddInt32(s) => s.introduces_nulls(),
3401            AddInt64(s) => s.introduces_nulls(),
3402            AddInterval(s) => s.introduces_nulls(),
3403            AddNumeric(s) => s.introduces_nulls(),
3404            AddTimeInterval(s) => s.introduces_nulls(),
3405            AddTimestampInterval(s) => s.introduces_nulls(),
3406            AddTimestampTzInterval(s) => s.introduces_nulls(),
3407            AddUint16(s) => s.introduces_nulls(),
3408            AddUint32(s) => s.introduces_nulls(),
3409            AddUint64(s) => s.introduces_nulls(),
3410            AgeTimestamp(s) => s.introduces_nulls(),
3411            AgeTimestampTz(s) => s.introduces_nulls(),
3412            ArrayArrayConcat(s) => s.introduces_nulls(),
3413            ArrayContains(s) => s.introduces_nulls(),
3414            ArrayContainsArray(s) => s.introduces_nulls(),
3415            ArrayContainsArrayRev(s) => s.introduces_nulls(),
3416            ArrayRemove(s) => s.introduces_nulls(),
3417            BitAndInt16(s) => s.introduces_nulls(),
3418            BitAndInt32(s) => s.introduces_nulls(),
3419            BitAndInt64(s) => s.introduces_nulls(),
3420            BitAndUint16(s) => s.introduces_nulls(),
3421            BitAndUint32(s) => s.introduces_nulls(),
3422            BitAndUint64(s) => s.introduces_nulls(),
3423            BitOrInt16(s) => s.introduces_nulls(),
3424            BitOrInt32(s) => s.introduces_nulls(),
3425            BitOrInt64(s) => s.introduces_nulls(),
3426            BitOrUint16(s) => s.introduces_nulls(),
3427            BitOrUint32(s) => s.introduces_nulls(),
3428            BitOrUint64(s) => s.introduces_nulls(),
3429            BitShiftLeftInt16(s) => s.introduces_nulls(),
3430            BitShiftLeftInt32(s) => s.introduces_nulls(),
3431            BitShiftLeftInt64(s) => s.introduces_nulls(),
3432            BitShiftLeftUint16(s) => s.introduces_nulls(),
3433            BitShiftLeftUint32(s) => s.introduces_nulls(),
3434            BitShiftLeftUint64(s) => s.introduces_nulls(),
3435            BitShiftRightInt16(s) => s.introduces_nulls(),
3436            BitShiftRightInt32(s) => s.introduces_nulls(),
3437            BitShiftRightInt64(s) => s.introduces_nulls(),
3438            BitShiftRightUint16(s) => s.introduces_nulls(),
3439            BitShiftRightUint32(s) => s.introduces_nulls(),
3440            BitShiftRightUint64(s) => s.introduces_nulls(),
3441            BitXorInt16(s) => s.introduces_nulls(),
3442            BitXorInt32(s) => s.introduces_nulls(),
3443            BitXorInt64(s) => s.introduces_nulls(),
3444            BitXorUint16(s) => s.introduces_nulls(),
3445            BitXorUint32(s) => s.introduces_nulls(),
3446            BitXorUint64(s) => s.introduces_nulls(),
3447            ConstantTimeEqBytes(s) => s.introduces_nulls(),
3448            ConstantTimeEqString(s) => s.introduces_nulls(),
3449            ConvertFrom(s) => s.introduces_nulls(),
3450            DateBinTimestamp(s) => s.introduces_nulls(),
3451            DateBinTimestampTz(s) => s.introduces_nulls(),
3452            DatePartInterval(s) => s.introduces_nulls(),
3453            DatePartTime(s) => s.introduces_nulls(),
3454            DatePartTimestamp(s) => s.introduces_nulls(),
3455            DatePartTimestampTz(s) => s.introduces_nulls(),
3456            DateTruncInterval(s) => s.introduces_nulls(),
3457            DateTruncTimestamp(s) => s.introduces_nulls(),
3458            DateTruncTimestampTz(s) => s.introduces_nulls(),
3459            Decode(s) => s.introduces_nulls(),
3460            DigestBytes(s) => s.introduces_nulls(),
3461            DigestString(s) => s.introduces_nulls(),
3462            DivFloat32(s) => s.introduces_nulls(),
3463            DivFloat64(s) => s.introduces_nulls(),
3464            DivInt16(s) => s.introduces_nulls(),
3465            DivInt32(s) => s.introduces_nulls(),
3466            DivInt64(s) => s.introduces_nulls(),
3467            DivInterval(s) => s.introduces_nulls(),
3468            DivNumeric(s) => s.introduces_nulls(),
3469            DivUint16(s) => s.introduces_nulls(),
3470            DivUint32(s) => s.introduces_nulls(),
3471            DivUint64(s) => s.introduces_nulls(),
3472            ElementListConcat(s) => s.introduces_nulls(),
3473            Encode(s) => s.introduces_nulls(),
3474            EncodedBytesCharLength(s) => s.introduces_nulls(),
3475            Eq(s) => s.introduces_nulls(),
3476            ExtractDate(s) => s.introduces_nulls(),
3477            ExtractInterval(s) => s.introduces_nulls(),
3478            ExtractTime(s) => s.introduces_nulls(),
3479            ExtractTimestamp(s) => s.introduces_nulls(),
3480            ExtractTimestampTz(s) => s.introduces_nulls(),
3481            GetBit(s) => s.introduces_nulls(),
3482            GetByte(s) => s.introduces_nulls(),
3483            Gt(s) => s.introduces_nulls(),
3484            Gte(s) => s.introduces_nulls(),
3485            IsLikeMatchCaseInsensitive(s) => s.introduces_nulls(),
3486            IsLikeMatchCaseSensitive(s) => s.introduces_nulls(),
3487            IsRegexpMatch { .. } => false,
3488            JsonbContainsJsonb(s) => s.introduces_nulls(),
3489            JsonbContainsString(s) => s.introduces_nulls(),
3490            Left(s) => s.introduces_nulls(),
3491            LikeEscape(s) => s.introduces_nulls(),
3492            ListContainsList(s) => s.introduces_nulls(),
3493            ListContainsListRev(s) => s.introduces_nulls(),
3494            ListElementConcat(s) => s.introduces_nulls(),
3495            ListListConcat(s) => s.introduces_nulls(),
3496            ListRemove(s) => s.introduces_nulls(),
3497            LogNumeric(s) => s.introduces_nulls(),
3498            Lt(s) => s.introduces_nulls(),
3499            Lte(s) => s.introduces_nulls(),
3500            MapContainsAllKeys(s) => s.introduces_nulls(),
3501            MapContainsAnyKeys(s) => s.introduces_nulls(),
3502            MapContainsKey(s) => s.introduces_nulls(),
3503            MapContainsMap(s) => s.introduces_nulls(),
3504            ModFloat32(s) => s.introduces_nulls(),
3505            ModFloat64(s) => s.introduces_nulls(),
3506            ModInt16(s) => s.introduces_nulls(),
3507            ModInt32(s) => s.introduces_nulls(),
3508            ModInt64(s) => s.introduces_nulls(),
3509            ModNumeric(s) => s.introduces_nulls(),
3510            ModUint16(s) => s.introduces_nulls(),
3511            ModUint32(s) => s.introduces_nulls(),
3512            ModUint64(s) => s.introduces_nulls(),
3513            MulFloat32(s) => s.introduces_nulls(),
3514            MulFloat64(s) => s.introduces_nulls(),
3515            MulInt16(s) => s.introduces_nulls(),
3516            MulInt32(s) => s.introduces_nulls(),
3517            MulInt64(s) => s.introduces_nulls(),
3518            MulInterval(s) => s.introduces_nulls(),
3519            MulNumeric(s) => s.introduces_nulls(),
3520            MulUint16(s) => s.introduces_nulls(),
3521            MulUint32(s) => s.introduces_nulls(),
3522            MulUint64(s) => s.introduces_nulls(),
3523            MzAclItemContainsPrivilege(s) => s.introduces_nulls(),
3524            MzRenderTypmod(s) => s.introduces_nulls(),
3525            Normalize => false,
3526            NotEq(s) => s.introduces_nulls(),
3527            ParseIdent(s) => s.introduces_nulls(),
3528            Position(s) => s.introduces_nulls(),
3529            Power(s) => s.introduces_nulls(),
3530            PowerNumeric(s) => s.introduces_nulls(),
3531            PrettySql(s) => s.introduces_nulls(),
3532            RangeAdjacent(s) => s.introduces_nulls(),
3533            RangeAfter(s) => s.introduces_nulls(),
3534            RangeBefore(s) => s.introduces_nulls(),
3535            RangeContainsElem { .. } => false,
3536            RangeContainsRange(s) => s.introduces_nulls(),
3537            RangeContainsRangeRev(s) => s.introduces_nulls(),
3538            RangeDifference(s) => s.introduces_nulls(),
3539            RangeIntersection(s) => s.introduces_nulls(),
3540            RangeOverlaps(s) => s.introduces_nulls(),
3541            RangeOverleft(s) => s.introduces_nulls(),
3542            RangeOverright(s) => s.introduces_nulls(),
3543            RangeUnion(s) => s.introduces_nulls(),
3544            RegexpReplace { .. } => false,
3545            RepeatString => false,
3546            Right(s) => s.introduces_nulls(),
3547            RoundNumeric(s) => s.introduces_nulls(),
3548            StartsWith(s) => s.introduces_nulls(),
3549            SubDate(s) => s.introduces_nulls(),
3550            SubDateInterval(s) => s.introduces_nulls(),
3551            SubFloat32(s) => s.introduces_nulls(),
3552            SubFloat64(s) => s.introduces_nulls(),
3553            SubInt16(s) => s.introduces_nulls(),
3554            SubInt32(s) => s.introduces_nulls(),
3555            SubInt64(s) => s.introduces_nulls(),
3556            SubInterval(s) => s.introduces_nulls(),
3557            SubNumeric(s) => s.introduces_nulls(),
3558            SubTime(s) => s.introduces_nulls(),
3559            SubTimeInterval(s) => s.introduces_nulls(),
3560            SubTimestamp(s) => s.introduces_nulls(),
3561            SubTimestampInterval(s) => s.introduces_nulls(),
3562            SubTimestampTz(s) => s.introduces_nulls(),
3563            SubTimestampTzInterval(s) => s.introduces_nulls(),
3564            SubUint16(s) => s.introduces_nulls(),
3565            SubUint32(s) => s.introduces_nulls(),
3566            SubUint64(s) => s.introduces_nulls(),
3567            TextConcat(s) => s.introduces_nulls(),
3568            TimezoneIntervalTime => false,
3569            TimezoneIntervalTimestamp => false,
3570            TimezoneIntervalTimestampTz => false,
3571            TimezoneOffset(s) => s.introduces_nulls(),
3572            TimezoneTimestamp => false,
3573            TimezoneTimestampTz => false,
3574            ToCharTimestamp(s) => s.introduces_nulls(),
3575            ToCharTimestampTz(s) => s.introduces_nulls(),
3576            Trim(s) => s.introduces_nulls(),
3577            TrimLeading(s) => s.introduces_nulls(),
3578            TrimTrailing(s) => s.introduces_nulls(),
3579            UuidGenerateV5(s) => s.introduces_nulls(),
3580
3581            ArrayLength(s) => s.introduces_nulls(),
3582            ArrayLower(s) => s.introduces_nulls(),
3583            ArrayUpper(s) => s.introduces_nulls(),
3584            JsonbConcat(s) => s.introduces_nulls(),
3585            JsonbDeleteInt64(s) => s.introduces_nulls(),
3586            JsonbDeleteString(s) => s.introduces_nulls(),
3587            JsonbGetInt64(s) => s.introduces_nulls(),
3588            JsonbGetInt64Stringify(s) => s.introduces_nulls(),
3589            JsonbGetPath(s) => s.introduces_nulls(),
3590            JsonbGetPathStringify(s) => s.introduces_nulls(),
3591            JsonbGetString(s) => s.introduces_nulls(),
3592            JsonbGetStringStringify(s) => s.introduces_nulls(),
3593            ListLengthMax(s) => s.introduces_nulls(),
3594            MapGetValue(s) => s.introduces_nulls(),
3595        }
3596    }
3597
3598    pub fn is_infix_op(&self) -> bool {
3599        use BinaryFunc::*;
3600        match self {
3601            AddDateInterval(s) => s.is_infix_op(),
3602            AddDateTime(s) => s.is_infix_op(),
3603            AddFloat32(s) => s.is_infix_op(),
3604            AddFloat64(s) => s.is_infix_op(),
3605            AddInt16(s) => s.is_infix_op(),
3606            AddInt32(s) => s.is_infix_op(),
3607            AddInt64(s) => s.is_infix_op(),
3608            AddInterval(s) => s.is_infix_op(),
3609            AddNumeric(s) => s.is_infix_op(),
3610            AddTimeInterval(s) => s.is_infix_op(),
3611            AddTimestampInterval(s) => s.is_infix_op(),
3612            AddTimestampTzInterval(s) => s.is_infix_op(),
3613            AddUint16(s) => s.is_infix_op(),
3614            AddUint32(s) => s.is_infix_op(),
3615            AddUint64(s) => s.is_infix_op(),
3616            ArrayArrayConcat(s) => s.is_infix_op(),
3617            ArrayContains(s) => s.is_infix_op(),
3618            ArrayContainsArray(s) => s.is_infix_op(),
3619            ArrayContainsArrayRev(s) => s.is_infix_op(),
3620            ArrayLength(s) => s.is_infix_op(),
3621            ArrayLower(s) => s.is_infix_op(),
3622            ArrayUpper(s) => s.is_infix_op(),
3623            BitAndInt16(s) => s.is_infix_op(),
3624            BitAndInt32(s) => s.is_infix_op(),
3625            BitAndInt64(s) => s.is_infix_op(),
3626            BitAndUint16(s) => s.is_infix_op(),
3627            BitAndUint32(s) => s.is_infix_op(),
3628            BitAndUint64(s) => s.is_infix_op(),
3629            BitOrInt16(s) => s.is_infix_op(),
3630            BitOrInt32(s) => s.is_infix_op(),
3631            BitOrInt64(s) => s.is_infix_op(),
3632            BitOrUint16(s) => s.is_infix_op(),
3633            BitOrUint32(s) => s.is_infix_op(),
3634            BitOrUint64(s) => s.is_infix_op(),
3635            BitShiftLeftInt16(s) => s.is_infix_op(),
3636            BitShiftLeftInt32(s) => s.is_infix_op(),
3637            BitShiftLeftInt64(s) => s.is_infix_op(),
3638            BitShiftLeftUint16(s) => s.is_infix_op(),
3639            BitShiftLeftUint32(s) => s.is_infix_op(),
3640            BitShiftLeftUint64(s) => s.is_infix_op(),
3641            BitShiftRightInt16(s) => s.is_infix_op(),
3642            BitShiftRightInt32(s) => s.is_infix_op(),
3643            BitShiftRightInt64(s) => s.is_infix_op(),
3644            BitShiftRightUint16(s) => s.is_infix_op(),
3645            BitShiftRightUint32(s) => s.is_infix_op(),
3646            BitShiftRightUint64(s) => s.is_infix_op(),
3647            BitXorInt16(s) => s.is_infix_op(),
3648            BitXorInt32(s) => s.is_infix_op(),
3649            BitXorInt64(s) => s.is_infix_op(),
3650            BitXorUint16(s) => s.is_infix_op(),
3651            BitXorUint32(s) => s.is_infix_op(),
3652            BitXorUint64(s) => s.is_infix_op(),
3653            DivFloat32(s) => s.is_infix_op(),
3654            DivFloat64(s) => s.is_infix_op(),
3655            DivInt16(s) => s.is_infix_op(),
3656            DivInt32(s) => s.is_infix_op(),
3657            DivInt64(s) => s.is_infix_op(),
3658            DivInterval(s) => s.is_infix_op(),
3659            DivNumeric(s) => s.is_infix_op(),
3660            DivUint16(s) => s.is_infix_op(),
3661            DivUint32(s) => s.is_infix_op(),
3662            DivUint64(s) => s.is_infix_op(),
3663            ElementListConcat(s) => s.is_infix_op(),
3664            Eq(s) => s.is_infix_op(),
3665            Gt(s) => s.is_infix_op(),
3666            Gte(s) => s.is_infix_op(),
3667            IsLikeMatchCaseInsensitive(s) => s.is_infix_op(),
3668            IsLikeMatchCaseSensitive(s) => s.is_infix_op(),
3669            IsRegexpMatch { .. } => true,
3670            JsonbConcat(s) => s.is_infix_op(),
3671            JsonbContainsJsonb(s) => s.is_infix_op(),
3672            JsonbContainsString(s) => s.is_infix_op(),
3673            JsonbDeleteInt64(s) => s.is_infix_op(),
3674            JsonbDeleteString(s) => s.is_infix_op(),
3675            JsonbGetInt64(s) => s.is_infix_op(),
3676            JsonbGetInt64Stringify(s) => s.is_infix_op(),
3677            JsonbGetPath(s) => s.is_infix_op(),
3678            JsonbGetPathStringify(s) => s.is_infix_op(),
3679            JsonbGetString(s) => s.is_infix_op(),
3680            JsonbGetStringStringify(s) => s.is_infix_op(),
3681            ListContainsList(s) => s.is_infix_op(),
3682            ListContainsListRev(s) => s.is_infix_op(),
3683            ListElementConcat(s) => s.is_infix_op(),
3684            ListListConcat(s) => s.is_infix_op(),
3685            Lt(s) => s.is_infix_op(),
3686            Lte(s) => s.is_infix_op(),
3687            MapContainsAllKeys(s) => s.is_infix_op(),
3688            MapContainsAnyKeys(s) => s.is_infix_op(),
3689            MapContainsKey(s) => s.is_infix_op(),
3690            MapContainsMap(s) => s.is_infix_op(),
3691            MapGetValue(s) => s.is_infix_op(),
3692            ModFloat32(s) => s.is_infix_op(),
3693            ModFloat64(s) => s.is_infix_op(),
3694            ModInt16(s) => s.is_infix_op(),
3695            ModInt32(s) => s.is_infix_op(),
3696            ModInt64(s) => s.is_infix_op(),
3697            ModNumeric(s) => s.is_infix_op(),
3698            ModUint16(s) => s.is_infix_op(),
3699            ModUint32(s) => s.is_infix_op(),
3700            ModUint64(s) => s.is_infix_op(),
3701            MulFloat32(s) => s.is_infix_op(),
3702            MulFloat64(s) => s.is_infix_op(),
3703            MulInt16(s) => s.is_infix_op(),
3704            MulInt32(s) => s.is_infix_op(),
3705            MulInt64(s) => s.is_infix_op(),
3706            MulInterval(s) => s.is_infix_op(),
3707            MulNumeric(s) => s.is_infix_op(),
3708            MulUint16(s) => s.is_infix_op(),
3709            MulUint32(s) => s.is_infix_op(),
3710            MulUint64(s) => s.is_infix_op(),
3711            NotEq(s) => s.is_infix_op(),
3712            RangeAdjacent(s) => s.is_infix_op(),
3713            RangeAfter(s) => s.is_infix_op(),
3714            RangeBefore(s) => s.is_infix_op(),
3715            RangeContainsElem { .. } => true,
3716            RangeContainsRange(s) => s.is_infix_op(),
3717            RangeContainsRangeRev(s) => s.is_infix_op(),
3718            RangeDifference(s) => s.is_infix_op(),
3719            RangeIntersection(s) => s.is_infix_op(),
3720            RangeOverlaps(s) => s.is_infix_op(),
3721            RangeOverleft(s) => s.is_infix_op(),
3722            RangeOverright(s) => s.is_infix_op(),
3723            RangeUnion(s) => s.is_infix_op(),
3724            SubDate(s) => s.is_infix_op(),
3725            SubDateInterval(s) => s.is_infix_op(),
3726            SubFloat32(s) => s.is_infix_op(),
3727            SubFloat64(s) => s.is_infix_op(),
3728            SubInt16(s) => s.is_infix_op(),
3729            SubInt32(s) => s.is_infix_op(),
3730            SubInt64(s) => s.is_infix_op(),
3731            SubInterval(s) => s.is_infix_op(),
3732            SubNumeric(s) => s.is_infix_op(),
3733            SubTime(s) => s.is_infix_op(),
3734            SubTimeInterval(s) => s.is_infix_op(),
3735            SubTimestamp(s) => s.is_infix_op(),
3736            SubTimestampInterval(s) => s.is_infix_op(),
3737            SubTimestampTz(s) => s.is_infix_op(),
3738            SubTimestampTzInterval(s) => s.is_infix_op(),
3739            SubUint16(s) => s.is_infix_op(),
3740            SubUint32(s) => s.is_infix_op(),
3741            SubUint64(s) => s.is_infix_op(),
3742            TextConcat(s) => s.is_infix_op(),
3743
3744            AgeTimestamp(s) => s.is_infix_op(),
3745            AgeTimestampTz(s) => s.is_infix_op(),
3746            ArrayRemove(s) => s.is_infix_op(),
3747            ConstantTimeEqBytes(s) => s.is_infix_op(),
3748            ConstantTimeEqString(s) => s.is_infix_op(),
3749            ConvertFrom(s) => s.is_infix_op(),
3750            DateBinTimestamp(s) => s.is_infix_op(),
3751            DateBinTimestampTz(s) => s.is_infix_op(),
3752            DatePartInterval(s) => s.is_infix_op(),
3753            DatePartTime(s) => s.is_infix_op(),
3754            DatePartTimestamp(s) => s.is_infix_op(),
3755            DatePartTimestampTz(s) => s.is_infix_op(),
3756            DateTruncInterval(s) => s.is_infix_op(),
3757            DateTruncTimestamp(s) => s.is_infix_op(),
3758            DateTruncTimestampTz(s) => s.is_infix_op(),
3759            Decode(s) => s.is_infix_op(),
3760            DigestBytes(s) => s.is_infix_op(),
3761            DigestString(s) => s.is_infix_op(),
3762            Encode(s) => s.is_infix_op(),
3763            EncodedBytesCharLength(s) => s.is_infix_op(),
3764            ExtractDate(s) => s.is_infix_op(),
3765            ExtractInterval(s) => s.is_infix_op(),
3766            ExtractTime(s) => s.is_infix_op(),
3767            ExtractTimestamp(s) => s.is_infix_op(),
3768            ExtractTimestampTz(s) => s.is_infix_op(),
3769            GetBit(s) => s.is_infix_op(),
3770            GetByte(s) => s.is_infix_op(),
3771            Left(s) => s.is_infix_op(),
3772            LikeEscape(s) => s.is_infix_op(),
3773            ListLengthMax(s) => s.is_infix_op(),
3774            ListRemove(s) => s.is_infix_op(),
3775            LogNumeric(s) => s.is_infix_op(),
3776            MzAclItemContainsPrivilege(s) => s.is_infix_op(),
3777            MzRenderTypmod(s) => s.is_infix_op(),
3778            Normalize => false,
3779            ParseIdent(s) => s.is_infix_op(),
3780            Position(s) => s.is_infix_op(),
3781            Power(s) => s.is_infix_op(),
3782            PowerNumeric(s) => s.is_infix_op(),
3783            PrettySql(s) => s.is_infix_op(),
3784            RegexpReplace { .. } => false,
3785            RepeatString => false,
3786            Right(s) => s.is_infix_op(),
3787            RoundNumeric(s) => s.is_infix_op(),
3788            StartsWith(s) => s.is_infix_op(),
3789            TimezoneIntervalTime => false,
3790            TimezoneIntervalTimestamp => false,
3791            TimezoneIntervalTimestampTz => false,
3792            TimezoneOffset(s) => s.is_infix_op(),
3793            TimezoneTimestamp => false,
3794            TimezoneTimestampTz => false,
3795            ToCharTimestamp(s) => s.is_infix_op(),
3796            ToCharTimestampTz(s) => s.is_infix_op(),
3797            Trim(s) => s.is_infix_op(),
3798            TrimLeading(s) => s.is_infix_op(),
3799            TrimTrailing(s) => s.is_infix_op(),
3800            UuidGenerateV5(s) => s.is_infix_op(),
3801        }
3802    }
3803
3804    /// Returns the negation of the given binary function, if it exists.
3805    pub fn negate(&self) -> Option<Self> {
3806        match self {
3807            BinaryFunc::AddDateInterval(s) => s.negate(),
3808            BinaryFunc::AddDateTime(s) => s.negate(),
3809            BinaryFunc::AddFloat32(s) => s.negate(),
3810            BinaryFunc::AddFloat64(s) => s.negate(),
3811            BinaryFunc::AddInt16(s) => s.negate(),
3812            BinaryFunc::AddInt32(s) => s.negate(),
3813            BinaryFunc::AddInt64(s) => s.negate(),
3814            BinaryFunc::AddInterval(s) => s.negate(),
3815            BinaryFunc::AddNumeric(s) => s.negate(),
3816            BinaryFunc::AddTimeInterval(s) => s.negate(),
3817            BinaryFunc::AddTimestampInterval(s) => s.negate(),
3818            BinaryFunc::AddTimestampTzInterval(s) => s.negate(),
3819            BinaryFunc::AddUint16(s) => s.negate(),
3820            BinaryFunc::AddUint32(s) => s.negate(),
3821            BinaryFunc::AddUint64(s) => s.negate(),
3822            BinaryFunc::AgeTimestamp(s) => s.negate(),
3823            BinaryFunc::AgeTimestampTz(s) => s.negate(),
3824            BinaryFunc::ArrayArrayConcat(s) => s.negate(),
3825            BinaryFunc::ArrayContains(s) => s.negate(),
3826            BinaryFunc::ArrayContainsArray(s) => s.negate(),
3827            BinaryFunc::ArrayContainsArrayRev(s) => s.negate(),
3828            BinaryFunc::ArrayLength(s) => s.negate(),
3829            BinaryFunc::ArrayLower(s) => s.negate(),
3830            BinaryFunc::ArrayRemove(s) => s.negate(),
3831            BinaryFunc::ArrayUpper(s) => s.negate(),
3832            BinaryFunc::BitAndInt16(s) => s.negate(),
3833            BinaryFunc::BitAndInt32(s) => s.negate(),
3834            BinaryFunc::BitAndInt64(s) => s.negate(),
3835            BinaryFunc::BitAndUint16(s) => s.negate(),
3836            BinaryFunc::BitAndUint32(s) => s.negate(),
3837            BinaryFunc::BitAndUint64(s) => s.negate(),
3838            BinaryFunc::BitOrInt16(s) => s.negate(),
3839            BinaryFunc::BitOrInt32(s) => s.negate(),
3840            BinaryFunc::BitOrInt64(s) => s.negate(),
3841            BinaryFunc::BitOrUint16(s) => s.negate(),
3842            BinaryFunc::BitOrUint32(s) => s.negate(),
3843            BinaryFunc::BitOrUint64(s) => s.negate(),
3844            BinaryFunc::BitShiftLeftInt16(s) => s.negate(),
3845            BinaryFunc::BitShiftLeftInt32(s) => s.negate(),
3846            BinaryFunc::BitShiftLeftInt64(s) => s.negate(),
3847            BinaryFunc::BitShiftLeftUint16(s) => s.negate(),
3848            BinaryFunc::BitShiftLeftUint32(s) => s.negate(),
3849            BinaryFunc::BitShiftLeftUint64(s) => s.negate(),
3850            BinaryFunc::BitShiftRightInt16(s) => s.negate(),
3851            BinaryFunc::BitShiftRightInt32(s) => s.negate(),
3852            BinaryFunc::BitShiftRightInt64(s) => s.negate(),
3853            BinaryFunc::BitShiftRightUint16(s) => s.negate(),
3854            BinaryFunc::BitShiftRightUint32(s) => s.negate(),
3855            BinaryFunc::BitShiftRightUint64(s) => s.negate(),
3856            BinaryFunc::BitXorInt16(s) => s.negate(),
3857            BinaryFunc::BitXorInt32(s) => s.negate(),
3858            BinaryFunc::BitXorInt64(s) => s.negate(),
3859            BinaryFunc::BitXorUint16(s) => s.negate(),
3860            BinaryFunc::BitXorUint32(s) => s.negate(),
3861            BinaryFunc::BitXorUint64(s) => s.negate(),
3862            BinaryFunc::ConstantTimeEqBytes(s) => s.negate(),
3863            BinaryFunc::ConstantTimeEqString(s) => s.negate(),
3864            BinaryFunc::ConvertFrom(s) => s.negate(),
3865            BinaryFunc::DateBinTimestamp(s) => s.negate(),
3866            BinaryFunc::DateBinTimestampTz(s) => s.negate(),
3867            BinaryFunc::DatePartInterval(s) => s.negate(),
3868            BinaryFunc::DatePartTime(s) => s.negate(),
3869            BinaryFunc::DatePartTimestamp(s) => s.negate(),
3870            BinaryFunc::DatePartTimestampTz(s) => s.negate(),
3871            BinaryFunc::DateTruncInterval(s) => s.negate(),
3872            BinaryFunc::DateTruncTimestamp(s) => s.negate(),
3873            BinaryFunc::DateTruncTimestampTz(s) => s.negate(),
3874            BinaryFunc::Decode(s) => s.negate(),
3875            BinaryFunc::DigestBytes(s) => s.negate(),
3876            BinaryFunc::DigestString(s) => s.negate(),
3877            BinaryFunc::DivFloat32(s) => s.negate(),
3878            BinaryFunc::DivFloat64(s) => s.negate(),
3879            BinaryFunc::DivInt16(s) => s.negate(),
3880            BinaryFunc::DivInt32(s) => s.negate(),
3881            BinaryFunc::DivInt64(s) => s.negate(),
3882            BinaryFunc::DivInterval(s) => s.negate(),
3883            BinaryFunc::DivNumeric(s) => s.negate(),
3884            BinaryFunc::DivUint16(s) => s.negate(),
3885            BinaryFunc::DivUint32(s) => s.negate(),
3886            BinaryFunc::DivUint64(s) => s.negate(),
3887            BinaryFunc::ElementListConcat(s) => s.negate(),
3888            BinaryFunc::Encode(s) => s.negate(),
3889            BinaryFunc::EncodedBytesCharLength(s) => s.negate(),
3890            BinaryFunc::Eq(s) => s.negate(),
3891            BinaryFunc::ExtractDate(s) => s.negate(),
3892            BinaryFunc::ExtractInterval(s) => s.negate(),
3893            BinaryFunc::ExtractTime(s) => s.negate(),
3894            BinaryFunc::ExtractTimestamp(s) => s.negate(),
3895            BinaryFunc::ExtractTimestampTz(s) => s.negate(),
3896            BinaryFunc::GetBit(s) => s.negate(),
3897            BinaryFunc::GetByte(s) => s.negate(),
3898            BinaryFunc::Gt(s) => s.negate(),
3899            BinaryFunc::Gte(s) => s.negate(),
3900            BinaryFunc::IsLikeMatchCaseInsensitive(s) => s.negate(),
3901            BinaryFunc::IsLikeMatchCaseSensitive(s) => s.negate(),
3902            BinaryFunc::IsRegexpMatch { .. } => None,
3903            BinaryFunc::JsonbConcat(s) => s.negate(),
3904            BinaryFunc::JsonbContainsJsonb(s) => s.negate(),
3905            BinaryFunc::JsonbContainsString(s) => s.negate(),
3906            BinaryFunc::JsonbDeleteInt64(s) => s.negate(),
3907            BinaryFunc::JsonbDeleteString(s) => s.negate(),
3908            BinaryFunc::JsonbGetInt64(s) => s.negate(),
3909            BinaryFunc::JsonbGetInt64Stringify(s) => s.negate(),
3910            BinaryFunc::JsonbGetPath(s) => s.negate(),
3911            BinaryFunc::JsonbGetPathStringify(s) => s.negate(),
3912            BinaryFunc::JsonbGetString(s) => s.negate(),
3913            BinaryFunc::JsonbGetStringStringify(s) => s.negate(),
3914            BinaryFunc::Left(s) => s.negate(),
3915            BinaryFunc::LikeEscape(s) => s.negate(),
3916            BinaryFunc::ListContainsList(s) => s.negate(),
3917            BinaryFunc::ListContainsListRev(s) => s.negate(),
3918            BinaryFunc::ListElementConcat(s) => s.negate(),
3919            BinaryFunc::ListLengthMax(s) => s.negate(),
3920            BinaryFunc::ListListConcat(s) => s.negate(),
3921            BinaryFunc::ListRemove(s) => s.negate(),
3922            BinaryFunc::LogNumeric(s) => s.negate(),
3923            BinaryFunc::Lt(s) => s.negate(),
3924            BinaryFunc::Lte(s) => s.negate(),
3925            BinaryFunc::MapContainsAllKeys(s) => s.negate(),
3926            BinaryFunc::MapContainsAnyKeys(s) => s.negate(),
3927            BinaryFunc::MapContainsKey(s) => s.negate(),
3928            BinaryFunc::MapContainsMap(s) => s.negate(),
3929            BinaryFunc::MapGetValue(s) => s.negate(),
3930            BinaryFunc::ModFloat32(s) => s.negate(),
3931            BinaryFunc::ModFloat64(s) => s.negate(),
3932            BinaryFunc::ModInt16(s) => s.negate(),
3933            BinaryFunc::ModInt32(s) => s.negate(),
3934            BinaryFunc::ModInt64(s) => s.negate(),
3935            BinaryFunc::ModNumeric(s) => s.negate(),
3936            BinaryFunc::ModUint16(s) => s.negate(),
3937            BinaryFunc::ModUint32(s) => s.negate(),
3938            BinaryFunc::ModUint64(s) => s.negate(),
3939            BinaryFunc::MulFloat32(s) => s.negate(),
3940            BinaryFunc::MulFloat64(s) => s.negate(),
3941            BinaryFunc::MulInt16(s) => s.negate(),
3942            BinaryFunc::MulInt32(s) => s.negate(),
3943            BinaryFunc::MulInt64(s) => s.negate(),
3944            BinaryFunc::MulInterval(s) => s.negate(),
3945            BinaryFunc::MulNumeric(s) => s.negate(),
3946            BinaryFunc::MulUint16(s) => s.negate(),
3947            BinaryFunc::MulUint32(s) => s.negate(),
3948            BinaryFunc::MulUint64(s) => s.negate(),
3949            BinaryFunc::MzAclItemContainsPrivilege(s) => s.negate(),
3950            BinaryFunc::MzRenderTypmod(s) => s.negate(),
3951            BinaryFunc::Normalize => None,
3952            BinaryFunc::NotEq(s) => s.negate(),
3953            BinaryFunc::ParseIdent(s) => s.negate(),
3954            BinaryFunc::Position(s) => s.negate(),
3955            BinaryFunc::Power(s) => s.negate(),
3956            BinaryFunc::PowerNumeric(s) => s.negate(),
3957            BinaryFunc::PrettySql(s) => s.negate(),
3958            BinaryFunc::RangeAdjacent(s) => s.negate(),
3959            BinaryFunc::RangeAfter(s) => s.negate(),
3960            BinaryFunc::RangeBefore(s) => s.negate(),
3961            BinaryFunc::RangeContainsElem { .. } => None,
3962            BinaryFunc::RangeContainsRange(s) => s.negate(),
3963            BinaryFunc::RangeContainsRangeRev(s) => s.negate(),
3964            BinaryFunc::RangeDifference(s) => s.negate(),
3965            BinaryFunc::RangeIntersection(s) => s.negate(),
3966            BinaryFunc::RangeOverlaps(s) => s.negate(),
3967            BinaryFunc::RangeOverleft(s) => s.negate(),
3968            BinaryFunc::RangeOverright(s) => s.negate(),
3969            BinaryFunc::RangeUnion(s) => s.negate(),
3970            BinaryFunc::RegexpReplace { .. } => None,
3971            BinaryFunc::RepeatString => None,
3972            BinaryFunc::Right(s) => s.negate(),
3973            BinaryFunc::RoundNumeric(s) => s.negate(),
3974            BinaryFunc::StartsWith(s) => s.negate(),
3975            BinaryFunc::SubDate(s) => s.negate(),
3976            BinaryFunc::SubDateInterval(s) => s.negate(),
3977            BinaryFunc::SubFloat32(s) => s.negate(),
3978            BinaryFunc::SubFloat64(s) => s.negate(),
3979            BinaryFunc::SubInt16(s) => s.negate(),
3980            BinaryFunc::SubInt32(s) => s.negate(),
3981            BinaryFunc::SubInt64(s) => s.negate(),
3982            BinaryFunc::SubInterval(s) => s.negate(),
3983            BinaryFunc::SubNumeric(s) => s.negate(),
3984            BinaryFunc::SubTime(s) => s.negate(),
3985            BinaryFunc::SubTimeInterval(s) => s.negate(),
3986            BinaryFunc::SubTimestamp(s) => s.negate(),
3987            BinaryFunc::SubTimestampInterval(s) => s.negate(),
3988            BinaryFunc::SubTimestampTz(s) => s.negate(),
3989            BinaryFunc::SubTimestampTzInterval(s) => s.negate(),
3990            BinaryFunc::SubUint16(s) => s.negate(),
3991            BinaryFunc::SubUint32(s) => s.negate(),
3992            BinaryFunc::SubUint64(s) => s.negate(),
3993            BinaryFunc::TextConcat(s) => s.negate(),
3994            BinaryFunc::TimezoneIntervalTime => None,
3995            BinaryFunc::TimezoneIntervalTimestamp => None,
3996            BinaryFunc::TimezoneIntervalTimestampTz => None,
3997            BinaryFunc::TimezoneOffset(s) => s.negate(),
3998            BinaryFunc::TimezoneTimestamp => None,
3999            BinaryFunc::TimezoneTimestampTz => None,
4000            BinaryFunc::ToCharTimestamp(s) => s.negate(),
4001            BinaryFunc::ToCharTimestampTz(s) => s.negate(),
4002            BinaryFunc::Trim(s) => s.negate(),
4003            BinaryFunc::TrimLeading(s) => s.negate(),
4004            BinaryFunc::TrimTrailing(s) => s.negate(),
4005            BinaryFunc::UuidGenerateV5(s) => s.negate(),
4006        }
4007    }
4008
4009    /// Returns true if the function could introduce an error on non-error inputs.
4010    pub fn could_error(&self) -> bool {
4011        match self {
4012            BinaryFunc::AddFloat32(s) => s.could_error(),
4013            BinaryFunc::AddFloat64(s) => s.could_error(),
4014            BinaryFunc::AddInt16(s) => s.could_error(),
4015            BinaryFunc::AddInt32(s) => s.could_error(),
4016            BinaryFunc::AddInt64(s) => s.could_error(),
4017            BinaryFunc::AddUint16(s) => s.could_error(),
4018            BinaryFunc::AddUint32(s) => s.could_error(),
4019            BinaryFunc::AddUint64(s) => s.could_error(),
4020            BinaryFunc::ArrayContains(s) => s.could_error(),
4021            BinaryFunc::ArrayContainsArray(s) => s.could_error(),
4022            BinaryFunc::ArrayContainsArrayRev(s) => s.could_error(),
4023            BinaryFunc::ArrayLower(s) => s.could_error(),
4024            BinaryFunc::BitAndInt16(s) => s.could_error(),
4025            BinaryFunc::BitAndInt32(s) => s.could_error(),
4026            BinaryFunc::BitAndInt64(s) => s.could_error(),
4027            BinaryFunc::BitAndUint16(s) => s.could_error(),
4028            BinaryFunc::BitAndUint32(s) => s.could_error(),
4029            BinaryFunc::BitAndUint64(s) => s.could_error(),
4030            BinaryFunc::BitOrInt16(s) => s.could_error(),
4031            BinaryFunc::BitOrInt32(s) => s.could_error(),
4032            BinaryFunc::BitOrInt64(s) => s.could_error(),
4033            BinaryFunc::BitOrUint16(s) => s.could_error(),
4034            BinaryFunc::BitOrUint32(s) => s.could_error(),
4035            BinaryFunc::BitOrUint64(s) => s.could_error(),
4036            BinaryFunc::BitShiftLeftInt16(s) => s.could_error(),
4037            BinaryFunc::BitShiftLeftInt32(s) => s.could_error(),
4038            BinaryFunc::BitShiftLeftInt64(s) => s.could_error(),
4039            BinaryFunc::BitShiftLeftUint16(s) => s.could_error(),
4040            BinaryFunc::BitShiftLeftUint32(s) => s.could_error(),
4041            BinaryFunc::BitShiftLeftUint64(s) => s.could_error(),
4042            BinaryFunc::BitShiftRightInt16(s) => s.could_error(),
4043            BinaryFunc::BitShiftRightInt32(s) => s.could_error(),
4044            BinaryFunc::BitShiftRightInt64(s) => s.could_error(),
4045            BinaryFunc::BitShiftRightUint16(s) => s.could_error(),
4046            BinaryFunc::BitShiftRightUint32(s) => s.could_error(),
4047            BinaryFunc::BitShiftRightUint64(s) => s.could_error(),
4048            BinaryFunc::BitXorInt16(s) => s.could_error(),
4049            BinaryFunc::BitXorInt32(s) => s.could_error(),
4050            BinaryFunc::BitXorInt64(s) => s.could_error(),
4051            BinaryFunc::BitXorUint16(s) => s.could_error(),
4052            BinaryFunc::BitXorUint32(s) => s.could_error(),
4053            BinaryFunc::BitXorUint64(s) => s.could_error(),
4054            BinaryFunc::ElementListConcat(s) => s.could_error(),
4055            BinaryFunc::Eq(s) => s.could_error(),
4056            BinaryFunc::Gt(s) => s.could_error(),
4057            BinaryFunc::Gte(s) => s.could_error(),
4058            BinaryFunc::JsonbGetInt64(s) => s.could_error(),
4059            BinaryFunc::JsonbGetInt64Stringify(s) => s.could_error(),
4060            BinaryFunc::JsonbGetPath(s) => s.could_error(),
4061            BinaryFunc::JsonbGetPathStringify(s) => s.could_error(),
4062            BinaryFunc::JsonbGetString(s) => s.could_error(),
4063            BinaryFunc::JsonbGetStringStringify(s) => s.could_error(),
4064            BinaryFunc::ListContainsList(s) => s.could_error(),
4065            BinaryFunc::ListContainsListRev(s) => s.could_error(),
4066            BinaryFunc::ListElementConcat(s) => s.could_error(),
4067            BinaryFunc::ListListConcat(s) => s.could_error(),
4068            BinaryFunc::ListRemove(s) => s.could_error(),
4069            BinaryFunc::Lt(s) => s.could_error(),
4070            BinaryFunc::Lte(s) => s.could_error(),
4071            BinaryFunc::NotEq(s) => s.could_error(),
4072            BinaryFunc::RangeAdjacent(s) => s.could_error(),
4073            BinaryFunc::RangeAfter(s) => s.could_error(),
4074            BinaryFunc::RangeBefore(s) => s.could_error(),
4075            BinaryFunc::RangeContainsElem { .. } => false,
4076            BinaryFunc::RangeContainsRange(s) => s.could_error(),
4077            BinaryFunc::RangeContainsRangeRev(s) => s.could_error(),
4078            BinaryFunc::RangeOverlaps(s) => s.could_error(),
4079            BinaryFunc::RangeOverleft(s) => s.could_error(),
4080            BinaryFunc::RangeOverright(s) => s.could_error(),
4081            BinaryFunc::StartsWith(s) => s.could_error(),
4082            BinaryFunc::TextConcat(s) => s.could_error(),
4083            BinaryFunc::ToCharTimestamp(s) => s.could_error(),
4084            BinaryFunc::ToCharTimestampTz(s) => s.could_error(),
4085            BinaryFunc::Trim(s) => s.could_error(),
4086            BinaryFunc::TrimLeading(s) => s.could_error(),
4087            BinaryFunc::TrimTrailing(s) => s.could_error(),
4088
4089            // All that formally returned true.
4090            BinaryFunc::AddInterval(s) => s.could_error(),
4091            BinaryFunc::AddTimestampInterval(s) => s.could_error(),
4092            BinaryFunc::AddTimestampTzInterval(s) => s.could_error(),
4093            BinaryFunc::AddDateInterval(s) => s.could_error(),
4094            BinaryFunc::AddDateTime(s) => s.could_error(),
4095            BinaryFunc::AddTimeInterval(s) => s.could_error(),
4096            BinaryFunc::AddNumeric(s) => s.could_error(),
4097            BinaryFunc::AgeTimestamp(s) => s.could_error(),
4098            BinaryFunc::AgeTimestampTz(s) => s.could_error(),
4099            BinaryFunc::SubInt16(s) => s.could_error(),
4100            BinaryFunc::SubInt32(s) => s.could_error(),
4101            BinaryFunc::SubInt64(s) => s.could_error(),
4102            BinaryFunc::SubUint16(s) => s.could_error(),
4103            BinaryFunc::SubUint32(s) => s.could_error(),
4104            BinaryFunc::SubUint64(s) => s.could_error(),
4105            BinaryFunc::SubFloat32(s) => s.could_error(),
4106            BinaryFunc::SubFloat64(s) => s.could_error(),
4107            BinaryFunc::SubInterval(s) => s.could_error(),
4108            BinaryFunc::SubTimestamp(s) => s.could_error(),
4109            BinaryFunc::SubTimestampTz(s) => s.could_error(),
4110            BinaryFunc::SubTimestampInterval(s) => s.could_error(),
4111            BinaryFunc::SubTimestampTzInterval(s) => s.could_error(),
4112            BinaryFunc::SubDate(s) => s.could_error(),
4113            BinaryFunc::SubDateInterval(s) => s.could_error(),
4114            BinaryFunc::SubTime(s) => s.could_error(),
4115            BinaryFunc::SubTimeInterval(s) => s.could_error(),
4116            BinaryFunc::SubNumeric(s) => s.could_error(),
4117            BinaryFunc::MulInt16(s) => s.could_error(),
4118            BinaryFunc::MulInt32(s) => s.could_error(),
4119            BinaryFunc::MulInt64(s) => s.could_error(),
4120            BinaryFunc::MulUint16(s) => s.could_error(),
4121            BinaryFunc::MulUint32(s) => s.could_error(),
4122            BinaryFunc::MulUint64(s) => s.could_error(),
4123            BinaryFunc::MulFloat32(s) => s.could_error(),
4124            BinaryFunc::MulFloat64(s) => s.could_error(),
4125            BinaryFunc::MulNumeric(s) => s.could_error(),
4126            BinaryFunc::MulInterval(s) => s.could_error(),
4127            BinaryFunc::DivInt16(s) => s.could_error(),
4128            BinaryFunc::DivInt32(s) => s.could_error(),
4129            BinaryFunc::DivInt64(s) => s.could_error(),
4130            BinaryFunc::DivUint16(s) => s.could_error(),
4131            BinaryFunc::DivUint32(s) => s.could_error(),
4132            BinaryFunc::DivUint64(s) => s.could_error(),
4133            BinaryFunc::DivFloat32(s) => s.could_error(),
4134            BinaryFunc::DivFloat64(s) => s.could_error(),
4135            BinaryFunc::DivNumeric(s) => s.could_error(),
4136            BinaryFunc::DivInterval(s) => s.could_error(),
4137            BinaryFunc::ModInt16(s) => s.could_error(),
4138            BinaryFunc::ModInt32(s) => s.could_error(),
4139            BinaryFunc::ModInt64(s) => s.could_error(),
4140            BinaryFunc::ModUint16(s) => s.could_error(),
4141            BinaryFunc::ModUint32(s) => s.could_error(),
4142            BinaryFunc::ModUint64(s) => s.could_error(),
4143            BinaryFunc::ModFloat32(s) => s.could_error(),
4144            BinaryFunc::ModFloat64(s) => s.could_error(),
4145            BinaryFunc::ModNumeric(s) => s.could_error(),
4146            BinaryFunc::RoundNumeric(s) => s.could_error(),
4147            BinaryFunc::LikeEscape(s) => s.could_error(),
4148            BinaryFunc::IsLikeMatchCaseInsensitive(s) => s.could_error(),
4149            BinaryFunc::IsLikeMatchCaseSensitive(s) => s.could_error(),
4150            BinaryFunc::IsRegexpMatch { .. } => true,
4151            BinaryFunc::DateBinTimestamp(s) => s.could_error(),
4152            BinaryFunc::DateBinTimestampTz(s) => s.could_error(),
4153            BinaryFunc::ExtractInterval(s) => s.could_error(),
4154            BinaryFunc::ExtractTime(s) => s.could_error(),
4155            BinaryFunc::ExtractTimestamp(s) => s.could_error(),
4156            BinaryFunc::ExtractTimestampTz(s) => s.could_error(),
4157            BinaryFunc::ExtractDate(s) => s.could_error(),
4158            BinaryFunc::DatePartInterval(s) => s.could_error(),
4159            BinaryFunc::DatePartTime(s) => s.could_error(),
4160            BinaryFunc::DatePartTimestamp(s) => s.could_error(),
4161            BinaryFunc::DatePartTimestampTz(s) => s.could_error(),
4162            BinaryFunc::DateTruncTimestamp(s) => s.could_error(),
4163            BinaryFunc::DateTruncTimestampTz(s) => s.could_error(),
4164            BinaryFunc::DateTruncInterval(s) => s.could_error(),
4165            BinaryFunc::TimezoneTimestamp => true,
4166            BinaryFunc::TimezoneTimestampTz => true,
4167            BinaryFunc::TimezoneIntervalTimestamp => true,
4168            BinaryFunc::TimezoneIntervalTimestampTz => true,
4169            BinaryFunc::TimezoneIntervalTime => true,
4170            BinaryFunc::TimezoneOffset(s) => s.could_error(),
4171            BinaryFunc::JsonbContainsString(s) => s.could_error(),
4172            BinaryFunc::JsonbConcat(s) => s.could_error(),
4173            BinaryFunc::JsonbContainsJsonb(s) => s.could_error(),
4174            BinaryFunc::JsonbDeleteInt64(s) => s.could_error(),
4175            BinaryFunc::JsonbDeleteString(s) => s.could_error(),
4176            BinaryFunc::MapContainsKey(s) => s.could_error(),
4177            BinaryFunc::MapGetValue(s) => s.could_error(),
4178            BinaryFunc::MapContainsAllKeys(s) => s.could_error(),
4179            BinaryFunc::MapContainsAnyKeys(s) => s.could_error(),
4180            BinaryFunc::MapContainsMap(s) => s.could_error(),
4181            BinaryFunc::ConvertFrom(s) => s.could_error(),
4182            BinaryFunc::Left(s) => s.could_error(),
4183            BinaryFunc::Position(s) => s.could_error(),
4184            BinaryFunc::Right(s) => s.could_error(),
4185            BinaryFunc::RepeatString => true,
4186            BinaryFunc::Normalize => true,
4187            BinaryFunc::EncodedBytesCharLength(s) => s.could_error(),
4188            BinaryFunc::ListLengthMax(s) => s.could_error(),
4189            BinaryFunc::ArrayLength(s) => s.could_error(),
4190            BinaryFunc::ArrayRemove(s) => s.could_error(),
4191            BinaryFunc::ArrayUpper(s) => s.could_error(),
4192            BinaryFunc::ArrayArrayConcat(s) => s.could_error(),
4193            BinaryFunc::DigestString(s) => s.could_error(),
4194            BinaryFunc::DigestBytes(s) => s.could_error(),
4195            BinaryFunc::MzRenderTypmod(s) => s.could_error(),
4196            BinaryFunc::Encode(s) => s.could_error(),
4197            BinaryFunc::Decode(s) => s.could_error(),
4198            BinaryFunc::LogNumeric(s) => s.could_error(),
4199            BinaryFunc::Power(s) => s.could_error(),
4200            BinaryFunc::PowerNumeric(s) => s.could_error(),
4201            BinaryFunc::GetBit(s) => s.could_error(),
4202            BinaryFunc::GetByte(s) => s.could_error(),
4203            BinaryFunc::ConstantTimeEqBytes(s) => s.could_error(),
4204            BinaryFunc::ConstantTimeEqString(s) => s.could_error(),
4205            BinaryFunc::RangeUnion(s) => s.could_error(),
4206            BinaryFunc::RangeIntersection(s) => s.could_error(),
4207            BinaryFunc::RangeDifference(s) => s.could_error(),
4208            BinaryFunc::UuidGenerateV5(s) => s.could_error(),
4209            BinaryFunc::MzAclItemContainsPrivilege(s) => s.could_error(),
4210            BinaryFunc::ParseIdent(s) => s.could_error(),
4211            BinaryFunc::PrettySql(s) => s.could_error(),
4212            BinaryFunc::RegexpReplace { .. } => true,
4213        }
4214    }
4215
4216    /// Returns true if the function is monotone. (Non-strict; either increasing or decreasing.)
4217    /// Monotone functions map ranges to ranges: ie. given a range of possible inputs, we can
4218    /// determine the range of possible outputs just by mapping the endpoints.
4219    ///
4220    /// This describes the *pointwise* behaviour of the function:
4221    /// ie. the behaviour of any specific argument as the others are held constant. (For example, `a - b` is
4222    /// monotone in the first argument because for any particular value of `b`, increasing `a` will
4223    /// always cause the result to increase... and in the second argument because for any specific `a`,
4224    /// increasing `b` will always cause the result to _decrease_.)
4225    ///
4226    /// This property describes the behaviour of the function over ranges where the function is defined:
4227    /// ie. the arguments and the result are non-error datums.
4228    pub fn is_monotone(&self) -> (bool, bool) {
4229        match self {
4230            BinaryFunc::AddInt16(s) => s.is_monotone(),
4231            BinaryFunc::AddInt32(s) => s.is_monotone(),
4232            BinaryFunc::AddInt64(s) => s.is_monotone(),
4233            BinaryFunc::AddUint16(s) => s.is_monotone(),
4234            BinaryFunc::AddUint32(s) => s.is_monotone(),
4235            BinaryFunc::AddUint64(s) => s.is_monotone(),
4236            BinaryFunc::AddFloat32(s) => s.is_monotone(),
4237            BinaryFunc::AddFloat64(s) => s.is_monotone(),
4238            BinaryFunc::AddInterval(s) => s.is_monotone(),
4239            BinaryFunc::AddTimestampInterval(s) => s.is_monotone(),
4240            BinaryFunc::AddTimestampTzInterval(s) => s.is_monotone(),
4241            BinaryFunc::AddDateInterval(s) => s.is_monotone(),
4242            BinaryFunc::AddDateTime(s) => s.is_monotone(),
4243            BinaryFunc::AddNumeric(s) => s.is_monotone(),
4244            // <time> + <interval> wraps!
4245            BinaryFunc::AddTimeInterval(s) => s.is_monotone(),
4246            BinaryFunc::BitAndInt16(s) => s.is_monotone(),
4247            BinaryFunc::BitAndInt32(s) => s.is_monotone(),
4248            BinaryFunc::BitAndInt64(s) => s.is_monotone(),
4249            BinaryFunc::BitAndUint16(s) => s.is_monotone(),
4250            BinaryFunc::BitAndUint32(s) => s.is_monotone(),
4251            BinaryFunc::BitAndUint64(s) => s.is_monotone(),
4252            BinaryFunc::BitOrInt16(s) => s.is_monotone(),
4253            BinaryFunc::BitOrInt32(s) => s.is_monotone(),
4254            BinaryFunc::BitOrInt64(s) => s.is_monotone(),
4255            BinaryFunc::BitOrUint16(s) => s.is_monotone(),
4256            BinaryFunc::BitOrUint32(s) => s.is_monotone(),
4257            BinaryFunc::BitOrUint64(s) => s.is_monotone(),
4258            BinaryFunc::BitXorInt16(s) => s.is_monotone(),
4259            BinaryFunc::BitXorInt32(s) => s.is_monotone(),
4260            BinaryFunc::BitXorInt64(s) => s.is_monotone(),
4261            BinaryFunc::BitXorUint16(s) => s.is_monotone(),
4262            BinaryFunc::BitXorUint32(s) => s.is_monotone(),
4263            BinaryFunc::BitXorUint64(s) => s.is_monotone(),
4264            // The shift functions wrap, which means they are monotonic in neither argument.
4265            BinaryFunc::BitShiftLeftInt16(s) => s.is_monotone(),
4266            BinaryFunc::BitShiftLeftInt32(s) => s.is_monotone(),
4267            BinaryFunc::BitShiftLeftInt64(s) => s.is_monotone(),
4268            BinaryFunc::BitShiftLeftUint16(s) => s.is_monotone(),
4269            BinaryFunc::BitShiftLeftUint32(s) => s.is_monotone(),
4270            BinaryFunc::BitShiftLeftUint64(s) => s.is_monotone(),
4271            BinaryFunc::BitShiftRightInt16(s) => s.is_monotone(),
4272            BinaryFunc::BitShiftRightInt32(s) => s.is_monotone(),
4273            BinaryFunc::BitShiftRightInt64(s) => s.is_monotone(),
4274            BinaryFunc::BitShiftRightUint16(s) => s.is_monotone(),
4275            BinaryFunc::BitShiftRightUint32(s) => s.is_monotone(),
4276            BinaryFunc::BitShiftRightUint64(s) => s.is_monotone(),
4277            BinaryFunc::SubInt16(s) => s.is_monotone(),
4278            BinaryFunc::SubInt32(s) => s.is_monotone(),
4279            BinaryFunc::SubInt64(s) => s.is_monotone(),
4280            BinaryFunc::SubUint16(s) => s.is_monotone(),
4281            BinaryFunc::SubUint32(s) => s.is_monotone(),
4282            BinaryFunc::SubUint64(s) => s.is_monotone(),
4283            BinaryFunc::SubFloat32(s) => s.is_monotone(),
4284            BinaryFunc::SubFloat64(s) => s.is_monotone(),
4285            BinaryFunc::SubInterval(s) => s.is_monotone(),
4286            BinaryFunc::SubTimestamp(s) => s.is_monotone(),
4287            BinaryFunc::SubTimestampTz(s) => s.is_monotone(),
4288            BinaryFunc::SubTimestampInterval(s) => s.is_monotone(),
4289            BinaryFunc::SubTimestampTzInterval(s) => s.is_monotone(),
4290            BinaryFunc::SubDate(s) => s.is_monotone(),
4291            BinaryFunc::SubDateInterval(s) => s.is_monotone(),
4292            BinaryFunc::SubTime(s) => s.is_monotone(),
4293            BinaryFunc::SubNumeric(s) => s.is_monotone(),
4294            // <time> - <interval> wraps!
4295            BinaryFunc::SubTimeInterval(s) => s.is_monotone(),
4296            BinaryFunc::MulInt16(s) => s.is_monotone(),
4297            BinaryFunc::MulInt32(s) => s.is_monotone(),
4298            BinaryFunc::MulInt64(s) => s.is_monotone(),
4299            BinaryFunc::MulUint16(s) => s.is_monotone(),
4300            BinaryFunc::MulUint32(s) => s.is_monotone(),
4301            BinaryFunc::MulUint64(s) => s.is_monotone(),
4302            BinaryFunc::MulFloat32(s) => s.is_monotone(),
4303            BinaryFunc::MulFloat64(s) => s.is_monotone(),
4304            BinaryFunc::MulNumeric(s) => s.is_monotone(),
4305            BinaryFunc::MulInterval(s) => s.is_monotone(),
4306            BinaryFunc::DivInt16(s) => s.is_monotone(),
4307            BinaryFunc::DivInt32(s) => s.is_monotone(),
4308            BinaryFunc::DivInt64(s) => s.is_monotone(),
4309            BinaryFunc::DivUint16(s) => s.is_monotone(),
4310            BinaryFunc::DivUint32(s) => s.is_monotone(),
4311            BinaryFunc::DivUint64(s) => s.is_monotone(),
4312            BinaryFunc::DivFloat32(s) => s.is_monotone(),
4313            BinaryFunc::DivFloat64(s) => s.is_monotone(),
4314            BinaryFunc::DivNumeric(s) => s.is_monotone(),
4315            BinaryFunc::DivInterval(s) => s.is_monotone(),
4316            BinaryFunc::ModInt16(s) => s.is_monotone(),
4317            BinaryFunc::ModInt32(s) => s.is_monotone(),
4318            BinaryFunc::ModInt64(s) => s.is_monotone(),
4319            BinaryFunc::ModUint16(s) => s.is_monotone(),
4320            BinaryFunc::ModUint32(s) => s.is_monotone(),
4321            BinaryFunc::ModUint64(s) => s.is_monotone(),
4322            BinaryFunc::ModFloat32(s) => s.is_monotone(),
4323            BinaryFunc::ModFloat64(s) => s.is_monotone(),
4324            BinaryFunc::ModNumeric(s) => s.is_monotone(),
4325            BinaryFunc::RoundNumeric(s) => s.is_monotone(),
4326            BinaryFunc::Eq(s) => s.is_monotone(),
4327            BinaryFunc::NotEq(s) => s.is_monotone(),
4328            BinaryFunc::Lt(s) => s.is_monotone(),
4329            BinaryFunc::Lte(s) => s.is_monotone(),
4330            BinaryFunc::Gt(s) => s.is_monotone(),
4331            BinaryFunc::Gte(s) => s.is_monotone(),
4332            BinaryFunc::LikeEscape(s) => s.is_monotone(),
4333            BinaryFunc::IsLikeMatchCaseInsensitive(s) => s.is_monotone(),
4334            BinaryFunc::IsLikeMatchCaseSensitive(s) => s.is_monotone(),
4335            BinaryFunc::IsRegexpMatch { .. } => (false, false),
4336            BinaryFunc::ToCharTimestamp(s) => s.is_monotone(),
4337            BinaryFunc::ToCharTimestampTz(s) => s.is_monotone(),
4338            BinaryFunc::DateBinTimestamp(s) => s.is_monotone(),
4339            BinaryFunc::DateBinTimestampTz(s) => s.is_monotone(),
4340            BinaryFunc::AgeTimestamp(s) => s.is_monotone(),
4341            BinaryFunc::AgeTimestampTz(s) => s.is_monotone(),
4342            BinaryFunc::TextConcat(s) => s.is_monotone(),
4343            BinaryFunc::Left(s) => s.is_monotone(),
4344            // TODO: can these ever be treated as monotone? It's safe to treat the unary versions
4345            // as monotone in some cases, but only when extracting specific parts.
4346            BinaryFunc::ExtractInterval(s) => s.is_monotone(),
4347            BinaryFunc::ExtractTime(s) => s.is_monotone(),
4348            BinaryFunc::ExtractTimestamp(s) => s.is_monotone(),
4349            BinaryFunc::ExtractTimestampTz(s) => s.is_monotone(),
4350            BinaryFunc::ExtractDate(s) => s.is_monotone(),
4351            BinaryFunc::DatePartInterval(s) => s.is_monotone(),
4352            BinaryFunc::DatePartTime(s) => s.is_monotone(),
4353            BinaryFunc::DatePartTimestamp(s) => s.is_monotone(),
4354            BinaryFunc::DatePartTimestampTz(s) => s.is_monotone(),
4355            BinaryFunc::DateTruncTimestamp(s) => s.is_monotone(),
4356            BinaryFunc::DateTruncTimestampTz(s) => s.is_monotone(),
4357            BinaryFunc::DateTruncInterval(s) => s.is_monotone(),
4358            BinaryFunc::TimezoneTimestamp
4359            | BinaryFunc::TimezoneTimestampTz
4360            | BinaryFunc::TimezoneIntervalTimestamp
4361            | BinaryFunc::TimezoneIntervalTimestampTz
4362            | BinaryFunc::TimezoneIntervalTime => (false, false),
4363            BinaryFunc::TimezoneOffset(s) => s.is_monotone(),
4364            BinaryFunc::JsonbGetInt64(s) => s.is_monotone(),
4365            BinaryFunc::JsonbGetInt64Stringify(s) => s.is_monotone(),
4366            BinaryFunc::JsonbGetString(s) => s.is_monotone(),
4367            BinaryFunc::JsonbGetStringStringify(s) => s.is_monotone(),
4368            BinaryFunc::JsonbGetPath(s) => s.is_monotone(),
4369            BinaryFunc::JsonbGetPathStringify(s) => s.is_monotone(),
4370            BinaryFunc::JsonbContainsString(s) => s.is_monotone(),
4371            BinaryFunc::JsonbConcat(s) => s.is_monotone(),
4372            BinaryFunc::JsonbContainsJsonb(s) => s.is_monotone(),
4373            BinaryFunc::JsonbDeleteInt64(s) => s.is_monotone(),
4374            BinaryFunc::JsonbDeleteString(s) => s.is_monotone(),
4375            BinaryFunc::MapContainsKey(s) => s.is_monotone(),
4376            BinaryFunc::MapGetValue(s) => s.is_monotone(),
4377            BinaryFunc::MapContainsAllKeys(s) => s.is_monotone(),
4378            BinaryFunc::MapContainsAnyKeys(s) => s.is_monotone(),
4379            BinaryFunc::MapContainsMap(s) => s.is_monotone(),
4380            BinaryFunc::ConvertFrom(s) => s.is_monotone(),
4381            BinaryFunc::Position(s) => s.is_monotone(),
4382            BinaryFunc::Right(s) => s.is_monotone(),
4383            BinaryFunc::RepeatString => (false, false),
4384            BinaryFunc::Trim(s) => s.is_monotone(),
4385            BinaryFunc::TrimLeading(s) => s.is_monotone(),
4386            BinaryFunc::TrimTrailing(s) => s.is_monotone(),
4387            BinaryFunc::EncodedBytesCharLength(s) => s.is_monotone(),
4388            BinaryFunc::ListLengthMax(s) => s.is_monotone(),
4389            BinaryFunc::ArrayContains(s) => s.is_monotone(),
4390            BinaryFunc::ArrayContainsArray(s) => s.is_monotone(),
4391            BinaryFunc::ArrayContainsArrayRev(s) => s.is_monotone(),
4392            BinaryFunc::ArrayLength(s) => s.is_monotone(),
4393            BinaryFunc::ArrayLower(s) => s.is_monotone(),
4394            BinaryFunc::ArrayRemove(s) => s.is_monotone(),
4395            BinaryFunc::ArrayUpper(s) => s.is_monotone(),
4396            BinaryFunc::ArrayArrayConcat(s) => s.is_monotone(),
4397            BinaryFunc::ListListConcat(s) => s.is_monotone(),
4398            BinaryFunc::ListElementConcat(s) => s.is_monotone(),
4399            BinaryFunc::ElementListConcat(s) => s.is_monotone(),
4400            BinaryFunc::ListContainsList(s) => s.is_monotone(),
4401            BinaryFunc::ListContainsListRev(s) => s.is_monotone(),
4402            BinaryFunc::ListRemove(s) => s.is_monotone(),
4403            BinaryFunc::DigestString(s) => s.is_monotone(),
4404            BinaryFunc::DigestBytes(s) => s.is_monotone(),
4405            BinaryFunc::MzRenderTypmod(s) => s.is_monotone(),
4406            BinaryFunc::Encode(s) => s.is_monotone(),
4407            BinaryFunc::Decode(s) => s.is_monotone(),
4408            // TODO: it may be safe to treat these as monotone.
4409            BinaryFunc::LogNumeric(s) => s.is_monotone(),
4410            BinaryFunc::Power(s) => s.is_monotone(),
4411            BinaryFunc::PowerNumeric(s) => s.is_monotone(),
4412            BinaryFunc::GetBit(s) => s.is_monotone(),
4413            BinaryFunc::GetByte(s) => s.is_monotone(),
4414            BinaryFunc::RangeContainsElem { .. } => (false, false),
4415            BinaryFunc::RangeContainsRange(s) => s.is_monotone(),
4416            BinaryFunc::RangeContainsRangeRev(s) => s.is_monotone(),
4417            BinaryFunc::RangeOverlaps(s) => s.is_monotone(),
4418            BinaryFunc::RangeAfter(s) => s.is_monotone(),
4419            BinaryFunc::RangeBefore(s) => s.is_monotone(),
4420            BinaryFunc::RangeOverleft(s) => s.is_monotone(),
4421            BinaryFunc::RangeOverright(s) => s.is_monotone(),
4422            BinaryFunc::RangeAdjacent(s) => s.is_monotone(),
4423            BinaryFunc::RangeUnion(s) => s.is_monotone(),
4424            BinaryFunc::RangeIntersection(s) => s.is_monotone(),
4425            BinaryFunc::RangeDifference(s) => s.is_monotone(),
4426            BinaryFunc::UuidGenerateV5(s) => s.is_monotone(),
4427            BinaryFunc::MzAclItemContainsPrivilege(s) => s.is_monotone(),
4428            BinaryFunc::ParseIdent(s) => s.is_monotone(),
4429            BinaryFunc::ConstantTimeEqBytes(s) => s.is_monotone(),
4430            BinaryFunc::ConstantTimeEqString(s) => s.is_monotone(),
4431            BinaryFunc::PrettySql(s) => s.is_monotone(),
4432            BinaryFunc::RegexpReplace { .. } => (false, false),
4433            BinaryFunc::StartsWith(s) => s.is_monotone(),
4434            BinaryFunc::Normalize => (false, false),
4435        }
4436    }
4437}
4438
4439impl fmt::Display for BinaryFunc {
4440    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4441        match self {
4442            BinaryFunc::AddInt16(s) => s.fmt(f),
4443            BinaryFunc::AddInt32(s) => s.fmt(f),
4444            BinaryFunc::AddInt64(s) => s.fmt(f),
4445            BinaryFunc::AddUint16(s) => s.fmt(f),
4446            BinaryFunc::AddUint32(s) => s.fmt(f),
4447            BinaryFunc::AddUint64(s) => s.fmt(f),
4448            BinaryFunc::AddFloat32(s) => s.fmt(f),
4449            BinaryFunc::AddFloat64(s) => s.fmt(f),
4450            BinaryFunc::AddNumeric(s) => s.fmt(f),
4451            BinaryFunc::AddInterval(s) => s.fmt(f),
4452            BinaryFunc::AddTimestampInterval(s) => s.fmt(f),
4453            BinaryFunc::AddTimestampTzInterval(s) => s.fmt(f),
4454            BinaryFunc::AddDateTime(s) => s.fmt(f),
4455            BinaryFunc::AddDateInterval(s) => s.fmt(f),
4456            BinaryFunc::AddTimeInterval(s) => s.fmt(f),
4457            BinaryFunc::AgeTimestamp(s) => s.fmt(f),
4458            BinaryFunc::AgeTimestampTz(s) => s.fmt(f),
4459            BinaryFunc::BitAndInt16(s) => s.fmt(f),
4460            BinaryFunc::BitAndInt32(s) => s.fmt(f),
4461            BinaryFunc::BitAndInt64(s) => s.fmt(f),
4462            BinaryFunc::BitAndUint16(s) => s.fmt(f),
4463            BinaryFunc::BitAndUint32(s) => s.fmt(f),
4464            BinaryFunc::BitAndUint64(s) => s.fmt(f),
4465            BinaryFunc::BitOrInt16(s) => s.fmt(f),
4466            BinaryFunc::BitOrInt32(s) => s.fmt(f),
4467            BinaryFunc::BitOrInt64(s) => s.fmt(f),
4468            BinaryFunc::BitOrUint16(s) => s.fmt(f),
4469            BinaryFunc::BitOrUint32(s) => s.fmt(f),
4470            BinaryFunc::BitOrUint64(s) => s.fmt(f),
4471            BinaryFunc::BitXorInt16(s) => s.fmt(f),
4472            BinaryFunc::BitXorInt32(s) => s.fmt(f),
4473            BinaryFunc::BitXorInt64(s) => s.fmt(f),
4474            BinaryFunc::BitXorUint16(s) => s.fmt(f),
4475            BinaryFunc::BitXorUint32(s) => s.fmt(f),
4476            BinaryFunc::BitXorUint64(s) => s.fmt(f),
4477            BinaryFunc::BitShiftLeftInt16(s) => s.fmt(f),
4478            BinaryFunc::BitShiftLeftInt32(s) => s.fmt(f),
4479            BinaryFunc::BitShiftLeftInt64(s) => s.fmt(f),
4480            BinaryFunc::BitShiftLeftUint16(s) => s.fmt(f),
4481            BinaryFunc::BitShiftLeftUint32(s) => s.fmt(f),
4482            BinaryFunc::BitShiftLeftUint64(s) => s.fmt(f),
4483            BinaryFunc::BitShiftRightInt16(s) => s.fmt(f),
4484            BinaryFunc::BitShiftRightInt32(s) => s.fmt(f),
4485            BinaryFunc::BitShiftRightInt64(s) => s.fmt(f),
4486            BinaryFunc::BitShiftRightUint16(s) => s.fmt(f),
4487            BinaryFunc::BitShiftRightUint32(s) => s.fmt(f),
4488            BinaryFunc::BitShiftRightUint64(s) => s.fmt(f),
4489            BinaryFunc::SubInt16(s) => s.fmt(f),
4490            BinaryFunc::SubInt32(s) => s.fmt(f),
4491            BinaryFunc::SubInt64(s) => s.fmt(f),
4492            BinaryFunc::SubUint16(s) => s.fmt(f),
4493            BinaryFunc::SubUint32(s) => s.fmt(f),
4494            BinaryFunc::SubUint64(s) => s.fmt(f),
4495            BinaryFunc::SubFloat32(s) => s.fmt(f),
4496            BinaryFunc::SubFloat64(s) => s.fmt(f),
4497            BinaryFunc::SubNumeric(s) => s.fmt(f),
4498            BinaryFunc::SubInterval(s) => s.fmt(f),
4499            BinaryFunc::SubTimestamp(s) => s.fmt(f),
4500            BinaryFunc::SubTimestampTz(s) => s.fmt(f),
4501            BinaryFunc::SubTimestampInterval(s) => s.fmt(f),
4502            BinaryFunc::SubTimestampTzInterval(s) => s.fmt(f),
4503            BinaryFunc::SubDate(s) => s.fmt(f),
4504            BinaryFunc::SubDateInterval(s) => s.fmt(f),
4505            BinaryFunc::SubTime(s) => s.fmt(f),
4506            BinaryFunc::SubTimeInterval(s) => s.fmt(f),
4507            BinaryFunc::MulInt16(s) => s.fmt(f),
4508            BinaryFunc::MulInt32(s) => s.fmt(f),
4509            BinaryFunc::MulInt64(s) => s.fmt(f),
4510            BinaryFunc::MulUint16(s) => s.fmt(f),
4511            BinaryFunc::MulUint32(s) => s.fmt(f),
4512            BinaryFunc::MulUint64(s) => s.fmt(f),
4513            BinaryFunc::MulFloat32(s) => s.fmt(f),
4514            BinaryFunc::MulFloat64(s) => s.fmt(f),
4515            BinaryFunc::MulNumeric(s) => s.fmt(f),
4516            BinaryFunc::MulInterval(s) => s.fmt(f),
4517            BinaryFunc::DivInt16(s) => s.fmt(f),
4518            BinaryFunc::DivInt32(s) => s.fmt(f),
4519            BinaryFunc::DivInt64(s) => s.fmt(f),
4520            BinaryFunc::DivUint16(s) => s.fmt(f),
4521            BinaryFunc::DivUint32(s) => s.fmt(f),
4522            BinaryFunc::DivUint64(s) => s.fmt(f),
4523            BinaryFunc::DivFloat32(s) => s.fmt(f),
4524            BinaryFunc::DivFloat64(s) => s.fmt(f),
4525            BinaryFunc::DivNumeric(s) => s.fmt(f),
4526            BinaryFunc::DivInterval(s) => s.fmt(f),
4527            BinaryFunc::ModInt16(s) => s.fmt(f),
4528            BinaryFunc::ModInt32(s) => s.fmt(f),
4529            BinaryFunc::ModInt64(s) => s.fmt(f),
4530            BinaryFunc::ModUint16(s) => s.fmt(f),
4531            BinaryFunc::ModUint32(s) => s.fmt(f),
4532            BinaryFunc::ModUint64(s) => s.fmt(f),
4533            BinaryFunc::ModFloat32(s) => s.fmt(f),
4534            BinaryFunc::ModFloat64(s) => s.fmt(f),
4535            BinaryFunc::ModNumeric(s) => s.fmt(f),
4536            BinaryFunc::Eq(s) => s.fmt(f),
4537            BinaryFunc::NotEq(s) => s.fmt(f),
4538            BinaryFunc::Lt(s) => s.fmt(f),
4539            BinaryFunc::Lte(s) => s.fmt(f),
4540            BinaryFunc::Gt(s) => s.fmt(f),
4541            BinaryFunc::Gte(s) => s.fmt(f),
4542            BinaryFunc::LikeEscape(s) => s.fmt(f),
4543            BinaryFunc::IsLikeMatchCaseSensitive(s) => s.fmt(f),
4544            BinaryFunc::IsLikeMatchCaseInsensitive(s) => s.fmt(f),
4545            BinaryFunc::IsRegexpMatch {
4546                case_insensitive: false,
4547            } => f.write_str("~"),
4548            BinaryFunc::IsRegexpMatch {
4549                case_insensitive: true,
4550            } => f.write_str("~*"),
4551            BinaryFunc::ToCharTimestamp(s) => s.fmt(f),
4552            BinaryFunc::ToCharTimestampTz(s) => s.fmt(f),
4553            BinaryFunc::DateBinTimestamp(s) => s.fmt(f),
4554            BinaryFunc::DateBinTimestampTz(s) => s.fmt(f),
4555            BinaryFunc::ExtractInterval(s) => s.fmt(f),
4556            BinaryFunc::ExtractTime(s) => s.fmt(f),
4557            BinaryFunc::ExtractTimestamp(s) => s.fmt(f),
4558            BinaryFunc::ExtractTimestampTz(s) => s.fmt(f),
4559            BinaryFunc::ExtractDate(s) => s.fmt(f),
4560            BinaryFunc::DatePartInterval(s) => s.fmt(f),
4561            BinaryFunc::DatePartTime(s) => s.fmt(f),
4562            BinaryFunc::DatePartTimestamp(s) => s.fmt(f),
4563            BinaryFunc::DatePartTimestampTz(s) => s.fmt(f),
4564            BinaryFunc::DateTruncTimestamp(s) => s.fmt(f),
4565            BinaryFunc::DateTruncInterval(s) => s.fmt(f),
4566            BinaryFunc::DateTruncTimestampTz(s) => s.fmt(f),
4567            BinaryFunc::TimezoneTimestamp => f.write_str("timezonets"),
4568            BinaryFunc::TimezoneTimestampTz => f.write_str("timezonetstz"),
4569            BinaryFunc::TimezoneIntervalTimestamp => f.write_str("timezoneits"),
4570            BinaryFunc::TimezoneIntervalTimestampTz => f.write_str("timezoneitstz"),
4571            BinaryFunc::TimezoneIntervalTime => f.write_str("timezoneit"),
4572            BinaryFunc::TimezoneOffset(s) => s.fmt(f),
4573            BinaryFunc::TextConcat(s) => s.fmt(f),
4574            BinaryFunc::JsonbGetInt64(s) => s.fmt(f),
4575            BinaryFunc::JsonbGetInt64Stringify(s) => s.fmt(f),
4576            BinaryFunc::JsonbGetString(s) => s.fmt(f),
4577            BinaryFunc::JsonbGetStringStringify(s) => s.fmt(f),
4578            BinaryFunc::JsonbGetPath(s) => s.fmt(f),
4579            BinaryFunc::JsonbGetPathStringify(s) => s.fmt(f),
4580            BinaryFunc::JsonbContainsString(s) => s.fmt(f),
4581            BinaryFunc::MapContainsKey(s) => s.fmt(f),
4582            BinaryFunc::JsonbConcat(s) => s.fmt(f),
4583            BinaryFunc::JsonbContainsJsonb(s) => s.fmt(f),
4584            BinaryFunc::MapContainsMap(s) => s.fmt(f),
4585            BinaryFunc::JsonbDeleteInt64(s) => s.fmt(f),
4586            BinaryFunc::JsonbDeleteString(s) => s.fmt(f),
4587            BinaryFunc::MapGetValue(s) => s.fmt(f),
4588            BinaryFunc::MapContainsAllKeys(s) => s.fmt(f),
4589            BinaryFunc::MapContainsAnyKeys(s) => s.fmt(f),
4590            BinaryFunc::RoundNumeric(s) => s.fmt(f),
4591            BinaryFunc::ConvertFrom(s) => s.fmt(f),
4592            BinaryFunc::Left(s) => s.fmt(f),
4593            BinaryFunc::Position(s) => s.fmt(f),
4594            BinaryFunc::Right(s) => s.fmt(f),
4595            BinaryFunc::Trim(s) => s.fmt(f),
4596            BinaryFunc::TrimLeading(s) => s.fmt(f),
4597            BinaryFunc::TrimTrailing(s) => s.fmt(f),
4598            BinaryFunc::EncodedBytesCharLength(s) => s.fmt(f),
4599            BinaryFunc::ListLengthMax(s) => s.fmt(f),
4600            BinaryFunc::ArrayContains(s) => s.fmt(f),
4601            BinaryFunc::ArrayContainsArray(s) => s.fmt(f),
4602            BinaryFunc::ArrayContainsArrayRev(s) => s.fmt(f),
4603            BinaryFunc::ArrayLength(s) => s.fmt(f),
4604            BinaryFunc::ArrayLower(s) => s.fmt(f),
4605            BinaryFunc::ArrayRemove(s) => s.fmt(f),
4606            BinaryFunc::ArrayUpper(s) => s.fmt(f),
4607            BinaryFunc::ArrayArrayConcat(s) => s.fmt(f),
4608            BinaryFunc::ListListConcat(s) => s.fmt(f),
4609            BinaryFunc::ListElementConcat(s) => s.fmt(f),
4610            BinaryFunc::ElementListConcat(s) => s.fmt(f),
4611            BinaryFunc::ListRemove(s) => s.fmt(f),
4612            BinaryFunc::ListContainsList(s) => s.fmt(f),
4613            BinaryFunc::ListContainsListRev(s) => s.fmt(f),
4614            BinaryFunc::DigestString(s) => s.fmt(f),
4615            BinaryFunc::DigestBytes(s) => s.fmt(f),
4616            BinaryFunc::MzRenderTypmod(s) => s.fmt(f),
4617            BinaryFunc::Encode(s) => s.fmt(f),
4618            BinaryFunc::Decode(s) => s.fmt(f),
4619            BinaryFunc::LogNumeric(s) => s.fmt(f),
4620            BinaryFunc::Power(s) => s.fmt(f),
4621            BinaryFunc::PowerNumeric(s) => s.fmt(f),
4622            BinaryFunc::RepeatString => f.write_str("repeat"),
4623            BinaryFunc::Normalize => f.write_str("normalize"),
4624            BinaryFunc::GetBit(s) => s.fmt(f),
4625            BinaryFunc::GetByte(s) => s.fmt(f),
4626            BinaryFunc::ConstantTimeEqBytes(s) => s.fmt(f),
4627            BinaryFunc::ConstantTimeEqString(s) => s.fmt(f),
4628            BinaryFunc::RangeContainsElem { rev, .. } => {
4629                f.write_str(if *rev { "<@" } else { "@>" })
4630            }
4631            BinaryFunc::RangeContainsRange(s) => s.fmt(f),
4632            BinaryFunc::RangeContainsRangeRev(s) => s.fmt(f),
4633            BinaryFunc::RangeOverlaps(s) => s.fmt(f),
4634            BinaryFunc::RangeAfter(s) => s.fmt(f),
4635            BinaryFunc::RangeBefore(s) => s.fmt(f),
4636            BinaryFunc::RangeOverleft(s) => s.fmt(f),
4637            BinaryFunc::RangeOverright(s) => s.fmt(f),
4638            BinaryFunc::RangeAdjacent(s) => s.fmt(f),
4639            BinaryFunc::RangeUnion(s) => s.fmt(f),
4640            BinaryFunc::RangeIntersection(s) => s.fmt(f),
4641            BinaryFunc::RangeDifference(s) => s.fmt(f),
4642            BinaryFunc::UuidGenerateV5(s) => s.fmt(f),
4643            BinaryFunc::MzAclItemContainsPrivilege(s) => s.fmt(f),
4644            BinaryFunc::ParseIdent(s) => s.fmt(f),
4645            BinaryFunc::PrettySql(s) => s.fmt(f),
4646            BinaryFunc::RegexpReplace { regex, limit } => write!(
4647                f,
4648                "regexp_replace[{}, case_insensitive={}, limit={}]",
4649                regex.pattern().escaped(),
4650                regex.case_insensitive,
4651                limit
4652            ),
4653            BinaryFunc::StartsWith(s) => s.fmt(f),
4654        }
4655    }
4656}
4657
4658#[sqlfunc(
4659    sqlname = "||",
4660    is_infix_op = true,
4661    propagates_nulls = true,
4662    // Text concatenation is monotonic in its second argument, because if I change the
4663    // second argument but don't change the first argument, then we won't find a difference
4664    // in that part of the concatenation result that came from the first argument, so we'll
4665    // find the difference that comes from changing the second argument.
4666    // (It's not monotonic in its first argument, because e.g.,
4667    // 'A' < 'AA' but 'AZ' > 'AAZ'.)
4668    is_monotone = (false, true),
4669)]
4670fn text_concat_binary(a: &str, b: &str) -> Result<String, EvalError> {
4671    if a.len() + b.len() > MAX_STRING_FUNC_RESULT_BYTES {
4672        return Err(EvalError::LengthTooLarge);
4673    }
4674    let mut buf = String::with_capacity(a.len() + b.len());
4675    buf.push_str(a);
4676    buf.push_str(b);
4677    Ok(buf)
4678}
4679
4680#[sqlfunc(propagates_nulls = true, introduces_nulls = false)]
4681fn like_escape<'a>(
4682    pattern: &str,
4683    b: &str,
4684    temp_storage: &'a RowArena,
4685) -> Result<&'a str, EvalError> {
4686    let escape = like_pattern::EscapeBehavior::from_str(b)?;
4687    let normalized = like_pattern::normalize_pattern(pattern, escape)?;
4688    Ok(temp_storage.push_string(normalized))
4689}
4690
4691#[sqlfunc(is_infix_op = true, sqlname = "like")]
4692fn is_like_match_case_sensitive(haystack: &str, pattern: &str) -> Result<bool, EvalError> {
4693    like_pattern::compile(pattern, false).map(|needle| needle.is_match(haystack))
4694}
4695
4696#[sqlfunc(is_infix_op = true, sqlname = "ilike")]
4697fn is_like_match_case_insensitive(haystack: &str, pattern: &str) -> Result<bool, EvalError> {
4698    like_pattern::compile(pattern, true).map(|needle| needle.is_match(haystack))
4699}
4700
4701fn is_regexp_match_dynamic<'a>(
4702    a: Datum<'a>,
4703    b: Datum<'a>,
4704    case_insensitive: bool,
4705) -> Result<Datum<'a>, EvalError> {
4706    let haystack = a.unwrap_str();
4707    let needle = build_regex(b.unwrap_str(), if case_insensitive { "i" } else { "" })?;
4708    Ok(Datum::from(needle.is_match(haystack)))
4709}
4710
4711fn regexp_match_static<'a>(
4712    haystack: Datum<'a>,
4713    temp_storage: &'a RowArena,
4714    needle: &regex::Regex,
4715) -> Result<Datum<'a>, EvalError> {
4716    let mut row = Row::default();
4717    let mut packer = row.packer();
4718    if needle.captures_len() > 1 {
4719        // The regex contains capture groups, so return an array containing the
4720        // matched text in each capture group, unless the entire match fails.
4721        // Individual capture groups may also be null if that group did not
4722        // participate in the match.
4723        match needle.captures(haystack.unwrap_str()) {
4724            None => packer.push(Datum::Null),
4725            Some(captures) => packer.try_push_array(
4726                &[ArrayDimension {
4727                    lower_bound: 1,
4728                    length: captures.len() - 1,
4729                }],
4730                // Skip the 0th capture group, which is the whole match.
4731                captures.iter().skip(1).map(|mtch| match mtch {
4732                    None => Datum::Null,
4733                    Some(mtch) => Datum::String(mtch.as_str()),
4734                }),
4735            )?,
4736        }
4737    } else {
4738        // The regex contains no capture groups, so return a one-element array
4739        // containing the match, or null if there is no match.
4740        match needle.find(haystack.unwrap_str()) {
4741            None => packer.push(Datum::Null),
4742            Some(mtch) => packer.try_push_array(
4743                &[ArrayDimension {
4744                    lower_bound: 1,
4745                    length: 1,
4746                }],
4747                iter::once(Datum::String(mtch.as_str())),
4748            )?,
4749        };
4750    };
4751    Ok(temp_storage.push_unary_row(row))
4752}
4753
4754/// Sets `limit` based on the presence of 'g' in `flags` for use in `Regex::replacen`,
4755/// and removes 'g' from `flags` if present.
4756pub(crate) fn regexp_replace_parse_flags(flags: &str) -> (usize, Cow<'_, str>) {
4757    // 'g' means to replace all instead of the first. Use a Cow to avoid allocating in the fast
4758    // path. We could switch build_regex to take an iter which would also achieve that.
4759    let (limit, flags) = if flags.contains('g') {
4760        let flags = flags.replace('g', "");
4761        (0, Cow::Owned(flags))
4762    } else {
4763        (1, Cow::Borrowed(flags))
4764    };
4765    (limit, flags)
4766}
4767
4768// WARNING: This function has potential OOM risk if used with an inflationary
4769// replacement pattern. It is very difficult to calculate the output size ahead
4770// of time because the replacement pattern may depend on capture groups.
4771fn regexp_replace_static<'a>(
4772    source: Datum<'a>,
4773    replacement: Datum<'a>,
4774    regexp: &regex::Regex,
4775    limit: usize,
4776    temp_storage: &'a RowArena,
4777) -> Result<Datum<'a>, EvalError> {
4778    let replaced = match regexp.replacen(source.unwrap_str(), limit, replacement.unwrap_str()) {
4779        Cow::Borrowed(s) => s,
4780        Cow::Owned(s) => temp_storage.push_string(s),
4781    };
4782    Ok(Datum::String(replaced))
4783}
4784
4785pub fn build_regex(needle: &str, flags: &str) -> Result<Regex, EvalError> {
4786    let mut case_insensitive = false;
4787    // Note: Postgres accepts it when both flags are present, taking the last one. We do the same.
4788    for f in flags.chars() {
4789        match f {
4790            'i' => {
4791                case_insensitive = true;
4792            }
4793            'c' => {
4794                case_insensitive = false;
4795            }
4796            _ => return Err(EvalError::InvalidRegexFlag(f)),
4797        }
4798    }
4799    Ok(Regex::new(needle, case_insensitive)?)
4800}
4801
4802fn repeat_string<'a>(
4803    string: Datum<'a>,
4804    count: Datum<'a>,
4805    temp_storage: &'a RowArena,
4806) -> Result<Datum<'a>, EvalError> {
4807    let len = usize::try_from(count.unwrap_int32()).unwrap_or(0);
4808    let string = string.unwrap_str();
4809    if (len * string.len()) > MAX_STRING_FUNC_RESULT_BYTES {
4810        return Err(EvalError::LengthTooLarge);
4811    }
4812    Ok(Datum::String(temp_storage.push_string(string.repeat(len))))
4813}
4814
4815/// Constructs a new zero or one dimensional array out of an arbitrary number of
4816/// scalars.
4817///
4818/// If `datums` is empty, constructs a zero-dimensional array. Otherwise,
4819/// constructs a one dimensional array whose lower bound is one and whose length
4820/// is equal to `datums.len()`.
4821fn array_create_scalar<'a>(
4822    datums: &[Datum<'a>],
4823    temp_storage: &'a RowArena,
4824) -> Result<Datum<'a>, EvalError> {
4825    let mut dims = &[ArrayDimension {
4826        lower_bound: 1,
4827        length: datums.len(),
4828    }][..];
4829    if datums.is_empty() {
4830        // Per PostgreSQL, empty arrays are represented with zero dimensions,
4831        // not one dimension of zero length. We write this condition a little
4832        // strangely to satisfy the borrow checker while avoiding an allocation.
4833        dims = &[];
4834    }
4835    let datum = temp_storage.try_make_datum(|packer| packer.try_push_array(dims, datums))?;
4836    Ok(datum)
4837}
4838
4839fn stringify_datum<'a, B>(
4840    buf: &mut B,
4841    d: Datum<'a>,
4842    ty: &SqlScalarType,
4843) -> Result<strconv::Nestable, EvalError>
4844where
4845    B: FormatBuffer,
4846{
4847    use SqlScalarType::*;
4848    match &ty {
4849        AclItem => Ok(strconv::format_acl_item(buf, d.unwrap_acl_item())),
4850        Bool => Ok(strconv::format_bool(buf, d.unwrap_bool())),
4851        Int16 => Ok(strconv::format_int16(buf, d.unwrap_int16())),
4852        Int32 => Ok(strconv::format_int32(buf, d.unwrap_int32())),
4853        Int64 => Ok(strconv::format_int64(buf, d.unwrap_int64())),
4854        UInt16 => Ok(strconv::format_uint16(buf, d.unwrap_uint16())),
4855        UInt32 | Oid | RegClass | RegProc | RegType => {
4856            Ok(strconv::format_uint32(buf, d.unwrap_uint32()))
4857        }
4858        UInt64 => Ok(strconv::format_uint64(buf, d.unwrap_uint64())),
4859        Float32 => Ok(strconv::format_float32(buf, d.unwrap_float32())),
4860        Float64 => Ok(strconv::format_float64(buf, d.unwrap_float64())),
4861        Numeric { .. } => Ok(strconv::format_numeric(buf, &d.unwrap_numeric())),
4862        Date => Ok(strconv::format_date(buf, d.unwrap_date())),
4863        Time => Ok(strconv::format_time(buf, d.unwrap_time())),
4864        Timestamp { .. } => Ok(strconv::format_timestamp(buf, &d.unwrap_timestamp())),
4865        TimestampTz { .. } => Ok(strconv::format_timestamptz(buf, &d.unwrap_timestamptz())),
4866        Interval => Ok(strconv::format_interval(buf, d.unwrap_interval())),
4867        Bytes => Ok(strconv::format_bytes(buf, d.unwrap_bytes())),
4868        String | VarChar { .. } | PgLegacyName => Ok(strconv::format_string(buf, d.unwrap_str())),
4869        Char { length } => Ok(strconv::format_string(
4870            buf,
4871            &mz_repr::adt::char::format_str_pad(d.unwrap_str(), *length),
4872        )),
4873        PgLegacyChar => {
4874            format_pg_legacy_char(buf, d.unwrap_uint8())?;
4875            Ok(strconv::Nestable::MayNeedEscaping)
4876        }
4877        Jsonb => Ok(strconv::format_jsonb(buf, JsonbRef::from_datum(d))),
4878        Uuid => Ok(strconv::format_uuid(buf, d.unwrap_uuid())),
4879        Record { fields, .. } => {
4880            let mut fields = fields.iter();
4881            strconv::format_record(buf, d.unwrap_list(), |buf, d| {
4882                let (_name, ty) = fields.next().unwrap();
4883                if d.is_null() {
4884                    Ok(buf.write_null())
4885                } else {
4886                    stringify_datum(buf.nonnull_buffer(), d, &ty.scalar_type)
4887                }
4888            })
4889        }
4890        Array(elem_type) => strconv::format_array(
4891            buf,
4892            &d.unwrap_array().dims().into_iter().collect::<Vec<_>>(),
4893            d.unwrap_array().elements(),
4894            |buf, d| {
4895                if d.is_null() {
4896                    Ok(buf.write_null())
4897                } else {
4898                    stringify_datum(buf.nonnull_buffer(), d, elem_type)
4899                }
4900            },
4901        ),
4902        List { element_type, .. } => strconv::format_list(buf, d.unwrap_list(), |buf, d| {
4903            if d.is_null() {
4904                Ok(buf.write_null())
4905            } else {
4906                stringify_datum(buf.nonnull_buffer(), d, element_type)
4907            }
4908        }),
4909        Map { value_type, .. } => strconv::format_map(buf, &d.unwrap_map(), |buf, d| {
4910            if d.is_null() {
4911                Ok(buf.write_null())
4912            } else {
4913                stringify_datum(buf.nonnull_buffer(), d, value_type)
4914            }
4915        }),
4916        Int2Vector => strconv::format_legacy_vector(buf, d.unwrap_array().elements(), |buf, d| {
4917            stringify_datum(buf.nonnull_buffer(), d, &SqlScalarType::Int16)
4918        }),
4919        MzTimestamp { .. } => Ok(strconv::format_mz_timestamp(buf, d.unwrap_mz_timestamp())),
4920        Range { element_type } => strconv::format_range(buf, &d.unwrap_range(), |buf, d| match d {
4921            Some(d) => stringify_datum(buf.nonnull_buffer(), *d, element_type),
4922            None => Ok::<_, EvalError>(buf.write_null()),
4923        }),
4924        MzAclItem => Ok(strconv::format_mz_acl_item(buf, d.unwrap_mz_acl_item())),
4925    }
4926}
4927
4928#[sqlfunc(propagates_nulls = true)]
4929fn position(substring: &str, string: &str) -> Result<i32, EvalError> {
4930    let char_index = string.find(substring);
4931
4932    if let Some(char_index) = char_index {
4933        // find the index in char space
4934        let string_prefix = &string[0..char_index];
4935
4936        let num_prefix_chars = string_prefix.chars().count();
4937        let num_prefix_chars = i32::try_from(num_prefix_chars)
4938            .map_err(|_| EvalError::Int32OutOfRange(num_prefix_chars.to_string().into()))?;
4939
4940        Ok(num_prefix_chars + 1)
4941    } else {
4942        Ok(0)
4943    }
4944}
4945
4946#[sqlfunc(
4947    propagates_nulls = true,
4948    // `left` is unfortunately not monotonic (at least for negative second arguments),
4949    // because 'aa' < 'z', but `left(_, -1)` makes 'a' > ''.
4950    is_monotone = (false, false)
4951)]
4952fn left<'a>(string: &'a str, b: i32) -> Result<&'a str, EvalError> {
4953    let n = i64::from(b);
4954
4955    let mut byte_indices = string.char_indices().map(|(i, _)| i);
4956
4957    let end_in_bytes = match n.cmp(&0) {
4958        Ordering::Equal => 0,
4959        Ordering::Greater => {
4960            let n = usize::try_from(n).map_err(|_| {
4961                EvalError::InvalidParameterValue(format!("invalid parameter n: {:?}", n).into())
4962            })?;
4963            // nth from the back
4964            byte_indices.nth(n).unwrap_or(string.len())
4965        }
4966        Ordering::Less => {
4967            let n = usize::try_from(n.abs() - 1).map_err(|_| {
4968                EvalError::InvalidParameterValue(format!("invalid parameter n: {:?}", n).into())
4969            })?;
4970            byte_indices.rev().nth(n).unwrap_or(0)
4971        }
4972    };
4973
4974    Ok(&string[..end_in_bytes])
4975}
4976
4977#[sqlfunc(propagates_nulls = true)]
4978fn right<'a>(string: &'a str, n: i32) -> Result<&'a str, EvalError> {
4979    let mut byte_indices = string.char_indices().map(|(i, _)| i);
4980
4981    let start_in_bytes = if n == 0 {
4982        string.len()
4983    } else if n > 0 {
4984        let n = usize::try_from(n - 1).map_err(|_| {
4985            EvalError::InvalidParameterValue(format!("invalid parameter n: {:?}", n).into())
4986        })?;
4987        // nth from the back
4988        byte_indices.rev().nth(n).unwrap_or(0)
4989    } else if n == i32::MIN {
4990        // this seems strange but Postgres behaves like this
4991        0
4992    } else {
4993        let n = n.abs();
4994        let n = usize::try_from(n).map_err(|_| {
4995            EvalError::InvalidParameterValue(format!("invalid parameter n: {:?}", n).into())
4996        })?;
4997        byte_indices.nth(n).unwrap_or(string.len())
4998    };
4999
5000    Ok(&string[start_in_bytes..])
5001}
5002
5003#[sqlfunc(sqlname = "btrim", propagates_nulls = true)]
5004fn trim<'a>(a: &'a str, trim_chars: &str) -> &'a str {
5005    a.trim_matches(|c| trim_chars.contains(c))
5006}
5007
5008#[sqlfunc(sqlname = "ltrim", propagates_nulls = true)]
5009fn trim_leading<'a>(a: &'a str, trim_chars: &str) -> &'a str {
5010    a.trim_start_matches(|c| trim_chars.contains(c))
5011}
5012
5013#[sqlfunc(sqlname = "rtrim", propagates_nulls = true)]
5014fn trim_trailing<'a>(a: &'a str, trim_chars: &str) -> &'a str {
5015    a.trim_end_matches(|c| trim_chars.contains(c))
5016}
5017
5018#[sqlfunc(
5019    sqlname = "array_length",
5020    propagates_nulls = true,
5021    introduces_nulls = true
5022)]
5023fn array_length<'a>(a: Array<'a>, b: i64) -> Result<Option<i32>, EvalError> {
5024    let i = match usize::try_from(b) {
5025        Ok(0) | Err(_) => return Ok(None),
5026        Ok(n) => n - 1,
5027    };
5028    Ok(match a.dims().into_iter().nth(i) {
5029        None => None,
5030        Some(dim) => Some(
5031            dim.length
5032                .try_into()
5033                .map_err(|_| EvalError::Int32OutOfRange(dim.length.to_string().into()))?,
5034        ),
5035    })
5036}
5037
5038#[sqlfunc(
5039    output_type = "Option<i32>",
5040    is_infix_op = true,
5041    sqlname = "array_lower",
5042    propagates_nulls = true,
5043    introduces_nulls = true
5044)]
5045// TODO(benesch): remove potentially dangerous usage of `as`.
5046#[allow(clippy::as_conversions)]
5047fn array_lower<'a>(a: Array<'a>, i: i64) -> Option<i32> {
5048    if i < 1 {
5049        return None;
5050    }
5051    match a.dims().into_iter().nth(i as usize - 1) {
5052        Some(_) => Some(1),
5053        None => None,
5054    }
5055}
5056
5057#[sqlfunc(
5058    output_type_expr = "input_type_a.scalar_type.without_modifiers().nullable(true)",
5059    sqlname = "array_remove",
5060    propagates_nulls = false,
5061    introduces_nulls = false
5062)]
5063fn array_remove<'a>(
5064    arr: Array<'a>,
5065    b: Datum<'a>,
5066    temp_storage: &'a RowArena,
5067) -> Result<Datum<'a>, EvalError> {
5068    // Zero-dimensional arrays are empty by definition
5069    if arr.dims().len() == 0 {
5070        return Ok(Datum::Array(arr));
5071    }
5072
5073    // array_remove only supports one-dimensional arrays
5074    if arr.dims().len() > 1 {
5075        return Err(EvalError::MultidimensionalArrayRemovalNotSupported);
5076    }
5077
5078    let elems: Vec<_> = arr.elements().iter().filter(|v| v != &b).collect();
5079    let mut dims = arr.dims().into_iter().collect::<Vec<_>>();
5080    // This access is safe because `dims` is guaranteed to be non-empty
5081    dims[0] = ArrayDimension {
5082        lower_bound: 1,
5083        length: elems.len(),
5084    };
5085
5086    Ok(temp_storage.try_make_datum(|packer| packer.try_push_array(&dims, elems))?)
5087}
5088
5089#[sqlfunc(
5090    output_type = "Option<i32>",
5091    is_infix_op = true,
5092    sqlname = "array_upper",
5093    propagates_nulls = true,
5094    introduces_nulls = true
5095)]
5096// TODO(benesch): remove potentially dangerous usage of `as`.
5097#[allow(clippy::as_conversions)]
5098fn array_upper<'a>(a: Array<'a>, i: i64) -> Result<Option<i32>, EvalError> {
5099    if i < 1 {
5100        return Ok(None);
5101    }
5102    a.dims()
5103        .into_iter()
5104        .nth(i as usize - 1)
5105        .map(|dim| {
5106            dim.length
5107                .try_into()
5108                .map_err(|_| EvalError::Int32OutOfRange(dim.length.to_string().into()))
5109        })
5110        .transpose()
5111}
5112
5113#[sqlfunc(
5114    is_infix_op = true,
5115    sqlname = "array_contains",
5116    propagates_nulls = true,
5117    introduces_nulls = false
5118)]
5119fn array_contains<'a>(a: Datum<'a>, array: Array<'a>) -> bool {
5120    array.elements().iter().any(|e| e == a)
5121}
5122
5123#[sqlfunc(is_infix_op = true, sqlname = "@>")]
5124fn array_contains_array<'a>(a: Array<'a>, b: Array<'a>) -> bool {
5125    let a = a.elements();
5126    let b = b.elements();
5127
5128    // NULL is never equal to NULL. If NULL is an element of b, b cannot be contained in a, even if a contains NULL.
5129    if b.iter().contains(&Datum::Null) {
5130        false
5131    } else {
5132        b.iter()
5133            .all(|item_b| a.iter().any(|item_a| item_a == item_b))
5134    }
5135}
5136
5137#[sqlfunc(is_infix_op = true, sqlname = "<@")]
5138fn array_contains_array_rev<'a>(a: Array<'a>, b: Array<'a>) -> bool {
5139    array_contains_array(b, a)
5140}
5141
5142#[sqlfunc(
5143    output_type_expr = "input_type_a.scalar_type.without_modifiers().nullable(true)",
5144    is_infix_op = true,
5145    sqlname = "||",
5146    propagates_nulls = false,
5147    introduces_nulls = false
5148)]
5149fn array_array_concat<'a>(
5150    a: Datum<'a>,
5151    b: Datum<'a>,
5152    temp_storage: &'a RowArena,
5153) -> Result<Datum<'a>, EvalError> {
5154    if a.is_null() {
5155        return Ok(b);
5156    } else if b.is_null() {
5157        return Ok(a);
5158    }
5159
5160    let a_array = a.unwrap_array();
5161    let b_array = b.unwrap_array();
5162
5163    let a_dims: Vec<ArrayDimension> = a_array.dims().into_iter().collect();
5164    let b_dims: Vec<ArrayDimension> = b_array.dims().into_iter().collect();
5165
5166    let a_ndims = a_dims.len();
5167    let b_ndims = b_dims.len();
5168
5169    // Per PostgreSQL, if either of the input arrays is zero dimensional,
5170    // the output is the other array, no matter their dimensions.
5171    if a_ndims == 0 {
5172        return Ok(b);
5173    } else if b_ndims == 0 {
5174        return Ok(a);
5175    }
5176
5177    // Postgres supports concatenating arrays of different dimensions,
5178    // as long as one of the arrays has the same type as an element of
5179    // the other array, i.e. `int[2][4] || int[4]` (or `int[4] || int[2][4]`)
5180    // works, because each element of `int[2][4]` is an `int[4]`.
5181    // This check is separate from the one below because Postgres gives a
5182    // specific error message if the number of dimensions differs by more
5183    // than one.
5184    // This cast is safe since MAX_ARRAY_DIMENSIONS is 6
5185    // Can be replaced by .abs_diff once it is stabilized
5186    // TODO(benesch): remove potentially dangerous usage of `as`.
5187    #[allow(clippy::as_conversions)]
5188    if (a_ndims as isize - b_ndims as isize).abs() > 1 {
5189        return Err(EvalError::IncompatibleArrayDimensions {
5190            dims: Some((a_ndims, b_ndims)),
5191        });
5192    }
5193
5194    let mut dims;
5195
5196    // After the checks above, we are certain that:
5197    // - neither array is zero dimensional nor empty
5198    // - both arrays have the same number of dimensions, or differ
5199    //   at most by one.
5200    match a_ndims.cmp(&b_ndims) {
5201        // If both arrays have the same number of dimensions, validate
5202        // that their inner dimensions are the same and concatenate the
5203        // arrays.
5204        Ordering::Equal => {
5205            if &a_dims[1..] != &b_dims[1..] {
5206                return Err(EvalError::IncompatibleArrayDimensions { dims: None });
5207            }
5208            dims = vec![ArrayDimension {
5209                lower_bound: a_dims[0].lower_bound,
5210                length: a_dims[0].length + b_dims[0].length,
5211            }];
5212            dims.extend(&a_dims[1..]);
5213        }
5214        // If `a` has less dimensions than `b`, this is an element-array
5215        // concatenation, which requires that `a` has the same dimensions
5216        // as an element of `b`.
5217        Ordering::Less => {
5218            if &a_dims[..] != &b_dims[1..] {
5219                return Err(EvalError::IncompatibleArrayDimensions { dims: None });
5220            }
5221            dims = vec![ArrayDimension {
5222                lower_bound: b_dims[0].lower_bound,
5223                // Since `a` is treated as an element of `b`, the length of
5224                // the first dimension of `b` is incremented by one, as `a` is
5225                // non-empty.
5226                length: b_dims[0].length + 1,
5227            }];
5228            dims.extend(a_dims);
5229        }
5230        // If `a` has more dimensions than `b`, this is an array-element
5231        // concatenation, which requires that `b` has the same dimensions
5232        // as an element of `a`.
5233        Ordering::Greater => {
5234            if &a_dims[1..] != &b_dims[..] {
5235                return Err(EvalError::IncompatibleArrayDimensions { dims: None });
5236            }
5237            dims = vec![ArrayDimension {
5238                lower_bound: a_dims[0].lower_bound,
5239                // Since `b` is treated as an element of `a`, the length of
5240                // the first dimension of `a` is incremented by one, as `b`
5241                // is non-empty.
5242                length: a_dims[0].length + 1,
5243            }];
5244            dims.extend(b_dims);
5245        }
5246    }
5247
5248    let elems = a_array.elements().iter().chain(b_array.elements().iter());
5249
5250    Ok(temp_storage.try_make_datum(|packer| packer.try_push_array(&dims, elems))?)
5251}
5252
5253#[sqlfunc(
5254    output_type_expr = "input_type_a.scalar_type.without_modifiers().nullable(true)",
5255    is_infix_op = true,
5256    sqlname = "||",
5257    propagates_nulls = false,
5258    introduces_nulls = false
5259)]
5260fn list_list_concat<'a>(a: Datum<'a>, b: Datum<'a>, temp_storage: &'a RowArena) -> Datum<'a> {
5261    if a.is_null() {
5262        return b;
5263    } else if b.is_null() {
5264        return a;
5265    }
5266
5267    let a = a.unwrap_list().iter();
5268    let b = b.unwrap_list().iter();
5269
5270    temp_storage.make_datum(|packer| packer.push_list(a.chain(b)))
5271}
5272
5273#[sqlfunc(
5274    output_type_expr = "input_type_a.scalar_type.without_modifiers().nullable(true)",
5275    is_infix_op = true,
5276    sqlname = "||",
5277    propagates_nulls = false,
5278    introduces_nulls = false
5279)]
5280fn list_element_concat<'a>(a: Datum<'a>, b: Datum<'a>, temp_storage: &'a RowArena) -> Datum<'a> {
5281    temp_storage.make_datum(|packer| {
5282        packer.push_list_with(|packer| {
5283            if !a.is_null() {
5284                for elem in a.unwrap_list().iter() {
5285                    packer.push(elem);
5286                }
5287            }
5288            packer.push(b);
5289        })
5290    })
5291}
5292
5293#[sqlfunc(
5294    output_type_expr = "input_type_b.scalar_type.without_modifiers().nullable(true)",
5295    is_infix_op = true,
5296    sqlname = "||",
5297    propagates_nulls = false,
5298    introduces_nulls = false
5299)]
5300fn element_list_concat<'a>(a: Datum<'a>, b: Datum<'a>, temp_storage: &'a RowArena) -> Datum<'a> {
5301    temp_storage.make_datum(|packer| {
5302        packer.push_list_with(|packer| {
5303            packer.push(a);
5304            if !b.is_null() {
5305                for elem in b.unwrap_list().iter() {
5306                    packer.push(elem);
5307                }
5308            }
5309        })
5310    })
5311}
5312
5313#[sqlfunc(
5314    output_type_expr = "input_type_a.scalar_type.without_modifiers().nullable(true)",
5315    sqlname = "list_remove",
5316    propagates_nulls = false,
5317    introduces_nulls = false
5318)]
5319fn list_remove<'a>(a: DatumList<'a>, b: Datum<'a>, temp_storage: &'a RowArena) -> Datum<'a> {
5320    temp_storage.make_datum(|packer| {
5321        packer.push_list_with(|packer| {
5322            for elem in a.iter() {
5323                if elem != b {
5324                    packer.push(elem);
5325                }
5326            }
5327        })
5328    })
5329}
5330
5331#[sqlfunc(
5332    output_type = "Vec<u8>",
5333    sqlname = "digest",
5334    propagates_nulls = true,
5335    introduces_nulls = false
5336)]
5337fn digest_string<'a>(a: &str, b: &str, temp_storage: &'a RowArena) -> Result<Datum<'a>, EvalError> {
5338    let to_digest = a.as_bytes();
5339    digest_inner(to_digest, b, temp_storage)
5340}
5341
5342#[sqlfunc(
5343    output_type = "Vec<u8>",
5344    sqlname = "digest",
5345    propagates_nulls = true,
5346    introduces_nulls = false
5347)]
5348fn digest_bytes<'a>(a: &[u8], b: &str, temp_storage: &'a RowArena) -> Result<Datum<'a>, EvalError> {
5349    let to_digest = a;
5350    digest_inner(to_digest, b, temp_storage)
5351}
5352
5353fn digest_inner<'a>(
5354    bytes: &[u8],
5355    digest_fn: &str,
5356    temp_storage: &'a RowArena,
5357) -> Result<Datum<'a>, EvalError> {
5358    let bytes = match digest_fn {
5359        "md5" => Md5::digest(bytes).to_vec(),
5360        "sha1" => Sha1::digest(bytes).to_vec(),
5361        "sha224" => Sha224::digest(bytes).to_vec(),
5362        "sha256" => Sha256::digest(bytes).to_vec(),
5363        "sha384" => Sha384::digest(bytes).to_vec(),
5364        "sha512" => Sha512::digest(bytes).to_vec(),
5365        other => return Err(EvalError::InvalidHashAlgorithm(other.into())),
5366    };
5367    Ok(Datum::Bytes(temp_storage.push_bytes(bytes)))
5368}
5369
5370#[sqlfunc(
5371    output_type = "String",
5372    sqlname = "mz_render_typmod",
5373    propagates_nulls = true,
5374    introduces_nulls = false
5375)]
5376fn mz_render_typmod<'a>(
5377    oid: u32,
5378    typmod: i32,
5379    temp_storage: &'a RowArena,
5380) -> Result<Datum<'a>, EvalError> {
5381    let s = match Type::from_oid_and_typmod(oid, typmod) {
5382        Ok(typ) => typ.constraint().display_or("").to_string(),
5383        // Match dubious PostgreSQL behavior of outputting the unmodified
5384        // `typmod` when positive if the type OID/typmod is invalid.
5385        Err(_) if typmod >= 0 => format!("({typmod})"),
5386        Err(_) => "".into(),
5387    };
5388    Ok(Datum::String(temp_storage.push_string(s)))
5389}
5390
5391#[cfg(test)]
5392mod test {
5393    use chrono::prelude::*;
5394    use mz_repr::PropDatum;
5395    use proptest::prelude::*;
5396
5397    use super::*;
5398
5399    #[mz_ore::test]
5400    fn add_interval_months() {
5401        let dt = ym(2000, 1);
5402
5403        assert_eq!(add_timestamp_months(&*dt, 0).unwrap(), dt);
5404        assert_eq!(add_timestamp_months(&*dt, 1).unwrap(), ym(2000, 2));
5405        assert_eq!(add_timestamp_months(&*dt, 12).unwrap(), ym(2001, 1));
5406        assert_eq!(add_timestamp_months(&*dt, 13).unwrap(), ym(2001, 2));
5407        assert_eq!(add_timestamp_months(&*dt, 24).unwrap(), ym(2002, 1));
5408        assert_eq!(add_timestamp_months(&*dt, 30).unwrap(), ym(2002, 7));
5409
5410        // and negatives
5411        assert_eq!(add_timestamp_months(&*dt, -1).unwrap(), ym(1999, 12));
5412        assert_eq!(add_timestamp_months(&*dt, -12).unwrap(), ym(1999, 1));
5413        assert_eq!(add_timestamp_months(&*dt, -13).unwrap(), ym(1998, 12));
5414        assert_eq!(add_timestamp_months(&*dt, -24).unwrap(), ym(1998, 1));
5415        assert_eq!(add_timestamp_months(&*dt, -30).unwrap(), ym(1997, 7));
5416
5417        // and going over a year boundary by less than a year
5418        let dt = ym(1999, 12);
5419        assert_eq!(add_timestamp_months(&*dt, 1).unwrap(), ym(2000, 1));
5420        let end_of_month_dt = NaiveDate::from_ymd_opt(1999, 12, 31)
5421            .unwrap()
5422            .and_hms_opt(9, 9, 9)
5423            .unwrap();
5424        assert_eq!(
5425            // leap year
5426            add_timestamp_months(&end_of_month_dt, 2).unwrap(),
5427            NaiveDate::from_ymd_opt(2000, 2, 29)
5428                .unwrap()
5429                .and_hms_opt(9, 9, 9)
5430                .unwrap()
5431                .try_into()
5432                .unwrap(),
5433        );
5434        assert_eq!(
5435            // not leap year
5436            add_timestamp_months(&end_of_month_dt, 14).unwrap(),
5437            NaiveDate::from_ymd_opt(2001, 2, 28)
5438                .unwrap()
5439                .and_hms_opt(9, 9, 9)
5440                .unwrap()
5441                .try_into()
5442                .unwrap(),
5443        );
5444    }
5445
5446    fn ym(year: i32, month: u32) -> CheckedTimestamp<NaiveDateTime> {
5447        NaiveDate::from_ymd_opt(year, month, 1)
5448            .unwrap()
5449            .and_hms_opt(9, 9, 9)
5450            .unwrap()
5451            .try_into()
5452            .unwrap()
5453    }
5454
5455    #[mz_ore::test]
5456    #[cfg_attr(miri, ignore)] // unsupported operation: can't call foreign function `decNumberFromInt32` on OS `linux`
5457    fn test_is_monotone() {
5458        use proptest::prelude::*;
5459
5460        /// Asserts that the function is either monotonically increasing or decreasing over
5461        /// the given sets of arguments.
5462        fn assert_monotone<'a, const N: usize>(
5463            expr: &MirScalarExpr,
5464            arena: &'a RowArena,
5465            datums: &[[Datum<'a>; N]],
5466        ) {
5467            // TODO: assertions for nulls, errors
5468            let Ok(results) = datums
5469                .iter()
5470                .map(|args| expr.eval(args.as_slice(), arena))
5471                .collect::<Result<Vec<_>, _>>()
5472            else {
5473                return;
5474            };
5475
5476            let forward = results.iter().tuple_windows().all(|(a, b)| a <= b);
5477            let reverse = results.iter().tuple_windows().all(|(a, b)| a >= b);
5478            assert!(
5479                forward || reverse,
5480                "expected {expr} to be monotone, but passing {datums:?} returned {results:?}"
5481            );
5482        }
5483
5484        fn proptest_binary<'a>(
5485            func: BinaryFunc,
5486            arena: &'a RowArena,
5487            left: impl Strategy<Value = PropDatum>,
5488            right: impl Strategy<Value = PropDatum>,
5489        ) {
5490            let (left_monotone, right_monotone) = func.is_monotone();
5491            let expr = MirScalarExpr::CallBinary {
5492                func,
5493                expr1: Box::new(MirScalarExpr::column(0)),
5494                expr2: Box::new(MirScalarExpr::column(1)),
5495            };
5496            proptest!(|(
5497                mut left in proptest::array::uniform3(left),
5498                mut right in proptest::array::uniform3(right),
5499            )| {
5500                left.sort();
5501                right.sort();
5502                if left_monotone {
5503                    for r in &right {
5504                        let args: Vec<[_; 2]> = left
5505                            .iter()
5506                            .map(|l| [Datum::from(l), Datum::from(r)])
5507                            .collect();
5508                        assert_monotone(&expr, arena, &args);
5509                    }
5510                }
5511                if right_monotone {
5512                    for l in &left {
5513                        let args: Vec<[_; 2]> = right
5514                            .iter()
5515                            .map(|r| [Datum::from(l), Datum::from(r)])
5516                            .collect();
5517                        assert_monotone(&expr, arena, &args);
5518                    }
5519                }
5520            });
5521        }
5522
5523        let interesting_strs: Vec<_> = SqlScalarType::String.interesting_datums().collect();
5524        let str_datums = proptest::strategy::Union::new([
5525            proptest::string::string_regex("[A-Z]{0,10}")
5526                .expect("valid regex")
5527                .prop_map(|s| PropDatum::String(s.to_string()))
5528                .boxed(),
5529            (0..interesting_strs.len())
5530                .prop_map(move |i| {
5531                    let Datum::String(val) = interesting_strs[i] else {
5532                        unreachable!("interesting strings has non-strings")
5533                    };
5534                    PropDatum::String(val.to_string())
5535                })
5536                .boxed(),
5537        ]);
5538
5539        let interesting_i32s: Vec<Datum<'static>> =
5540            SqlScalarType::Int32.interesting_datums().collect();
5541        let i32_datums = proptest::strategy::Union::new([
5542            any::<i32>().prop_map(PropDatum::Int32).boxed(),
5543            (0..interesting_i32s.len())
5544                .prop_map(move |i| {
5545                    let Datum::Int32(val) = interesting_i32s[i] else {
5546                        unreachable!("interesting int32 has non-i32s")
5547                    };
5548                    PropDatum::Int32(val)
5549                })
5550                .boxed(),
5551            (-10i32..10).prop_map(PropDatum::Int32).boxed(),
5552        ]);
5553
5554        let arena = RowArena::new();
5555
5556        // It would be interesting to test all funcs here, but we currently need to hardcode
5557        // the generators for the argument types, which makes this tedious. Choose an interesting
5558        // subset for now.
5559        proptest_binary(
5560            BinaryFunc::AddInt32(AddInt32),
5561            &arena,
5562            &i32_datums,
5563            &i32_datums,
5564        );
5565        proptest_binary(SubInt32.into(), &arena, &i32_datums, &i32_datums);
5566        proptest_binary(MulInt32.into(), &arena, &i32_datums, &i32_datums);
5567        proptest_binary(DivInt32.into(), &arena, &i32_datums, &i32_datums);
5568        proptest_binary(TextConcatBinary.into(), &arena, &str_datums, &str_datums);
5569        proptest_binary(Left.into(), &arena, &str_datums, &i32_datums);
5570    }
5571}