mz_expr/scalar/
func.rs

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