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