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