mz_expr/scalar/
func.rs

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