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::{self, Ordering};
16use std::convert::{TryFrom, TryInto};
17use std::ops::Deref;
18use std::str::FromStr;
19use std::{fmt, iter, str};
20
21use ::encoding::DecoderTrap;
22use ::encoding::label::encoding_from_whatwg_label;
23use chrono::{DateTime, Duration, NaiveDate, NaiveDateTime, TimeZone, Timelike, Utc};
24use chrono_tz::{OffsetComponents, OffsetName, Tz};
25use dec::OrderedDecimal;
26use fallible_iterator::FallibleIterator;
27use hmac::{Hmac, Mac};
28use itertools::Itertools;
29use md5::{Digest, Md5};
30use mz_expr_derive::sqlfunc;
31use mz_lowertest::MzReflect;
32use mz_ore::cast::{self, CastFrom, ReinterpretCast};
33use mz_ore::fmt::FormatBuffer;
34use mz_ore::lex::LexBuf;
35use mz_ore::option::OptionExt;
36use mz_ore::result::ResultExt;
37use mz_ore::soft_assert_eq_or_log;
38use mz_ore::str::StrExt;
39use mz_pgrepr::Type;
40use mz_pgtz::timezone::{Timezone, TimezoneSpec};
41use mz_proto::chrono::any_naive_datetime;
42use mz_proto::{IntoRustIfSome, ProtoType, RustType, TryFromProtoError};
43use mz_repr::adt::array::ArrayDimension;
44use mz_repr::adt::date::Date;
45use mz_repr::adt::interval::{Interval, RoundBehavior};
46use mz_repr::adt::jsonb::JsonbRef;
47use mz_repr::adt::mz_acl_item::{AclItem, AclMode, MzAclItem};
48use mz_repr::adt::numeric::{self, DecimalLike, Numeric, NumericMaxScale};
49use mz_repr::adt::range::{self, Range, RangeBound, RangeOps};
50use mz_repr::adt::regex::{Regex, any_regex};
51use mz_repr::adt::system::Oid;
52use mz_repr::adt::timestamp::{CheckedTimestamp, TimestampLike};
53use mz_repr::role_id::RoleId;
54use mz_repr::{ColumnName, ColumnType, Datum, DatumType, Row, RowArena, ScalarType, strconv};
55use mz_sql_parser::ast::display::FormatMode;
56use mz_sql_pretty::{PrettyConfig, pretty_str};
57use num::traits::CheckedNeg;
58use proptest::prelude::*;
59use proptest::strategy::*;
60use proptest_derive::Arbitrary;
61use serde::{Deserialize, Serialize};
62use sha1::Sha1;
63use sha2::{Sha224, Sha256, Sha384, Sha512};
64use subtle::ConstantTimeEq;
65
66use crate::scalar::func::format::DateTimeFormat;
67use crate::scalar::{
68    ProtoBinaryFunc, ProtoUnaryFunc, ProtoUnmaterializableFunc, ProtoVariadicFunc,
69};
70use crate::{EvalError, MirScalarExpr, like_pattern};
71
72#[macro_use]
73mod macros;
74mod binary;
75mod encoding;
76pub(crate) mod format;
77pub(crate) mod impls;
78
79pub use impls::*;
80
81/// The maximum size of a newly allocated string. Chosen to be the smallest number to keep our tests
82/// passing without changing. 100MiB is probably higher than what we want, but it's better than no
83/// limit.
84const MAX_STRING_BYTES: usize = 1024 * 1024 * 100;
85
86#[derive(
87    Arbitrary, Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect,
88)]
89pub enum UnmaterializableFunc {
90    CurrentDatabase,
91    CurrentSchema,
92    CurrentSchemasWithSystem,
93    CurrentSchemasWithoutSystem,
94    CurrentTimestamp,
95    CurrentUser,
96    IsRbacEnabled,
97    MzEnvironmentId,
98    MzIsSuperuser,
99    MzNow,
100    MzRoleOidMemberships,
101    MzSessionId,
102    MzUptime,
103    MzVersion,
104    MzVersionNum,
105    PgBackendPid,
106    PgPostmasterStartTime,
107    SessionUser,
108    Version,
109    ViewableVariables,
110}
111
112impl UnmaterializableFunc {
113    pub fn output_type(&self) -> ColumnType {
114        match self {
115            UnmaterializableFunc::CurrentDatabase => ScalarType::String.nullable(false),
116            // TODO: The `CurrentSchema` function should return `name`. This is
117            // tricky in Materialize because `name` truncates to 63 characters
118            // but Materialize does not have a limit on identifier length.
119            UnmaterializableFunc::CurrentSchema => ScalarType::String.nullable(true),
120            // TODO: The `CurrentSchemas` function should return `name[]`. This
121            // is tricky in Materialize because `name` truncates to 63
122            // characters but Materialize does not have a limit on identifier
123            // length.
124            UnmaterializableFunc::CurrentSchemasWithSystem => {
125                ScalarType::Array(Box::new(ScalarType::String)).nullable(false)
126            }
127            UnmaterializableFunc::CurrentSchemasWithoutSystem => {
128                ScalarType::Array(Box::new(ScalarType::String)).nullable(false)
129            }
130            UnmaterializableFunc::CurrentTimestamp => {
131                ScalarType::TimestampTz { precision: None }.nullable(false)
132            }
133            UnmaterializableFunc::CurrentUser => ScalarType::String.nullable(false),
134            UnmaterializableFunc::IsRbacEnabled => ScalarType::Bool.nullable(false),
135            UnmaterializableFunc::MzEnvironmentId => ScalarType::String.nullable(false),
136            UnmaterializableFunc::MzIsSuperuser => ScalarType::Bool.nullable(false),
137            UnmaterializableFunc::MzNow => ScalarType::MzTimestamp.nullable(false),
138            UnmaterializableFunc::MzRoleOidMemberships => ScalarType::Map {
139                value_type: Box::new(ScalarType::Array(Box::new(ScalarType::String))),
140                custom_id: None,
141            }
142            .nullable(false),
143            UnmaterializableFunc::MzSessionId => ScalarType::Uuid.nullable(false),
144            UnmaterializableFunc::MzUptime => ScalarType::Interval.nullable(true),
145            UnmaterializableFunc::MzVersion => ScalarType::String.nullable(false),
146            UnmaterializableFunc::MzVersionNum => ScalarType::Int32.nullable(false),
147            UnmaterializableFunc::PgBackendPid => ScalarType::Int32.nullable(false),
148            UnmaterializableFunc::PgPostmasterStartTime => {
149                ScalarType::TimestampTz { precision: None }.nullable(false)
150            }
151            UnmaterializableFunc::SessionUser => ScalarType::String.nullable(false),
152            UnmaterializableFunc::Version => ScalarType::String.nullable(false),
153            UnmaterializableFunc::ViewableVariables => ScalarType::Map {
154                value_type: Box::new(ScalarType::String),
155                custom_id: None,
156            }
157            .nullable(false),
158        }
159    }
160}
161
162impl fmt::Display for UnmaterializableFunc {
163    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164        match self {
165            UnmaterializableFunc::CurrentDatabase => f.write_str("current_database"),
166            UnmaterializableFunc::CurrentSchema => f.write_str("current_schema"),
167            UnmaterializableFunc::CurrentSchemasWithSystem => f.write_str("current_schemas(true)"),
168            UnmaterializableFunc::CurrentSchemasWithoutSystem => {
169                f.write_str("current_schemas(false)")
170            }
171            UnmaterializableFunc::CurrentTimestamp => f.write_str("current_timestamp"),
172            UnmaterializableFunc::CurrentUser => f.write_str("current_user"),
173            UnmaterializableFunc::IsRbacEnabled => f.write_str("is_rbac_enabled"),
174            UnmaterializableFunc::MzEnvironmentId => f.write_str("mz_environment_id"),
175            UnmaterializableFunc::MzIsSuperuser => f.write_str("mz_is_superuser"),
176            UnmaterializableFunc::MzNow => f.write_str("mz_now"),
177            UnmaterializableFunc::MzRoleOidMemberships => f.write_str("mz_role_oid_memberships"),
178            UnmaterializableFunc::MzSessionId => f.write_str("mz_session_id"),
179            UnmaterializableFunc::MzUptime => f.write_str("mz_uptime"),
180            UnmaterializableFunc::MzVersion => f.write_str("mz_version"),
181            UnmaterializableFunc::MzVersionNum => f.write_str("mz_version_num"),
182            UnmaterializableFunc::PgBackendPid => f.write_str("pg_backend_pid"),
183            UnmaterializableFunc::PgPostmasterStartTime => f.write_str("pg_postmaster_start_time"),
184            UnmaterializableFunc::SessionUser => f.write_str("session_user"),
185            UnmaterializableFunc::Version => f.write_str("version"),
186            UnmaterializableFunc::ViewableVariables => f.write_str("viewable_variables"),
187        }
188    }
189}
190
191impl RustType<ProtoUnmaterializableFunc> for UnmaterializableFunc {
192    fn into_proto(&self) -> ProtoUnmaterializableFunc {
193        use crate::scalar::proto_unmaterializable_func::Kind::*;
194        let kind = match self {
195            UnmaterializableFunc::CurrentDatabase => CurrentDatabase(()),
196            UnmaterializableFunc::CurrentSchema => CurrentSchema(()),
197            UnmaterializableFunc::CurrentSchemasWithSystem => CurrentSchemasWithSystem(()),
198            UnmaterializableFunc::CurrentSchemasWithoutSystem => CurrentSchemasWithoutSystem(()),
199            UnmaterializableFunc::ViewableVariables => CurrentSetting(()),
200            UnmaterializableFunc::CurrentTimestamp => CurrentTimestamp(()),
201            UnmaterializableFunc::CurrentUser => CurrentUser(()),
202            UnmaterializableFunc::IsRbacEnabled => IsRbacEnabled(()),
203            UnmaterializableFunc::MzEnvironmentId => MzEnvironmentId(()),
204            UnmaterializableFunc::MzIsSuperuser => MzIsSuperuser(()),
205            UnmaterializableFunc::MzNow => MzNow(()),
206            UnmaterializableFunc::MzRoleOidMemberships => MzRoleOidMemberships(()),
207            UnmaterializableFunc::MzSessionId => MzSessionId(()),
208            UnmaterializableFunc::MzUptime => MzUptime(()),
209            UnmaterializableFunc::MzVersion => MzVersion(()),
210            UnmaterializableFunc::MzVersionNum => MzVersionNum(()),
211            UnmaterializableFunc::PgBackendPid => PgBackendPid(()),
212            UnmaterializableFunc::PgPostmasterStartTime => PgPostmasterStartTime(()),
213            UnmaterializableFunc::SessionUser => SessionUser(()),
214            UnmaterializableFunc::Version => Version(()),
215        };
216        ProtoUnmaterializableFunc { kind: Some(kind) }
217    }
218
219    fn from_proto(proto: ProtoUnmaterializableFunc) -> Result<Self, TryFromProtoError> {
220        use crate::scalar::proto_unmaterializable_func::Kind::*;
221        if let Some(kind) = proto.kind {
222            match kind {
223                CurrentDatabase(()) => Ok(UnmaterializableFunc::CurrentDatabase),
224                CurrentSchema(()) => Ok(UnmaterializableFunc::CurrentSchema),
225                CurrentSchemasWithSystem(()) => Ok(UnmaterializableFunc::CurrentSchemasWithSystem),
226                CurrentSchemasWithoutSystem(()) => {
227                    Ok(UnmaterializableFunc::CurrentSchemasWithoutSystem)
228                }
229                CurrentTimestamp(()) => Ok(UnmaterializableFunc::CurrentTimestamp),
230                CurrentSetting(()) => Ok(UnmaterializableFunc::ViewableVariables),
231                CurrentUser(()) => Ok(UnmaterializableFunc::CurrentUser),
232                IsRbacEnabled(()) => Ok(UnmaterializableFunc::IsRbacEnabled),
233                MzEnvironmentId(()) => Ok(UnmaterializableFunc::MzEnvironmentId),
234                MzIsSuperuser(()) => Ok(UnmaterializableFunc::MzIsSuperuser),
235                MzNow(()) => Ok(UnmaterializableFunc::MzNow),
236                MzRoleOidMemberships(()) => Ok(UnmaterializableFunc::MzRoleOidMemberships),
237                MzSessionId(()) => Ok(UnmaterializableFunc::MzSessionId),
238                MzUptime(()) => Ok(UnmaterializableFunc::MzUptime),
239                MzVersion(()) => Ok(UnmaterializableFunc::MzVersion),
240                MzVersionNum(()) => Ok(UnmaterializableFunc::MzVersionNum),
241                PgBackendPid(()) => Ok(UnmaterializableFunc::PgBackendPid),
242                PgPostmasterStartTime(()) => Ok(UnmaterializableFunc::PgPostmasterStartTime),
243                SessionUser(()) => Ok(UnmaterializableFunc::SessionUser),
244                Version(()) => Ok(UnmaterializableFunc::Version),
245            }
246        } else {
247            Err(TryFromProtoError::missing_field(
248                "`ProtoUnmaterializableFunc::kind`",
249            ))
250        }
251    }
252}
253
254pub fn and<'a>(
255    datums: &[Datum<'a>],
256    temp_storage: &'a RowArena,
257    exprs: &'a [MirScalarExpr],
258) -> Result<Datum<'a>, EvalError> {
259    // If any is false, then return false. Else, if any is null, then return null. Else, return true.
260    let mut null = false;
261    let mut err = None;
262    for expr in exprs {
263        match expr.eval(datums, temp_storage) {
264            Ok(Datum::False) => return Ok(Datum::False), // short-circuit
265            Ok(Datum::True) => {}
266            // No return in these two cases, because we might still see a false
267            Ok(Datum::Null) => null = true,
268            Err(this_err) => err = std::cmp::max(err.take(), Some(this_err)),
269            _ => unreachable!(),
270        }
271    }
272    match (err, null) {
273        (Some(err), _) => Err(err),
274        (None, true) => Ok(Datum::Null),
275        (None, false) => Ok(Datum::True),
276    }
277}
278
279pub fn or<'a>(
280    datums: &[Datum<'a>],
281    temp_storage: &'a RowArena,
282    exprs: &'a [MirScalarExpr],
283) -> Result<Datum<'a>, EvalError> {
284    // If any is true, then return true. Else, if any is null, then return null. Else, return false.
285    let mut null = false;
286    let mut err = None;
287    for expr in exprs {
288        match expr.eval(datums, temp_storage) {
289            Ok(Datum::False) => {}
290            Ok(Datum::True) => return Ok(Datum::True), // short-circuit
291            // No return in these two cases, because we might still see a true
292            Ok(Datum::Null) => null = true,
293            Err(this_err) => err = std::cmp::max(err.take(), Some(this_err)),
294            _ => unreachable!(),
295        }
296    }
297    match (err, null) {
298        (Some(err), _) => Err(err),
299        (None, true) => Ok(Datum::Null),
300        (None, false) => Ok(Datum::False),
301    }
302}
303
304pub fn jsonb_stringify<'a>(a: Datum<'a>, temp_storage: &'a RowArena) -> Datum<'a> {
305    match a {
306        Datum::JsonNull => Datum::Null,
307        Datum::String(_) => a,
308        _ => {
309            let s = cast_jsonb_to_string(JsonbRef::from_datum(a));
310            Datum::String(temp_storage.push_string(s))
311        }
312    }
313}
314
315#[sqlfunc(
316    is_monotone = "(true, true)",
317    output_type = "i16",
318    is_infix_op = true,
319    sqlname = "+",
320    propagates_nulls = true
321)]
322fn add_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
323    a.unwrap_int16()
324        .checked_add(b.unwrap_int16())
325        .ok_or(EvalError::NumericFieldOverflow)
326        .map(Datum::from)
327}
328
329#[sqlfunc(
330    is_monotone = "(true, true)",
331    output_type = "i32",
332    is_infix_op = true,
333    sqlname = "+",
334    propagates_nulls = true
335)]
336fn add_int32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
337    a.unwrap_int32()
338        .checked_add(b.unwrap_int32())
339        .ok_or(EvalError::NumericFieldOverflow)
340        .map(Datum::from)
341}
342
343#[sqlfunc(
344    is_monotone = "(true, true)",
345    output_type = "i64",
346    is_infix_op = true,
347    sqlname = "+",
348    propagates_nulls = true
349)]
350fn add_int64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
351    a.unwrap_int64()
352        .checked_add(b.unwrap_int64())
353        .ok_or(EvalError::NumericFieldOverflow)
354        .map(Datum::from)
355}
356
357#[sqlfunc(
358    is_monotone = "(true, true)",
359    output_type = "u16",
360    is_infix_op = true,
361    sqlname = "+",
362    propagates_nulls = true
363)]
364fn add_uint16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
365    a.unwrap_uint16()
366        .checked_add(b.unwrap_uint16())
367        .ok_or(EvalError::UInt16OutOfRange(format!("{a} + {b}").into()))
368        .map(Datum::from)
369}
370
371#[sqlfunc(
372    is_monotone = "(true, true)",
373    output_type = "u32",
374    is_infix_op = true,
375    sqlname = "+",
376    propagates_nulls = true
377)]
378fn add_uint32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
379    a.unwrap_uint32()
380        .checked_add(b.unwrap_uint32())
381        .ok_or(EvalError::UInt32OutOfRange(format!("{a} + {b}").into()))
382        .map(Datum::from)
383}
384
385#[sqlfunc(
386    is_monotone = "(true, true)",
387    output_type = "u64",
388    is_infix_op = true,
389    sqlname = "+",
390    propagates_nulls = true
391)]
392fn add_uint64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
393    a.unwrap_uint64()
394        .checked_add(b.unwrap_uint64())
395        .ok_or(EvalError::UInt64OutOfRange(format!("{a} + {b}").into()))
396        .map(Datum::from)
397}
398
399#[sqlfunc(
400    is_monotone = "(true, true)",
401    output_type = "f32",
402    is_infix_op = true,
403    sqlname = "+",
404    propagates_nulls = true
405)]
406fn add_float32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
407    let a = a.unwrap_float32();
408    let b = b.unwrap_float32();
409    let sum = a + b;
410    if sum.is_infinite() && !a.is_infinite() && !b.is_infinite() {
411        Err(EvalError::FloatOverflow)
412    } else {
413        Ok(Datum::from(sum))
414    }
415}
416
417#[sqlfunc(
418    is_monotone = "(true, true)",
419    output_type = "f64",
420    is_infix_op = true,
421    sqlname = "+",
422    propagates_nulls = true
423)]
424fn add_float64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
425    let a = a.unwrap_float64();
426    let b = b.unwrap_float64();
427    let sum = a + b;
428    if sum.is_infinite() && !a.is_infinite() && !b.is_infinite() {
429        Err(EvalError::FloatOverflow)
430    } else {
431        Ok(Datum::from(sum))
432    }
433}
434
435fn add_timestamplike_interval<'a, T>(
436    a: CheckedTimestamp<T>,
437    b: Interval,
438) -> Result<Datum<'a>, EvalError>
439where
440    T: TimestampLike,
441{
442    let dt = a.date_time();
443    let dt = add_timestamp_months(&dt, b.months)?;
444    let dt = dt
445        .checked_add_signed(b.duration_as_chrono())
446        .ok_or(EvalError::TimestampOutOfRange)?;
447    T::from_date_time(dt).try_into().err_into()
448}
449
450fn sub_timestamplike_interval<'a, T>(
451    a: CheckedTimestamp<T>,
452    b: Datum,
453) -> Result<Datum<'a>, EvalError>
454where
455    T: TimestampLike,
456{
457    neg_interval_inner(b).and_then(|i| add_timestamplike_interval(a, i))
458}
459
460#[sqlfunc(
461    is_monotone = "(true, true)",
462    output_type = "CheckedTimestamp<NaiveDateTime>",
463    is_infix_op = true,
464    sqlname = "+",
465    propagates_nulls = true
466)]
467fn add_date_time<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
468    let date = a.unwrap_date();
469    let time = b.unwrap_time();
470
471    let dt = NaiveDate::from(date)
472        .and_hms_nano_opt(time.hour(), time.minute(), time.second(), time.nanosecond())
473        .unwrap();
474    Ok(dt.try_into()?)
475}
476
477#[sqlfunc(
478    is_monotone = "(true, true)",
479    output_type = "CheckedTimestamp<NaiveDateTime>",
480    is_infix_op = true,
481    sqlname = "+",
482    propagates_nulls = true
483)]
484fn add_date_interval<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
485    let date = a.unwrap_date();
486    let interval = b.unwrap_interval();
487
488    let dt = NaiveDate::from(date).and_hms_opt(0, 0, 0).unwrap();
489    let dt = add_timestamp_months(&dt, interval.months)?;
490    let dt = dt
491        .checked_add_signed(interval.duration_as_chrono())
492        .ok_or(EvalError::TimestampOutOfRange)?;
493    Ok(dt.try_into()?)
494}
495
496#[sqlfunc(
497    is_monotone = "(true, true)",
498    output_type = "CheckedTimestamp<chrono::DateTime<Utc>>",
499    is_infix_op = true,
500    sqlname = "+",
501    propagates_nulls = true
502)]
503fn add_time_interval<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
504    let time = a.unwrap_time();
505    let interval = b.unwrap_interval();
506    let (t, _) = time.overflowing_add_signed(interval.duration_as_chrono());
507    Datum::Time(t)
508}
509
510#[sqlfunc(
511    is_monotone = "(true, false)",
512    output_type = "Numeric",
513    is_infix_op = false,
514    sqlname = "round",
515    propagates_nulls = true
516)]
517fn round_numeric_binary<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
518    let mut a = a.unwrap_numeric().0;
519    let mut b = b.unwrap_int32();
520    let mut cx = numeric::cx_datum();
521    let a_exp = a.exponent();
522    if a_exp > 0 && b > 0 || a_exp < 0 && -a_exp < b {
523        // This condition indicates:
524        // - a is a value without a decimal point, b is a positive number
525        // - a has a decimal point, but b is larger than its scale
526        // In both of these situations, right-pad the number with zeroes, which // is most easily done with rescale.
527
528        // Ensure rescale doesn't exceed max precision by putting a ceiling on
529        // b equal to the maximum remaining scale the value can support.
530        let max_remaining_scale = u32::from(numeric::NUMERIC_DATUM_MAX_PRECISION)
531            - (numeric::get_precision(&a) - numeric::get_scale(&a));
532        b = match i32::try_from(max_remaining_scale) {
533            Ok(max_remaining_scale) => std::cmp::min(b, max_remaining_scale),
534            Err(_) => b,
535        };
536        cx.rescale(&mut a, &numeric::Numeric::from(-b));
537    } else {
538        // To avoid invalid operations, clamp b to be within 1 more than the
539        // precision limit.
540        const MAX_P_LIMIT: i32 = 1 + cast::u8_to_i32(numeric::NUMERIC_DATUM_MAX_PRECISION);
541        b = std::cmp::min(MAX_P_LIMIT, b);
542        b = std::cmp::max(-MAX_P_LIMIT, b);
543        let mut b = numeric::Numeric::from(b);
544        // Shift by 10^b; this put digit to round to in the one's place.
545        cx.scaleb(&mut a, &b);
546        cx.round(&mut a);
547        // Negate exponent for shift back
548        cx.neg(&mut b);
549        cx.scaleb(&mut a, &b);
550    }
551
552    if cx.status().overflow() {
553        Err(EvalError::FloatOverflow)
554    } else if a.is_zero() {
555        // simpler than handling cases where exponent has gotten set to some
556        // value greater than the max precision, but all significant digits
557        // were rounded away.
558        Ok(Datum::from(numeric::Numeric::zero()))
559    } else {
560        numeric::munge_numeric(&mut a).unwrap();
561        Ok(Datum::from(a))
562    }
563}
564
565#[sqlfunc(
566    is_monotone = "(false, false)",
567    output_type = "String",
568    is_infix_op = false,
569    sqlname = "convert_from",
570    propagates_nulls = true
571)]
572fn convert_from<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
573    // Convert PostgreSQL-style encoding names[1] to WHATWG-style encoding names[2],
574    // which the encoding library uses[3].
575    // [1]: https://www.postgresql.org/docs/9.5/multibyte.html
576    // [2]: https://encoding.spec.whatwg.org/
577    // [3]: https://github.com/lifthrasiir/rust-encoding/blob/4e79c35ab6a351881a86dbff565c4db0085cc113/src/label.rs
578    let encoding_name = b
579        .unwrap_str()
580        .to_lowercase()
581        .replace('_', "-")
582        .into_boxed_str();
583
584    // Supporting other encodings is tracked by database-issues#797.
585    if encoding_from_whatwg_label(&encoding_name).map(|e| e.name()) != Some("utf-8") {
586        return Err(EvalError::InvalidEncodingName(encoding_name));
587    }
588
589    match str::from_utf8(a.unwrap_bytes()) {
590        Ok(from) => Ok(Datum::String(from)),
591        Err(e) => Err(EvalError::InvalidByteSequence {
592            byte_sequence: e.to_string().into(),
593            encoding_name,
594        }),
595    }
596}
597
598#[sqlfunc(
599    is_monotone = "(false, false)",
600    output_type = "String",
601    is_infix_op = false,
602    sqlname = "encode",
603    propagates_nulls = true
604)]
605fn encode<'a>(
606    bytes: Datum<'a>,
607    format: Datum<'a>,
608    temp_storage: &'a RowArena,
609) -> Result<Datum<'a>, EvalError> {
610    let format = encoding::lookup_format(format.unwrap_str())?;
611    let out = format.encode(bytes.unwrap_bytes());
612    Ok(Datum::from(temp_storage.push_string(out)))
613}
614
615fn decode<'a>(
616    string: Datum<'a>,
617    format: Datum<'a>,
618    temp_storage: &'a RowArena,
619) -> Result<Datum<'a>, EvalError> {
620    let format = encoding::lookup_format(format.unwrap_str())?;
621    let out = format.decode(string.unwrap_str())?;
622    Ok(Datum::from(temp_storage.push_bytes(out)))
623}
624
625#[sqlfunc(
626    is_monotone = "(false, false)",
627    output_type = "i32",
628    is_infix_op = false,
629    sqlname = "length",
630    propagates_nulls = true
631)]
632fn encoded_bytes_char_length<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
633    // Convert PostgreSQL-style encoding names[1] to WHATWG-style encoding names[2],
634    // which the encoding library uses[3].
635    // [1]: https://www.postgresql.org/docs/9.5/multibyte.html
636    // [2]: https://encoding.spec.whatwg.org/
637    // [3]: https://github.com/lifthrasiir/rust-encoding/blob/4e79c35ab6a351881a86dbff565c4db0085cc113/src/label.rs
638    let encoding_name = b
639        .unwrap_str()
640        .to_lowercase()
641        .replace('_', "-")
642        .into_boxed_str();
643
644    let enc = match encoding_from_whatwg_label(&encoding_name) {
645        Some(enc) => enc,
646        None => return Err(EvalError::InvalidEncodingName(encoding_name)),
647    };
648
649    let decoded_string = match enc.decode(a.unwrap_bytes(), DecoderTrap::Strict) {
650        Ok(s) => s,
651        Err(e) => {
652            return Err(EvalError::InvalidByteSequence {
653                byte_sequence: e.into(),
654                encoding_name,
655            });
656        }
657    };
658
659    let count = decoded_string.chars().count();
660    match i32::try_from(count) {
661        Ok(l) => Ok(Datum::from(l)),
662        Err(_) => Err(EvalError::Int32OutOfRange(count.to_string().into())),
663    }
664}
665
666// TODO(benesch): remove potentially dangerous usage of `as`.
667#[allow(clippy::as_conversions)]
668pub fn add_timestamp_months<T: TimestampLike>(
669    dt: &T,
670    mut months: i32,
671) -> Result<CheckedTimestamp<T>, EvalError> {
672    if months == 0 {
673        return Ok(CheckedTimestamp::from_timestamplike(dt.clone())?);
674    }
675
676    let (mut year, mut month, mut day) = (dt.year(), dt.month0() as i32, dt.day());
677    let years = months / 12;
678    year = year
679        .checked_add(years)
680        .ok_or(EvalError::TimestampOutOfRange)?;
681
682    months %= 12;
683    // positive modulus is easier to reason about
684    if months < 0 {
685        year -= 1;
686        months += 12;
687    }
688    year += (month + months) / 12;
689    month = (month + months) % 12;
690    // account for dt.month0
691    month += 1;
692
693    // handle going from January 31st to February by saturation
694    let mut new_d = chrono::NaiveDate::from_ymd_opt(year, month as u32, day);
695    while new_d.is_none() {
696        // If we have decremented day past 28 and are still receiving `None`,
697        // then we have generally overflowed `NaiveDate`.
698        if day < 28 {
699            return Err(EvalError::TimestampOutOfRange);
700        }
701        day -= 1;
702        new_d = chrono::NaiveDate::from_ymd_opt(year, month as u32, day);
703    }
704    let new_d = new_d.unwrap();
705
706    // Neither postgres nor mysql support leap seconds, so this should be safe.
707    //
708    // Both my testing and https://dba.stackexchange.com/a/105829 support the
709    // idea that we should ignore leap seconds
710    let new_dt = new_d
711        .and_hms_nano_opt(dt.hour(), dt.minute(), dt.second(), dt.nanosecond())
712        .unwrap();
713    let new_dt = T::from_date_time(new_dt);
714    Ok(CheckedTimestamp::from_timestamplike(new_dt)?)
715}
716
717#[sqlfunc(
718    is_monotone = "(true, true)",
719    output_type = "Numeric",
720    is_infix_op = true,
721    sqlname = "+",
722    propagates_nulls = true
723)]
724fn add_numeric<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
725    let mut cx = numeric::cx_datum();
726    let mut a = a.unwrap_numeric().0;
727    cx.add(&mut a, &b.unwrap_numeric().0);
728    if cx.status().overflow() {
729        Err(EvalError::FloatOverflow)
730    } else {
731        Ok(Datum::from(a))
732    }
733}
734
735#[sqlfunc(
736    is_monotone = "(true, true)",
737    output_type = "Interval",
738    is_infix_op = true,
739    sqlname = "+",
740    propagates_nulls = true
741)]
742fn add_interval<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
743    a.unwrap_interval()
744        .checked_add(&b.unwrap_interval())
745        .ok_or(EvalError::IntervalOutOfRange(format!("{a} + {b}").into()))
746        .map(Datum::from)
747}
748
749#[sqlfunc(
750    is_monotone = "(false, false)",
751    output_type = "i16",
752    is_infix_op = true,
753    sqlname = "&",
754    propagates_nulls = true
755)]
756fn bit_and_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
757    Datum::from(a.unwrap_int16() & b.unwrap_int16())
758}
759
760#[sqlfunc(
761    is_monotone = "(false, false)",
762    output_type = "i32",
763    is_infix_op = true,
764    sqlname = "&",
765    propagates_nulls = true
766)]
767fn bit_and_int32<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
768    Datum::from(a.unwrap_int32() & b.unwrap_int32())
769}
770
771#[sqlfunc(
772    is_monotone = "(false, false)",
773    output_type = "i64",
774    is_infix_op = true,
775    sqlname = "&",
776    propagates_nulls = true
777)]
778fn bit_and_int64<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
779    Datum::from(a.unwrap_int64() & b.unwrap_int64())
780}
781
782#[sqlfunc(
783    is_monotone = "(false, false)",
784    output_type = "u16",
785    is_infix_op = true,
786    sqlname = "&",
787    propagates_nulls = true
788)]
789fn bit_and_uint16<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
790    Datum::from(a.unwrap_uint16() & b.unwrap_uint16())
791}
792
793#[sqlfunc(
794    is_monotone = "(false, false)",
795    output_type = "u32",
796    is_infix_op = true,
797    sqlname = "&",
798    propagates_nulls = true
799)]
800fn bit_and_uint32<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
801    Datum::from(a.unwrap_uint32() & b.unwrap_uint32())
802}
803
804#[sqlfunc(
805    is_monotone = "(false, false)",
806    output_type = "u64",
807    is_infix_op = true,
808    sqlname = "&",
809    propagates_nulls = true
810)]
811fn bit_and_uint64<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
812    Datum::from(a.unwrap_uint64() & b.unwrap_uint64())
813}
814
815#[sqlfunc(
816    is_monotone = "(false, false)",
817    output_type = "i16",
818    is_infix_op = true,
819    sqlname = "|",
820    propagates_nulls = true
821)]
822fn bit_or_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
823    Datum::from(a.unwrap_int16() | b.unwrap_int16())
824}
825
826#[sqlfunc(
827    is_monotone = "(false, false)",
828    output_type = "i32",
829    is_infix_op = true,
830    sqlname = "|",
831    propagates_nulls = true
832)]
833fn bit_or_int32<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
834    Datum::from(a.unwrap_int32() | b.unwrap_int32())
835}
836
837#[sqlfunc(
838    is_monotone = "(false, false)",
839    output_type = "i64",
840    is_infix_op = true,
841    sqlname = "|",
842    propagates_nulls = true
843)]
844fn bit_or_int64<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
845    Datum::from(a.unwrap_int64() | b.unwrap_int64())
846}
847
848#[sqlfunc(
849    is_monotone = "(false, false)",
850    output_type = "u16",
851    is_infix_op = true,
852    sqlname = "|",
853    propagates_nulls = true
854)]
855fn bit_or_uint16<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
856    Datum::from(a.unwrap_uint16() | b.unwrap_uint16())
857}
858
859#[sqlfunc(
860    is_monotone = "(false, false)",
861    output_type = "u32",
862    is_infix_op = true,
863    sqlname = "|",
864    propagates_nulls = true
865)]
866fn bit_or_uint32<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
867    Datum::from(a.unwrap_uint32() | b.unwrap_uint32())
868}
869
870#[sqlfunc(
871    is_monotone = "(false, false)",
872    output_type = "u64",
873    is_infix_op = true,
874    sqlname = "|",
875    propagates_nulls = true
876)]
877fn bit_or_uint64<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
878    Datum::from(a.unwrap_uint64() | b.unwrap_uint64())
879}
880
881#[sqlfunc(
882    is_monotone = "(false, false)",
883    output_type = "i16",
884    is_infix_op = true,
885    sqlname = "#",
886    propagates_nulls = true
887)]
888fn bit_xor_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
889    Datum::from(a.unwrap_int16() ^ b.unwrap_int16())
890}
891
892#[sqlfunc(
893    is_monotone = "(false, false)",
894    output_type = "i32",
895    is_infix_op = true,
896    sqlname = "#",
897    propagates_nulls = true
898)]
899fn bit_xor_int32<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
900    Datum::from(a.unwrap_int32() ^ b.unwrap_int32())
901}
902
903#[sqlfunc(
904    is_monotone = "(false, false)",
905    output_type = "i64",
906    is_infix_op = true,
907    sqlname = "#",
908    propagates_nulls = true
909)]
910fn bit_xor_int64<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
911    Datum::from(a.unwrap_int64() ^ b.unwrap_int64())
912}
913
914#[sqlfunc(
915    is_monotone = "(false, false)",
916    output_type = "u16",
917    is_infix_op = true,
918    sqlname = "#",
919    propagates_nulls = true
920)]
921fn bit_xor_uint16<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
922    Datum::from(a.unwrap_uint16() ^ b.unwrap_uint16())
923}
924
925#[sqlfunc(
926    is_monotone = "(false, false)",
927    output_type = "u32",
928    is_infix_op = true,
929    sqlname = "#",
930    propagates_nulls = true
931)]
932fn bit_xor_uint32<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
933    Datum::from(a.unwrap_uint32() ^ b.unwrap_uint32())
934}
935
936#[sqlfunc(
937    is_monotone = "(false, false)",
938    output_type = "u64",
939    is_infix_op = true,
940    sqlname = "#",
941    propagates_nulls = true
942)]
943fn bit_xor_uint64<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
944    Datum::from(a.unwrap_uint64() ^ b.unwrap_uint64())
945}
946
947#[sqlfunc(
948    is_monotone = "(false, false)",
949    output_type = "i16",
950    is_infix_op = true,
951    sqlname = "<<",
952    propagates_nulls = true
953)]
954// TODO(benesch): remove potentially dangerous usage of `as`.
955#[allow(clippy::as_conversions)]
956fn bit_shift_left_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
957    // widen to i32 and then cast back to i16 in order emulate the C promotion rules used in by Postgres
958    // when the rhs in the 16-31 range, e.g. (1 << 17 should evaluate to 0)
959    // see https://github.com/postgres/postgres/blob/REL_14_STABLE/src/backend/utils/adt/int.c#L1460-L1476
960    let lhs: i32 = a.unwrap_int16() as i32;
961    let rhs: u32 = b.unwrap_int32() as u32;
962    Datum::from(lhs.wrapping_shl(rhs) as i16)
963}
964
965#[sqlfunc(
966    is_monotone = "(false, false)",
967    output_type = "i32",
968    is_infix_op = true,
969    sqlname = "<<",
970    propagates_nulls = true
971)]
972// TODO(benesch): remove potentially dangerous usage of `as`.
973#[allow(clippy::as_conversions)]
974fn bit_shift_left_int32<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
975    let lhs = a.unwrap_int32();
976    let rhs = b.unwrap_int32() as u32;
977    Datum::from(lhs.wrapping_shl(rhs))
978}
979
980#[sqlfunc(
981    is_monotone = "(false, false)",
982    output_type = "i64",
983    is_infix_op = true,
984    sqlname = "<<",
985    propagates_nulls = true
986)]
987// TODO(benesch): remove potentially dangerous usage of `as`.
988#[allow(clippy::as_conversions)]
989fn bit_shift_left_int64<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
990    let lhs = a.unwrap_int64();
991    let rhs = b.unwrap_int32() as u32;
992    Datum::from(lhs.wrapping_shl(rhs))
993}
994
995#[sqlfunc(
996    is_monotone = "(false, false)",
997    output_type = "u16",
998    is_infix_op = true,
999    sqlname = "<<",
1000    propagates_nulls = true
1001)]
1002// TODO(benesch): remove potentially dangerous usage of `as`.
1003#[allow(clippy::as_conversions)]
1004fn bit_shift_left_uint16<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1005    // widen to u32 and then cast back to u16 in order emulate the C promotion rules used in by Postgres
1006    // when the rhs in the 16-31 range, e.g. (1 << 17 should evaluate to 0)
1007    // see https://github.com/postgres/postgres/blob/REL_14_STABLE/src/backend/utils/adt/int.c#L1460-L1476
1008    let lhs: u32 = a.unwrap_uint16() as u32;
1009    let rhs: u32 = b.unwrap_uint32();
1010    Datum::from(lhs.wrapping_shl(rhs) as u16)
1011}
1012
1013#[sqlfunc(
1014    is_monotone = "(false, false)",
1015    output_type = "u32",
1016    is_infix_op = true,
1017    sqlname = "<<",
1018    propagates_nulls = true
1019)]
1020fn bit_shift_left_uint32<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1021    let lhs = a.unwrap_uint32();
1022    let rhs = b.unwrap_uint32();
1023    Datum::from(lhs.wrapping_shl(rhs))
1024}
1025
1026#[sqlfunc(
1027    is_monotone = "(false, false)",
1028    output_type = "u64",
1029    is_infix_op = true,
1030    sqlname = "<<",
1031    propagates_nulls = true
1032)]
1033fn bit_shift_left_uint64<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1034    let lhs = a.unwrap_uint64();
1035    let rhs = b.unwrap_uint32();
1036    Datum::from(lhs.wrapping_shl(rhs))
1037}
1038
1039#[sqlfunc(
1040    is_monotone = "(false, false)",
1041    output_type = "i16",
1042    is_infix_op = true,
1043    sqlname = ">>",
1044    propagates_nulls = true
1045)]
1046// TODO(benesch): remove potentially dangerous usage of `as`.
1047#[allow(clippy::as_conversions)]
1048fn bit_shift_right_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1049    // widen to i32 and then cast back to i16 in order emulate the C promotion rules used in by Postgres
1050    // when the rhs in the 16-31 range, e.g. (-32767 >> 17 should evaluate to -1)
1051    // see https://github.com/postgres/postgres/blob/REL_14_STABLE/src/backend/utils/adt/int.c#L1460-L1476
1052    let lhs = a.unwrap_int16() as i32;
1053    let rhs = b.unwrap_int32() as u32;
1054    Datum::from(lhs.wrapping_shr(rhs) as i16)
1055}
1056
1057#[sqlfunc(
1058    is_monotone = "(false, false)",
1059    output_type = "i32",
1060    is_infix_op = true,
1061    sqlname = ">>",
1062    propagates_nulls = true
1063)]
1064// TODO(benesch): remove potentially dangerous usage of `as`.
1065#[allow(clippy::as_conversions)]
1066fn bit_shift_right_int32<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1067    let lhs = a.unwrap_int32();
1068    let rhs = b.unwrap_int32() as u32;
1069    Datum::from(lhs.wrapping_shr(rhs))
1070}
1071
1072#[sqlfunc(
1073    is_monotone = "(false, false)",
1074    output_type = "i64",
1075    is_infix_op = true,
1076    sqlname = ">>",
1077    propagates_nulls = true
1078)]
1079// TODO(benesch): remove potentially dangerous usage of `as`.
1080#[allow(clippy::as_conversions)]
1081fn bit_shift_right_int64<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1082    let lhs = a.unwrap_int64();
1083    let rhs = b.unwrap_int32() as u32;
1084    Datum::from(lhs.wrapping_shr(rhs))
1085}
1086
1087#[sqlfunc(
1088    is_monotone = "(false, false)",
1089    output_type = "u16",
1090    is_infix_op = true,
1091    sqlname = ">>",
1092    propagates_nulls = true
1093)]
1094// TODO(benesch): remove potentially dangerous usage of `as`.
1095#[allow(clippy::as_conversions)]
1096fn bit_shift_right_uint16<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1097    // widen to u32 and then cast back to u16 in order emulate the C promotion rules used in by Postgres
1098    // when the rhs in the 16-31 range, e.g. (-32767 >> 17 should evaluate to -1)
1099    // see https://github.com/postgres/postgres/blob/REL_14_STABLE/src/backend/utils/adt/int.c#L1460-L1476
1100    let lhs = a.unwrap_uint16() as u32;
1101    let rhs = b.unwrap_uint32();
1102    Datum::from(lhs.wrapping_shr(rhs) as u16)
1103}
1104
1105#[sqlfunc(
1106    is_monotone = "(false, false)",
1107    output_type = "u32",
1108    is_infix_op = true,
1109    sqlname = ">>",
1110    propagates_nulls = true
1111)]
1112fn bit_shift_right_uint32<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1113    let lhs = a.unwrap_uint32();
1114    let rhs = b.unwrap_uint32();
1115    Datum::from(lhs.wrapping_shr(rhs))
1116}
1117
1118#[sqlfunc(
1119    is_monotone = "(false, false)",
1120    output_type = "u64",
1121    is_infix_op = true,
1122    sqlname = ">>",
1123    propagates_nulls = true
1124)]
1125fn bit_shift_right_uint64<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1126    let lhs = a.unwrap_uint64();
1127    let rhs = b.unwrap_uint32();
1128    Datum::from(lhs.wrapping_shr(rhs))
1129}
1130
1131#[sqlfunc(
1132    is_monotone = "(true, true)",
1133    output_type = "i16",
1134    is_infix_op = true,
1135    sqlname = "-",
1136    propagates_nulls = true
1137)]
1138fn sub_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1139    a.unwrap_int16()
1140        .checked_sub(b.unwrap_int16())
1141        .ok_or(EvalError::NumericFieldOverflow)
1142        .map(Datum::from)
1143}
1144
1145#[sqlfunc(
1146    is_monotone = "(true, true)",
1147    output_type = "i32",
1148    is_infix_op = true,
1149    sqlname = "-",
1150    propagates_nulls = true
1151)]
1152fn sub_int32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1153    a.unwrap_int32()
1154        .checked_sub(b.unwrap_int32())
1155        .ok_or(EvalError::NumericFieldOverflow)
1156        .map(Datum::from)
1157}
1158
1159#[sqlfunc(
1160    is_monotone = "(true, true)",
1161    output_type = "i64",
1162    is_infix_op = true,
1163    sqlname = "-",
1164    propagates_nulls = true
1165)]
1166fn sub_int64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1167    a.unwrap_int64()
1168        .checked_sub(b.unwrap_int64())
1169        .ok_or(EvalError::NumericFieldOverflow)
1170        .map(Datum::from)
1171}
1172
1173#[sqlfunc(
1174    is_monotone = "(true, true)",
1175    output_type = "u16",
1176    is_infix_op = true,
1177    sqlname = "-",
1178    propagates_nulls = true
1179)]
1180fn sub_uint16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1181    a.unwrap_uint16()
1182        .checked_sub(b.unwrap_uint16())
1183        .ok_or(EvalError::UInt16OutOfRange(format!("{a} - {b}").into()))
1184        .map(Datum::from)
1185}
1186
1187#[sqlfunc(
1188    is_monotone = "(true, true)",
1189    output_type = "u32",
1190    is_infix_op = true,
1191    sqlname = "-",
1192    propagates_nulls = true
1193)]
1194fn sub_uint32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1195    a.unwrap_uint32()
1196        .checked_sub(b.unwrap_uint32())
1197        .ok_or(EvalError::UInt32OutOfRange(format!("{a} - {b}").into()))
1198        .map(Datum::from)
1199}
1200
1201#[sqlfunc(
1202    is_monotone = "(true, true)",
1203    output_type = "u64",
1204    is_infix_op = true,
1205    sqlname = "-",
1206    propagates_nulls = true
1207)]
1208fn sub_uint64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1209    a.unwrap_uint64()
1210        .checked_sub(b.unwrap_uint64())
1211        .ok_or(EvalError::UInt64OutOfRange(format!("{a} - {b}").into()))
1212        .map(Datum::from)
1213}
1214
1215#[sqlfunc(
1216    is_monotone = "(true, true)",
1217    output_type = "f32",
1218    is_infix_op = true,
1219    sqlname = "-",
1220    propagates_nulls = true
1221)]
1222fn sub_float32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1223    let a = a.unwrap_float32();
1224    let b = b.unwrap_float32();
1225    let difference = a - b;
1226    if difference.is_infinite() && !a.is_infinite() && !b.is_infinite() {
1227        Err(EvalError::FloatOverflow)
1228    } else {
1229        Ok(Datum::from(difference))
1230    }
1231}
1232
1233#[sqlfunc(
1234    is_monotone = "(true, true)",
1235    output_type = "f64",
1236    is_infix_op = true,
1237    sqlname = "-",
1238    propagates_nulls = true
1239)]
1240fn sub_float64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1241    let a = a.unwrap_float64();
1242    let b = b.unwrap_float64();
1243    let difference = a - b;
1244    if difference.is_infinite() && !a.is_infinite() && !b.is_infinite() {
1245        Err(EvalError::FloatOverflow)
1246    } else {
1247        Ok(Datum::from(difference))
1248    }
1249}
1250
1251#[sqlfunc(
1252    is_monotone = "(true, true)",
1253    output_type = "Numeric",
1254    is_infix_op = true,
1255    sqlname = "-",
1256    propagates_nulls = true
1257)]
1258fn sub_numeric<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1259    let mut cx = numeric::cx_datum();
1260    let mut a = a.unwrap_numeric().0;
1261    cx.sub(&mut a, &b.unwrap_numeric().0);
1262    if cx.status().overflow() {
1263        Err(EvalError::FloatOverflow)
1264    } else {
1265        Ok(Datum::from(a))
1266    }
1267}
1268
1269#[sqlfunc(
1270    is_monotone = "(true, true)",
1271    output_type = "Interval",
1272    is_infix_op = false,
1273    sqlname = "age",
1274    propagates_nulls = true
1275)]
1276fn age_timestamp<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1277    let a_ts = a.unwrap_timestamp();
1278    let b_ts = b.unwrap_timestamp();
1279    let age = a_ts.age(&b_ts)?;
1280
1281    Ok(Datum::from(age))
1282}
1283
1284#[sqlfunc(
1285    is_monotone = "(true, true)",
1286    output_type = "Interval",
1287    is_infix_op = false,
1288    sqlname = "age",
1289    propagates_nulls = true
1290)]
1291fn age_timestamptz<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1292    let a_ts = a.unwrap_timestamptz();
1293    let b_ts = b.unwrap_timestamptz();
1294    let age = a_ts.age(&b_ts)?;
1295
1296    Ok(Datum::from(age))
1297}
1298
1299#[sqlfunc(
1300    is_monotone = "(true, true)",
1301    output_type = "Interval",
1302    is_infix_op = true,
1303    sqlname = "-",
1304    propagates_nulls = true
1305)]
1306fn sub_timestamp<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1307    Datum::from(a.unwrap_timestamp() - b.unwrap_timestamp())
1308}
1309
1310#[sqlfunc(
1311    is_monotone = "(true, true)",
1312    output_type = "Interval",
1313    is_infix_op = true,
1314    sqlname = "-",
1315    propagates_nulls = true
1316)]
1317fn sub_timestamptz<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1318    Datum::from(a.unwrap_timestamptz() - b.unwrap_timestamptz())
1319}
1320
1321#[sqlfunc(
1322    is_monotone = "(true, true)",
1323    output_type = "i32",
1324    is_infix_op = true,
1325    sqlname = "-",
1326    propagates_nulls = true
1327)]
1328fn sub_date<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1329    Datum::from(a.unwrap_date() - b.unwrap_date())
1330}
1331
1332#[sqlfunc(
1333    is_monotone = "(true, true)",
1334    output_type = "Interval",
1335    is_infix_op = true,
1336    sqlname = "-",
1337    propagates_nulls = true
1338)]
1339fn sub_time<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1340    Datum::from(a.unwrap_time() - b.unwrap_time())
1341}
1342
1343#[sqlfunc(
1344    is_monotone = "(true, true)",
1345    output_type = "Interval",
1346    is_infix_op = true,
1347    sqlname = "-",
1348    propagates_nulls = true
1349)]
1350fn sub_interval<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1351    b.unwrap_interval()
1352        .checked_neg()
1353        .and_then(|b| b.checked_add(&a.unwrap_interval()))
1354        .ok_or(EvalError::IntervalOutOfRange(format!("{a} - {b}").into()))
1355        .map(Datum::from)
1356}
1357
1358#[sqlfunc(
1359    is_monotone = "(true, true)",
1360    output_type = "CheckedTimestamp<NaiveDateTime>",
1361    is_infix_op = true,
1362    sqlname = "-",
1363    propagates_nulls = true
1364)]
1365fn sub_date_interval<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1366    let date = a.unwrap_date();
1367    let interval = b.unwrap_interval();
1368
1369    let dt = NaiveDate::from(date).and_hms_opt(0, 0, 0).unwrap();
1370    let dt = interval
1371        .months
1372        .checked_neg()
1373        .ok_or(EvalError::IntervalOutOfRange(
1374            interval.months.to_string().into(),
1375        ))
1376        .and_then(|months| add_timestamp_months(&dt, months))?;
1377    let dt = dt
1378        .checked_sub_signed(interval.duration_as_chrono())
1379        .ok_or(EvalError::TimestampOutOfRange)?;
1380    Ok(dt.try_into()?)
1381}
1382
1383#[sqlfunc(
1384    is_monotone = "(true, true)",
1385    output_type = "chrono::NaiveTime",
1386    is_infix_op = true,
1387    sqlname = "-",
1388    propagates_nulls = true
1389)]
1390fn sub_time_interval<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
1391    let time = a.unwrap_time();
1392    let interval = b.unwrap_interval();
1393    let (t, _) = time.overflowing_sub_signed(interval.duration_as_chrono());
1394    Datum::Time(t)
1395}
1396
1397#[sqlfunc(
1398    is_monotone = "(true, true)",
1399    output_type = "i16",
1400    is_infix_op = true,
1401    sqlname = "*",
1402    propagates_nulls = true
1403)]
1404fn mul_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1405    a.unwrap_int16()
1406        .checked_mul(b.unwrap_int16())
1407        .ok_or(EvalError::NumericFieldOverflow)
1408        .map(Datum::from)
1409}
1410
1411#[sqlfunc(
1412    is_monotone = "(true, true)",
1413    output_type = "i32",
1414    is_infix_op = true,
1415    sqlname = "*",
1416    propagates_nulls = true
1417)]
1418fn mul_int32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1419    a.unwrap_int32()
1420        .checked_mul(b.unwrap_int32())
1421        .ok_or(EvalError::NumericFieldOverflow)
1422        .map(Datum::from)
1423}
1424
1425#[sqlfunc(
1426    is_monotone = "(true, true)",
1427    output_type = "i64",
1428    is_infix_op = true,
1429    sqlname = "*",
1430    propagates_nulls = true
1431)]
1432fn mul_int64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1433    a.unwrap_int64()
1434        .checked_mul(b.unwrap_int64())
1435        .ok_or(EvalError::NumericFieldOverflow)
1436        .map(Datum::from)
1437}
1438
1439#[sqlfunc(
1440    is_monotone = "(true, true)",
1441    output_type = "u16",
1442    is_infix_op = true,
1443    sqlname = "*",
1444    propagates_nulls = true
1445)]
1446fn mul_uint16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1447    a.unwrap_uint16()
1448        .checked_mul(b.unwrap_uint16())
1449        .ok_or(EvalError::UInt16OutOfRange(format!("{a} * {b}").into()))
1450        .map(Datum::from)
1451}
1452
1453#[sqlfunc(
1454    is_monotone = "(true, true)",
1455    output_type = "u32",
1456    is_infix_op = true,
1457    sqlname = "*",
1458    propagates_nulls = true
1459)]
1460fn mul_uint32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1461    a.unwrap_uint32()
1462        .checked_mul(b.unwrap_uint32())
1463        .ok_or(EvalError::UInt32OutOfRange(format!("{a} * {b}").into()))
1464        .map(Datum::from)
1465}
1466
1467#[sqlfunc(
1468    is_monotone = "(true, true)",
1469    output_type = "u64",
1470    is_infix_op = true,
1471    sqlname = "*",
1472    propagates_nulls = true
1473)]
1474fn mul_uint64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1475    a.unwrap_uint64()
1476        .checked_mul(b.unwrap_uint64())
1477        .ok_or(EvalError::UInt64OutOfRange(format!("{a} * {b}").into()))
1478        .map(Datum::from)
1479}
1480
1481#[sqlfunc(
1482    is_monotone = "(true, true)",
1483    output_type = "f32",
1484    is_infix_op = true,
1485    sqlname = "*",
1486    propagates_nulls = true
1487)]
1488fn mul_float32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1489    let a = a.unwrap_float32();
1490    let b = b.unwrap_float32();
1491    let product = a * b;
1492    if product.is_infinite() && !a.is_infinite() && !b.is_infinite() {
1493        Err(EvalError::FloatOverflow)
1494    } else if product == 0.0f32 && a != 0.0f32 && b != 0.0f32 {
1495        Err(EvalError::FloatUnderflow)
1496    } else {
1497        Ok(Datum::from(product))
1498    }
1499}
1500
1501#[sqlfunc(
1502    is_monotone = "(true, true)",
1503    output_type = "f64",
1504    is_infix_op = true,
1505    sqlname = "*",
1506    propagates_nulls = true
1507)]
1508fn mul_float64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1509    let a = a.unwrap_float64();
1510    let b = b.unwrap_float64();
1511    let product = a * b;
1512    if product.is_infinite() && !a.is_infinite() && !b.is_infinite() {
1513        Err(EvalError::FloatOverflow)
1514    } else if product == 0.0f64 && a != 0.0f64 && b != 0.0f64 {
1515        Err(EvalError::FloatUnderflow)
1516    } else {
1517        Ok(Datum::from(product))
1518    }
1519}
1520
1521#[sqlfunc(
1522    is_monotone = "(true, true)",
1523    output_type = "Numeric",
1524    is_infix_op = true,
1525    sqlname = "*",
1526    propagates_nulls = true
1527)]
1528fn mul_numeric<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1529    let mut cx = numeric::cx_datum();
1530    let mut a = a.unwrap_numeric().0;
1531    cx.mul(&mut a, &b.unwrap_numeric().0);
1532    let cx_status = cx.status();
1533    if cx_status.overflow() {
1534        Err(EvalError::FloatOverflow)
1535    } else if cx_status.subnormal() {
1536        Err(EvalError::FloatUnderflow)
1537    } else {
1538        numeric::munge_numeric(&mut a).unwrap();
1539        Ok(Datum::from(a))
1540    }
1541}
1542
1543#[sqlfunc(
1544    is_monotone = "(true, true)",
1545    output_type = "Interval",
1546    is_infix_op = true,
1547    sqlname = "*",
1548    propagates_nulls = true
1549)]
1550fn mul_interval<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1551    a.unwrap_interval()
1552        .checked_mul(b.unwrap_float64())
1553        .ok_or(EvalError::IntervalOutOfRange(format!("{a} * {b}").into()))
1554        .map(Datum::from)
1555}
1556
1557#[sqlfunc(
1558    is_monotone = "(true, false)",
1559    output_type = "i16",
1560    is_infix_op = true,
1561    sqlname = "/",
1562    propagates_nulls = true
1563)]
1564fn div_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1565    let b = b.unwrap_int16();
1566    if b == 0 {
1567        Err(EvalError::DivisionByZero)
1568    } else {
1569        a.unwrap_int16()
1570            .checked_div(b)
1571            .map(Datum::from)
1572            .ok_or(EvalError::Int16OutOfRange(format!("{a} / {b}").into()))
1573    }
1574}
1575
1576#[sqlfunc(
1577    is_monotone = "(true, false)",
1578    output_type = "i32",
1579    is_infix_op = true,
1580    sqlname = "/",
1581    propagates_nulls = true
1582)]
1583fn div_int32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1584    let b = b.unwrap_int32();
1585    if b == 0 {
1586        Err(EvalError::DivisionByZero)
1587    } else {
1588        a.unwrap_int32()
1589            .checked_div(b)
1590            .map(Datum::from)
1591            .ok_or(EvalError::Int32OutOfRange(format!("{a} / {b}").into()))
1592    }
1593}
1594
1595#[sqlfunc(
1596    is_monotone = "(true, false)",
1597    output_type = "i64",
1598    is_infix_op = true,
1599    sqlname = "/",
1600    propagates_nulls = true
1601)]
1602fn div_int64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1603    let b = b.unwrap_int64();
1604    if b == 0 {
1605        Err(EvalError::DivisionByZero)
1606    } else {
1607        a.unwrap_int64()
1608            .checked_div(b)
1609            .map(Datum::from)
1610            .ok_or(EvalError::Int64OutOfRange(format!("{a} / {b}").into()))
1611    }
1612}
1613
1614#[sqlfunc(
1615    is_monotone = "(true, false)",
1616    output_type = "u16",
1617    is_infix_op = true,
1618    sqlname = "/",
1619    propagates_nulls = true
1620)]
1621fn div_uint16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1622    let b = b.unwrap_uint16();
1623    if b == 0 {
1624        Err(EvalError::DivisionByZero)
1625    } else {
1626        Ok(Datum::from(a.unwrap_uint16() / b))
1627    }
1628}
1629
1630#[sqlfunc(
1631    is_monotone = "(true, false)",
1632    output_type = "u32",
1633    is_infix_op = true,
1634    sqlname = "/",
1635    propagates_nulls = true
1636)]
1637fn div_uint32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1638    let b = b.unwrap_uint32();
1639    if b == 0 {
1640        Err(EvalError::DivisionByZero)
1641    } else {
1642        Ok(Datum::from(a.unwrap_uint32() / b))
1643    }
1644}
1645
1646#[sqlfunc(
1647    is_monotone = "(true, false)",
1648    output_type = "u64",
1649    is_infix_op = true,
1650    sqlname = "/",
1651    propagates_nulls = true
1652)]
1653fn div_uint64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1654    let b = b.unwrap_uint64();
1655    if b == 0 {
1656        Err(EvalError::DivisionByZero)
1657    } else {
1658        Ok(Datum::from(a.unwrap_uint64() / b))
1659    }
1660}
1661
1662#[sqlfunc(
1663    is_monotone = "(true, false)",
1664    output_type = "f32",
1665    is_infix_op = true,
1666    sqlname = "/",
1667    propagates_nulls = true
1668)]
1669fn div_float32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1670    let a = a.unwrap_float32();
1671    let b = b.unwrap_float32();
1672    if b == 0.0f32 && !a.is_nan() {
1673        Err(EvalError::DivisionByZero)
1674    } else {
1675        let quotient = a / b;
1676        if quotient.is_infinite() && !a.is_infinite() {
1677            Err(EvalError::FloatOverflow)
1678        } else if quotient == 0.0f32 && a != 0.0f32 && !b.is_infinite() {
1679            Err(EvalError::FloatUnderflow)
1680        } else {
1681            Ok(Datum::from(quotient))
1682        }
1683    }
1684}
1685
1686#[sqlfunc(
1687    is_monotone = "(true, false)",
1688    output_type = "f64",
1689    is_infix_op = true,
1690    sqlname = "/",
1691    propagates_nulls = true
1692)]
1693fn div_float64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1694    let a = a.unwrap_float64();
1695    let b = b.unwrap_float64();
1696    if b == 0.0f64 && !a.is_nan() {
1697        Err(EvalError::DivisionByZero)
1698    } else {
1699        let quotient = a / b;
1700        if quotient.is_infinite() && !a.is_infinite() {
1701            Err(EvalError::FloatOverflow)
1702        } else if quotient == 0.0f64 && a != 0.0f64 && !b.is_infinite() {
1703            Err(EvalError::FloatUnderflow)
1704        } else {
1705            Ok(Datum::from(quotient))
1706        }
1707    }
1708}
1709
1710#[sqlfunc(
1711    is_monotone = "(true, false)",
1712    output_type = "Numeric",
1713    is_infix_op = true,
1714    sqlname = "/",
1715    propagates_nulls = true
1716)]
1717fn div_numeric<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1718    let mut cx = numeric::cx_datum();
1719    let mut a = a.unwrap_numeric().0;
1720    let b = b.unwrap_numeric().0;
1721
1722    cx.div(&mut a, &b);
1723    let cx_status = cx.status();
1724
1725    // checking the status for division by zero errors is insufficient because
1726    // the underlying library treats 0/0 as undefined and not division by zero.
1727    if b.is_zero() {
1728        Err(EvalError::DivisionByZero)
1729    } else if cx_status.overflow() {
1730        Err(EvalError::FloatOverflow)
1731    } else if cx_status.subnormal() {
1732        Err(EvalError::FloatUnderflow)
1733    } else {
1734        numeric::munge_numeric(&mut a).unwrap();
1735        Ok(Datum::from(a))
1736    }
1737}
1738
1739#[sqlfunc(
1740    is_monotone = "(true, false)",
1741    output_type = "Interval",
1742    is_infix_op = true,
1743    sqlname = "/",
1744    propagates_nulls = true
1745)]
1746fn div_interval<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1747    let b = b.unwrap_float64();
1748    if b == 0.0 {
1749        Err(EvalError::DivisionByZero)
1750    } else {
1751        a.unwrap_interval()
1752            .checked_div(b)
1753            .ok_or(EvalError::IntervalOutOfRange(format!("{a} / {b}").into()))
1754            .map(Datum::from)
1755    }
1756}
1757
1758#[sqlfunc(
1759    is_monotone = "(false, false)",
1760    output_type = "i16",
1761    is_infix_op = true,
1762    sqlname = "%",
1763    propagates_nulls = true
1764)]
1765fn mod_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1766    let b = b.unwrap_int16();
1767    if b == 0 {
1768        Err(EvalError::DivisionByZero)
1769    } else {
1770        Ok(Datum::from(a.unwrap_int16().checked_rem(b).unwrap_or(0)))
1771    }
1772}
1773
1774#[sqlfunc(
1775    is_monotone = "(false, false)",
1776    output_type = "i32",
1777    is_infix_op = true,
1778    sqlname = "%",
1779    propagates_nulls = true
1780)]
1781fn mod_int32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1782    let b = b.unwrap_int32();
1783    if b == 0 {
1784        Err(EvalError::DivisionByZero)
1785    } else {
1786        Ok(Datum::from(a.unwrap_int32().checked_rem(b).unwrap_or(0)))
1787    }
1788}
1789
1790#[sqlfunc(
1791    is_monotone = "(false, false)",
1792    output_type = "i64",
1793    is_infix_op = true,
1794    sqlname = "%",
1795    propagates_nulls = true
1796)]
1797fn mod_int64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1798    let b = b.unwrap_int64();
1799    if b == 0 {
1800        Err(EvalError::DivisionByZero)
1801    } else {
1802        Ok(Datum::from(a.unwrap_int64().checked_rem(b).unwrap_or(0)))
1803    }
1804}
1805
1806#[sqlfunc(
1807    is_monotone = "(false, false)",
1808    output_type = "u16",
1809    is_infix_op = true,
1810    sqlname = "%",
1811    propagates_nulls = true
1812)]
1813fn mod_uint16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1814    let b = b.unwrap_uint16();
1815    if b == 0 {
1816        Err(EvalError::DivisionByZero)
1817    } else {
1818        Ok(Datum::from(a.unwrap_uint16() % b))
1819    }
1820}
1821
1822#[sqlfunc(
1823    is_monotone = "(false, false)",
1824    output_type = "u32",
1825    is_infix_op = true,
1826    sqlname = "%",
1827    propagates_nulls = true
1828)]
1829fn mod_uint32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1830    let b = b.unwrap_uint32();
1831    if b == 0 {
1832        Err(EvalError::DivisionByZero)
1833    } else {
1834        Ok(Datum::from(a.unwrap_uint32() % b))
1835    }
1836}
1837
1838#[sqlfunc(
1839    is_monotone = "(false, false)",
1840    output_type = "u64",
1841    is_infix_op = true,
1842    sqlname = "%",
1843    propagates_nulls = true
1844)]
1845fn mod_uint64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1846    let b = b.unwrap_uint64();
1847    if b == 0 {
1848        Err(EvalError::DivisionByZero)
1849    } else {
1850        Ok(Datum::from(a.unwrap_uint64() % b))
1851    }
1852}
1853
1854#[sqlfunc(
1855    is_monotone = "(false, false)",
1856    output_type = "f32",
1857    is_infix_op = true,
1858    sqlname = "%",
1859    propagates_nulls = true
1860)]
1861fn mod_float32<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1862    let b = b.unwrap_float32();
1863    if b == 0.0 {
1864        Err(EvalError::DivisionByZero)
1865    } else {
1866        Ok(Datum::from(a.unwrap_float32() % b))
1867    }
1868}
1869
1870#[sqlfunc(
1871    is_monotone = "(false, false)",
1872    output_type = "f64",
1873    is_infix_op = true,
1874    sqlname = "%",
1875    propagates_nulls = true
1876)]
1877fn mod_float64<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1878    let b = b.unwrap_float64();
1879    if b == 0.0 {
1880        Err(EvalError::DivisionByZero)
1881    } else {
1882        Ok(Datum::from(a.unwrap_float64() % b))
1883    }
1884}
1885
1886#[sqlfunc(
1887    is_monotone = "(false, false)",
1888    output_type = "Numeric",
1889    is_infix_op = true,
1890    sqlname = "%",
1891    propagates_nulls = true
1892)]
1893fn mod_numeric<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1894    let mut a = a.unwrap_numeric();
1895    let b = b.unwrap_numeric();
1896    if b.0.is_zero() {
1897        return Err(EvalError::DivisionByZero);
1898    }
1899    let mut cx = numeric::cx_datum();
1900    // Postgres does _not_ use IEEE 754-style remainder
1901    cx.rem(&mut a.0, &b.0);
1902    numeric::munge_numeric(&mut a.0).unwrap();
1903    Ok(Datum::Numeric(a))
1904}
1905
1906fn neg_interval_inner(a: Datum) -> Result<Interval, EvalError> {
1907    a.unwrap_interval()
1908        .checked_neg()
1909        .ok_or(EvalError::IntervalOutOfRange(a.to_string().into()))
1910}
1911
1912fn log_guard_numeric(val: &Numeric, function_name: &str) -> Result<(), EvalError> {
1913    if val.is_negative() {
1914        return Err(EvalError::NegativeOutOfDomain(function_name.into()));
1915    }
1916    if val.is_zero() {
1917        return Err(EvalError::ZeroOutOfDomain(function_name.into()));
1918    }
1919    Ok(())
1920}
1921
1922#[sqlfunc(
1923    is_monotone = "(false, false)",
1924    output_type = "Numeric",
1925    is_infix_op = false,
1926    sqlname = "log",
1927    propagates_nulls = true
1928)]
1929fn log_base_numeric<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1930    let mut a = a.unwrap_numeric().0;
1931    log_guard_numeric(&a, "log")?;
1932    let mut b = b.unwrap_numeric().0;
1933    log_guard_numeric(&b, "log")?;
1934    let mut cx = numeric::cx_datum();
1935    cx.ln(&mut a);
1936    cx.ln(&mut b);
1937    cx.div(&mut b, &a);
1938    if a.is_zero() {
1939        Err(EvalError::DivisionByZero)
1940    } else {
1941        // This division can result in slightly wrong answers due to the
1942        // limitation of dividing irrational numbers. To correct that, see if
1943        // rounding off the value from its `numeric::NUMERIC_DATUM_MAX_PRECISION
1944        // - 1`th position results in an integral value.
1945        cx.set_precision(usize::from(numeric::NUMERIC_DATUM_MAX_PRECISION - 1))
1946            .expect("reducing precision below max always succeeds");
1947        let mut integral_check = b.clone();
1948
1949        // `reduce` rounds to the context's final digit when the number of
1950        // digits in its argument exceeds its precision. We've contrived that to
1951        // happen by shrinking the context's precision by 1.
1952        cx.reduce(&mut integral_check);
1953
1954        // Reduced integral values always have a non-negative exponent.
1955        let mut b = if integral_check.exponent() >= 0 {
1956            // We believe our result should have been an integral
1957            integral_check
1958        } else {
1959            b
1960        };
1961
1962        numeric::munge_numeric(&mut b).unwrap();
1963        Ok(Datum::from(b))
1964    }
1965}
1966
1967#[sqlfunc(
1968    is_monotone = "(false, false)",
1969    output_type = "f64",
1970    is_infix_op = false,
1971    propagates_nulls = true
1972)]
1973fn power<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
1974    let a = a.unwrap_float64();
1975    let b = b.unwrap_float64();
1976    if a == 0.0 && b.is_sign_negative() {
1977        return Err(EvalError::Undefined(
1978            "zero raised to a negative power".into(),
1979        ));
1980    }
1981    if a.is_sign_negative() && b.fract() != 0.0 {
1982        // Equivalent to PG error:
1983        // > a negative number raised to a non-integer power yields a complex result
1984        return Err(EvalError::ComplexOutOfRange("pow".into()));
1985    }
1986    let res = a.powf(b);
1987    if res.is_infinite() {
1988        return Err(EvalError::FloatOverflow);
1989    }
1990    if res == 0.0 && a != 0.0 {
1991        return Err(EvalError::FloatUnderflow);
1992    }
1993    Ok(Datum::from(res))
1994}
1995
1996#[sqlfunc(
1997    is_monotone = "(false, false)",
1998    output_type = "uuid::Uuid",
1999    is_infix_op = false,
2000    propagates_nulls = true
2001)]
2002fn uuid_generate_v5<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2003    let a = a.unwrap_uuid();
2004    let b = b.unwrap_str();
2005    let res = uuid::Uuid::new_v5(&a, b.as_bytes());
2006    Datum::Uuid(res)
2007}
2008
2009#[sqlfunc(
2010    is_monotone = "(false, false)",
2011    output_type = "Numeric",
2012    is_infix_op = false,
2013    propagates_nulls = true
2014)]
2015fn power_numeric<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
2016    let mut a = a.unwrap_numeric().0;
2017    let b = b.unwrap_numeric().0;
2018    if a.is_zero() {
2019        if b.is_zero() {
2020            return Ok(Datum::from(Numeric::from(1)));
2021        }
2022        if b.is_negative() {
2023            return Err(EvalError::Undefined(
2024                "zero raised to a negative power".into(),
2025            ));
2026        }
2027    }
2028    if a.is_negative() && b.exponent() < 0 {
2029        // Equivalent to PG error:
2030        // > a negative number raised to a non-integer power yields a complex result
2031        return Err(EvalError::ComplexOutOfRange("pow".into()));
2032    }
2033    let mut cx = numeric::cx_datum();
2034    cx.pow(&mut a, &b);
2035    let cx_status = cx.status();
2036    if cx_status.overflow() || (cx_status.invalid_operation() && !b.is_negative()) {
2037        Err(EvalError::FloatOverflow)
2038    } else if cx_status.subnormal() || cx_status.invalid_operation() {
2039        Err(EvalError::FloatUnderflow)
2040    } else {
2041        numeric::munge_numeric(&mut a).unwrap();
2042        Ok(Datum::from(a))
2043    }
2044}
2045
2046#[sqlfunc(
2047    is_monotone = "(false, false)",
2048    output_type = "i32",
2049    is_infix_op = false,
2050    propagates_nulls = true
2051)]
2052fn get_bit<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
2053    let bytes = a.unwrap_bytes();
2054    let index = b.unwrap_int32();
2055    let err = EvalError::IndexOutOfRange {
2056        provided: index,
2057        valid_end: i32::try_from(bytes.len().saturating_mul(8)).unwrap() - 1,
2058    };
2059
2060    let index = usize::try_from(index).map_err(|_| err.clone())?;
2061
2062    let byte_index = index / 8;
2063    let bit_index = index % 8;
2064
2065    let i = bytes
2066        .get(byte_index)
2067        .map(|b| (*b >> bit_index) & 1)
2068        .ok_or(err)?;
2069    assert!(i == 0 || i == 1);
2070    Ok(Datum::from(i32::from(i)))
2071}
2072
2073#[sqlfunc(
2074    is_monotone = "(false, false)",
2075    output_type = "i32",
2076    is_infix_op = false,
2077    propagates_nulls = true
2078)]
2079fn get_byte<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
2080    let bytes = a.unwrap_bytes();
2081    let index = b.unwrap_int32();
2082    let err = EvalError::IndexOutOfRange {
2083        provided: index,
2084        valid_end: i32::try_from(bytes.len()).unwrap() - 1,
2085    };
2086    let i: &u8 = bytes
2087        .get(usize::try_from(index).map_err(|_| err.clone())?)
2088        .ok_or(err)?;
2089    Ok(Datum::from(i32::from(*i)))
2090}
2091
2092#[sqlfunc(
2093    is_monotone = "(false, false)",
2094    output_type = "bool",
2095    is_infix_op = false,
2096    sqlname = "constant_time_compare_bytes",
2097    propagates_nulls = true
2098)]
2099pub fn constant_time_eq_bytes<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
2100    let a_bytes = a.unwrap_bytes();
2101    let b_bytes = b.unwrap_bytes();
2102    Ok(Datum::from(bool::from(a_bytes.ct_eq(b_bytes))))
2103}
2104
2105#[sqlfunc(
2106    is_monotone = "(false, false)",
2107    output_type = "bool",
2108    is_infix_op = false,
2109    sqlname = "constant_time_compare_strings",
2110    propagates_nulls = true
2111)]
2112pub fn constant_time_eq_string<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
2113    let a = a.unwrap_str();
2114    let b = b.unwrap_str();
2115    Ok(Datum::from(bool::from(a.as_bytes().ct_eq(b.as_bytes()))))
2116}
2117
2118fn contains_range_elem<'a, R: RangeOps<'a>>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a>
2119where
2120    <R as TryFrom<Datum<'a>>>::Error: std::fmt::Debug,
2121{
2122    let range = a.unwrap_range();
2123    let elem = R::try_from(b).expect("type checking must produce correct R");
2124    Datum::from(range.contains_elem(&elem))
2125}
2126
2127/// Macro to define binary function for various range operations.
2128/// Parameters:
2129/// 1. Unique binary function symbol.
2130/// 2. Range function symbol.
2131/// 3. SQL name for the function.
2132macro_rules! range_fn {
2133    ($fn:expr, $range_fn:expr, $sqlname:expr) => {
2134        paste::paste! {
2135
2136            #[sqlfunc(
2137                is_monotone = "(false, false)",
2138                output_type = "bool",
2139                is_infix_op = true,
2140                sqlname = $sqlname,
2141                propagates_nulls = true
2142            )]
2143            fn [< range_ $fn >]<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a>
2144            {
2145                let l = a.unwrap_range();
2146                let r = b.unwrap_range();
2147                Datum::from(Range::<Datum<'a>>::$range_fn(&l, &r))
2148            }
2149        }
2150    };
2151}
2152
2153// RangeContainsRange is either @> or <@ depending on the order of the arguments.
2154// It doesn't influence the result, but it does influence the display string.
2155range_fn!(contains_range, contains_range, "@>");
2156range_fn!(contains_range_rev, contains_range, "<@");
2157range_fn!(overlaps, overlaps, "&&");
2158range_fn!(after, after, ">>");
2159range_fn!(before, before, "<<");
2160range_fn!(overleft, overleft, "&<");
2161range_fn!(overright, overright, "&>");
2162range_fn!(adjacent, adjacent, "-|-");
2163
2164fn range_union<'a>(
2165    a: Datum<'a>,
2166    b: Datum<'a>,
2167    temp_storage: &'a RowArena,
2168) -> Result<Datum<'a>, EvalError> {
2169    let l = a.unwrap_range();
2170    let r = b.unwrap_range();
2171    l.union(&r)?.into_result(temp_storage)
2172}
2173
2174fn range_intersection<'a>(
2175    a: Datum<'a>,
2176    b: Datum<'a>,
2177    temp_storage: &'a RowArena,
2178) -> Result<Datum<'a>, EvalError> {
2179    let l = a.unwrap_range();
2180    let r = b.unwrap_range();
2181    l.intersection(&r).into_result(temp_storage)
2182}
2183
2184fn range_difference<'a>(
2185    a: Datum<'a>,
2186    b: Datum<'a>,
2187    temp_storage: &'a RowArena,
2188) -> Result<Datum<'a>, EvalError> {
2189    let l = a.unwrap_range();
2190    let r = b.unwrap_range();
2191    l.difference(&r)?.into_result(temp_storage)
2192}
2193
2194#[sqlfunc(
2195    is_monotone = "(false, false)",
2196    output_type = "bool",
2197    is_infix_op = true,
2198    sqlname = "=",
2199    propagates_nulls = true
2200)]
2201fn eq<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2202    Datum::from(a == b)
2203}
2204
2205#[sqlfunc(
2206    is_monotone = "(false, false)",
2207    output_type = "bool",
2208    is_infix_op = true,
2209    sqlname = "!=",
2210    propagates_nulls = true
2211)]
2212fn not_eq<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2213    Datum::from(a != b)
2214}
2215
2216#[sqlfunc(
2217    is_monotone = "(true, true)",
2218    output_type = "bool",
2219    is_infix_op = true,
2220    sqlname = "<",
2221    propagates_nulls = true
2222)]
2223fn lt<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2224    Datum::from(a < b)
2225}
2226
2227#[sqlfunc(
2228    is_monotone = "(true, true)",
2229    output_type = "bool",
2230    is_infix_op = true,
2231    sqlname = "<=",
2232    propagates_nulls = true
2233)]
2234fn lte<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2235    Datum::from(a <= b)
2236}
2237
2238#[sqlfunc(
2239    is_monotone = "(true, true)",
2240    output_type = "bool",
2241    is_infix_op = true,
2242    sqlname = ">",
2243    propagates_nulls = true
2244)]
2245fn gt<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2246    Datum::from(a > b)
2247}
2248
2249#[sqlfunc(
2250    is_monotone = "(true, true)",
2251    output_type = "bool",
2252    is_infix_op = true,
2253    sqlname = ">=",
2254    propagates_nulls = true
2255)]
2256fn gte<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2257    Datum::from(a >= b)
2258}
2259
2260fn to_char_timestamplike<'a, T>(ts: &T, format: &str, temp_storage: &'a RowArena) -> Datum<'a>
2261where
2262    T: TimestampLike,
2263{
2264    let fmt = DateTimeFormat::compile(format);
2265    Datum::String(temp_storage.push_string(fmt.render(ts)))
2266}
2267
2268fn jsonb_get_int64<'a>(
2269    a: Datum<'a>,
2270    b: Datum<'a>,
2271    temp_storage: &'a RowArena,
2272    stringify: bool,
2273) -> Datum<'a> {
2274    let i = b.unwrap_int64();
2275    match a {
2276        Datum::List(list) => {
2277            let i = if i >= 0 {
2278                usize::cast_from(i.unsigned_abs())
2279            } else {
2280                // index backwards from the end
2281                let i = usize::cast_from(i.unsigned_abs());
2282                (list.iter().count()).wrapping_sub(i)
2283            };
2284            match list.iter().nth(i) {
2285                Some(d) if stringify => jsonb_stringify(d, temp_storage),
2286                Some(d) => d,
2287                None => Datum::Null,
2288            }
2289        }
2290        Datum::Map(_) => Datum::Null,
2291        _ => {
2292            if i == 0 || i == -1 {
2293                // I have no idea why postgres does this, but we're stuck with it
2294                if stringify {
2295                    jsonb_stringify(a, temp_storage)
2296                } else {
2297                    a
2298                }
2299            } else {
2300                Datum::Null
2301            }
2302        }
2303    }
2304}
2305
2306fn jsonb_get_string<'a>(
2307    a: Datum<'a>,
2308    b: Datum<'a>,
2309    temp_storage: &'a RowArena,
2310    stringify: bool,
2311) -> Datum<'a> {
2312    let k = b.unwrap_str();
2313    match a {
2314        Datum::Map(dict) => match dict.iter().find(|(k2, _v)| k == *k2) {
2315            Some((_k, v)) if stringify => jsonb_stringify(v, temp_storage),
2316            Some((_k, v)) => v,
2317            None => Datum::Null,
2318        },
2319        _ => Datum::Null,
2320    }
2321}
2322
2323fn jsonb_get_path<'a>(
2324    a: Datum<'a>,
2325    b: Datum<'a>,
2326    temp_storage: &'a RowArena,
2327    stringify: bool,
2328) -> Datum<'a> {
2329    let mut json = a;
2330    let path = b.unwrap_array().elements();
2331    for key in path.iter() {
2332        let key = match key {
2333            Datum::String(s) => s,
2334            Datum::Null => return Datum::Null,
2335            _ => unreachable!("keys in jsonb_get_path known to be strings"),
2336        };
2337        json = match json {
2338            Datum::Map(map) => match map.iter().find(|(k, _)| key == *k) {
2339                Some((_k, v)) => v,
2340                None => return Datum::Null,
2341            },
2342            Datum::List(list) => match strconv::parse_int64(key) {
2343                Ok(i) => {
2344                    let i = if i >= 0 {
2345                        usize::cast_from(i.unsigned_abs())
2346                    } else {
2347                        // index backwards from the end
2348                        let i = usize::cast_from(i.unsigned_abs());
2349                        (list.iter().count()).wrapping_sub(i)
2350                    };
2351                    match list.iter().nth(i) {
2352                        Some(e) => e,
2353                        None => return Datum::Null,
2354                    }
2355                }
2356                Err(_) => return Datum::Null,
2357            },
2358            _ => return Datum::Null,
2359        }
2360    }
2361    if stringify {
2362        jsonb_stringify(json, temp_storage)
2363    } else {
2364        json
2365    }
2366}
2367
2368#[sqlfunc(
2369    is_monotone = "(false, false)",
2370    output_type = "bool",
2371    is_infix_op = true,
2372    sqlname = "?",
2373    propagates_nulls = true
2374)]
2375fn jsonb_contains_string<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2376    let k = b.unwrap_str();
2377    // https://www.postgresql.org/docs/current/datatype-json.html#JSON-CONTAINMENT
2378    match a {
2379        Datum::List(list) => list.iter().any(|k2| b == k2).into(),
2380        Datum::Map(dict) => dict.iter().any(|(k2, _v)| k == k2).into(),
2381        Datum::String(string) => (string == k).into(),
2382        _ => false.into(),
2383    }
2384}
2385
2386#[sqlfunc(
2387    is_monotone = "(false, false)",
2388    output_type = "bool",
2389    is_infix_op = true,
2390    sqlname = "?",
2391    propagates_nulls = true
2392)]
2393fn map_contains_key<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2394    let map = a.unwrap_map();
2395    let k = b.unwrap_str(); // Map keys are always text.
2396    map.iter().any(|(k2, _v)| k == k2).into()
2397}
2398
2399#[sqlfunc(
2400    is_monotone = "(false, false)",
2401    output_type = "bool",
2402    is_infix_op = true,
2403    sqlname = "?&",
2404    propagates_nulls = true
2405)]
2406fn map_contains_all_keys<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2407    let map = a.unwrap_map();
2408    let keys = b.unwrap_array();
2409
2410    keys.elements()
2411        .iter()
2412        .all(|key| !key.is_null() && map.iter().any(|(k, _v)| k == key.unwrap_str()))
2413        .into()
2414}
2415
2416#[sqlfunc(
2417    is_monotone = "(false, false)",
2418    output_type = "bool",
2419    is_infix_op = true,
2420    sqlname = "?|",
2421    propagates_nulls = true
2422)]
2423fn map_contains_any_keys<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2424    let map = a.unwrap_map();
2425    let keys = b.unwrap_array();
2426
2427    keys.elements()
2428        .iter()
2429        .any(|key| !key.is_null() && map.iter().any(|(k, _v)| k == key.unwrap_str()))
2430        .into()
2431}
2432
2433#[sqlfunc(
2434    is_monotone = "(false, false)",
2435    output_type = "bool",
2436    is_infix_op = true,
2437    sqlname = "@>",
2438    propagates_nulls = true
2439)]
2440fn map_contains_map<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2441    let map_a = a.unwrap_map();
2442    b.unwrap_map()
2443        .iter()
2444        .all(|(b_key, b_val)| {
2445            map_a
2446                .iter()
2447                .any(|(a_key, a_val)| (a_key == b_key) && (a_val == b_val))
2448        })
2449        .into()
2450}
2451
2452fn map_get_value<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2453    let target_key = b.unwrap_str();
2454    match a.unwrap_map().iter().find(|(key, _v)| target_key == *key) {
2455        Some((_k, v)) => v,
2456        None => Datum::Null,
2457    }
2458}
2459
2460fn list_contains_list<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2461    let a = a.unwrap_list();
2462    let b = b.unwrap_list();
2463
2464    // NULL is never equal to NULL. If NULL is an element of b, b cannot be contained in a, even if a contains NULL.
2465    if b.iter().contains(&Datum::Null) {
2466        Datum::False
2467    } else {
2468        b.iter()
2469            .all(|item_b| a.iter().any(|item_a| item_a == item_b))
2470            .into()
2471    }
2472}
2473
2474// TODO(jamii) nested loops are possibly not the fastest way to do this
2475#[sqlfunc(
2476    is_monotone = "(false, false)",
2477    output_type = "bool",
2478    is_infix_op = true,
2479    sqlname = "@>",
2480    propagates_nulls = true
2481)]
2482fn jsonb_contains_jsonb<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
2483    // https://www.postgresql.org/docs/current/datatype-json.html#JSON-CONTAINMENT
2484    fn contains(a: Datum, b: Datum, at_top_level: bool) -> bool {
2485        match (a, b) {
2486            (Datum::JsonNull, Datum::JsonNull) => true,
2487            (Datum::False, Datum::False) => true,
2488            (Datum::True, Datum::True) => true,
2489            (Datum::Numeric(a), Datum::Numeric(b)) => a == b,
2490            (Datum::String(a), Datum::String(b)) => a == b,
2491            (Datum::List(a), Datum::List(b)) => b
2492                .iter()
2493                .all(|b_elem| a.iter().any(|a_elem| contains(a_elem, b_elem, false))),
2494            (Datum::Map(a), Datum::Map(b)) => b.iter().all(|(b_key, b_val)| {
2495                a.iter()
2496                    .any(|(a_key, a_val)| (a_key == b_key) && contains(a_val, b_val, false))
2497            }),
2498
2499            // fun special case
2500            (Datum::List(a), b) => {
2501                at_top_level && a.iter().any(|a_elem| contains(a_elem, b, false))
2502            }
2503
2504            _ => false,
2505        }
2506    }
2507    contains(a, b, true).into()
2508}
2509
2510fn jsonb_concat<'a>(a: Datum<'a>, b: Datum<'a>, temp_storage: &'a RowArena) -> Datum<'a> {
2511    match (a, b) {
2512        (Datum::Map(dict_a), Datum::Map(dict_b)) => {
2513            let mut pairs = dict_b.iter().chain(dict_a.iter()).collect::<Vec<_>>();
2514            // stable sort, so if keys collide dedup prefers dict_b
2515            pairs.sort_by(|(k1, _v1), (k2, _v2)| k1.cmp(k2));
2516            pairs.dedup_by(|(k1, _v1), (k2, _v2)| k1 == k2);
2517            temp_storage.make_datum(|packer| packer.push_dict(pairs))
2518        }
2519        (Datum::List(list_a), Datum::List(list_b)) => {
2520            let elems = list_a.iter().chain(list_b.iter());
2521            temp_storage.make_datum(|packer| packer.push_list(elems))
2522        }
2523        (Datum::List(list_a), b) => {
2524            let elems = list_a.iter().chain(Some(b));
2525            temp_storage.make_datum(|packer| packer.push_list(elems))
2526        }
2527        (a, Datum::List(list_b)) => {
2528            let elems = Some(a).into_iter().chain(list_b.iter());
2529            temp_storage.make_datum(|packer| packer.push_list(elems))
2530        }
2531        _ => Datum::Null,
2532    }
2533}
2534
2535fn jsonb_delete_int64<'a>(a: Datum<'a>, b: Datum<'a>, temp_storage: &'a RowArena) -> Datum<'a> {
2536    let i = b.unwrap_int64();
2537    match a {
2538        Datum::List(list) => {
2539            let i = if i >= 0 {
2540                usize::cast_from(i.unsigned_abs())
2541            } else {
2542                // index backwards from the end
2543                let i = usize::cast_from(i.unsigned_abs());
2544                (list.iter().count()).wrapping_sub(i)
2545            };
2546            let elems = list
2547                .iter()
2548                .enumerate()
2549                .filter(|(i2, _e)| i != *i2)
2550                .map(|(_, e)| e);
2551            temp_storage.make_datum(|packer| packer.push_list(elems))
2552        }
2553        _ => Datum::Null,
2554    }
2555}
2556
2557fn jsonb_delete_string<'a>(a: Datum<'a>, b: Datum<'a>, temp_storage: &'a RowArena) -> Datum<'a> {
2558    match a {
2559        Datum::List(list) => {
2560            let elems = list.iter().filter(|e| b != *e);
2561            temp_storage.make_datum(|packer| packer.push_list(elems))
2562        }
2563        Datum::Map(dict) => {
2564            let k = b.unwrap_str();
2565            let pairs = dict.iter().filter(|(k2, _v)| k != *k2);
2566            temp_storage.make_datum(|packer| packer.push_dict(pairs))
2567        }
2568        _ => Datum::Null,
2569    }
2570}
2571
2572fn date_part_interval<'a, D>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError>
2573where
2574    D: DecimalLike + Into<Datum<'static>>,
2575{
2576    let units = a.unwrap_str();
2577    match units.parse() {
2578        Ok(units) => Ok(date_part_interval_inner::<D>(units, b.unwrap_interval())?.into()),
2579        Err(_) => Err(EvalError::UnknownUnits(units.into())),
2580    }
2581}
2582
2583fn date_part_time<'a, D>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError>
2584where
2585    D: DecimalLike + Into<Datum<'a>>,
2586{
2587    let units = a.unwrap_str();
2588    match units.parse() {
2589        Ok(units) => Ok(date_part_time_inner::<D>(units, b.unwrap_time())?.into()),
2590        Err(_) => Err(EvalError::UnknownUnits(units.into())),
2591    }
2592}
2593
2594fn date_part_timestamp<'a, T, D>(a: Datum<'a>, ts: &T) -> Result<Datum<'a>, EvalError>
2595where
2596    T: TimestampLike,
2597    D: DecimalLike + Into<Datum<'a>>,
2598{
2599    let units = a.unwrap_str();
2600    match units.parse() {
2601        Ok(units) => Ok(date_part_timestamp_inner::<_, D>(units, ts)?.into()),
2602        Err(_) => Err(EvalError::UnknownUnits(units.into())),
2603    }
2604}
2605
2606#[sqlfunc(
2607    is_monotone = "(false, false)",
2608    output_type = "Numeric",
2609    is_infix_op = false,
2610    sqlname = "extractd",
2611    propagates_nulls = true
2612)]
2613fn extract_date_units<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
2614    let units = a.unwrap_str();
2615    match units.parse() {
2616        Ok(units) => Ok(extract_date_inner(units, b.unwrap_date().into())?.into()),
2617        Err(_) => Err(EvalError::UnknownUnits(units.into())),
2618    }
2619}
2620
2621pub fn date_bin<'a, T>(
2622    stride: Interval,
2623    source: CheckedTimestamp<T>,
2624    origin: CheckedTimestamp<T>,
2625) -> Result<Datum<'a>, EvalError>
2626where
2627    T: TimestampLike,
2628{
2629    if stride.months != 0 {
2630        return Err(EvalError::DateBinOutOfRange(
2631            "timestamps cannot be binned into intervals containing months or years".into(),
2632        ));
2633    }
2634
2635    let stride_ns = match stride.duration_as_chrono().num_nanoseconds() {
2636        Some(ns) if ns <= 0 => Err(EvalError::DateBinOutOfRange(
2637            "stride must be greater than zero".into(),
2638        )),
2639        Some(ns) => Ok(ns),
2640        None => Err(EvalError::DateBinOutOfRange(
2641            format!("stride cannot exceed {}/{} nanoseconds", i64::MAX, i64::MIN,).into(),
2642        )),
2643    }?;
2644
2645    // Make sure the returned timestamp is at the start of the bin, even if the
2646    // origin is in the future. We do this here because `T` is not `Copy` and
2647    // gets moved by its subtraction operation.
2648    let sub_stride = origin > source;
2649
2650    let tm_diff = (source - origin.clone()).num_nanoseconds().ok_or_else(|| {
2651        EvalError::DateBinOutOfRange(
2652            "source and origin must not differ more than 2^63 nanoseconds".into(),
2653        )
2654    })?;
2655
2656    let mut tm_delta = tm_diff - tm_diff % stride_ns;
2657
2658    if sub_stride {
2659        tm_delta -= stride_ns;
2660    }
2661
2662    let res = origin
2663        .checked_add_signed(Duration::nanoseconds(tm_delta))
2664        .ok_or(EvalError::TimestampOutOfRange)?;
2665    Ok(res.try_into()?)
2666}
2667
2668fn date_trunc<'a, T>(a: Datum<'a>, ts: &T) -> Result<Datum<'a>, EvalError>
2669where
2670    T: TimestampLike,
2671{
2672    let units = a.unwrap_str();
2673    match units.parse() {
2674        Ok(units) => Ok(date_trunc_inner(units, ts)?.try_into()?),
2675        Err(_) => Err(EvalError::UnknownUnits(units.into())),
2676    }
2677}
2678
2679#[sqlfunc(
2680    is_monotone = "(false, false)",
2681    output_type = "Interval",
2682    is_infix_op = false,
2683    sqlname = "date_trunciv",
2684    propagates_nulls = true
2685)]
2686fn date_trunc_interval<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
2687    let mut interval = b.unwrap_interval();
2688    let units = a.unwrap_str();
2689    let dtf = units
2690        .parse()
2691        .map_err(|_| EvalError::UnknownUnits(units.into()))?;
2692
2693    interval
2694        .truncate_low_fields(dtf, Some(0), RoundBehavior::Truncate)
2695        .expect(
2696            "truncate_low_fields should not fail with max_precision 0 and RoundBehavior::Truncate",
2697        );
2698    Ok(interval.into())
2699}
2700
2701fn date_diff_timestamp<'a>(unit: Datum, a: Datum, b: Datum) -> Result<Datum<'a>, EvalError> {
2702    let unit = unit.unwrap_str();
2703    let unit = unit
2704        .parse()
2705        .map_err(|_| EvalError::InvalidDatePart(unit.into()))?;
2706
2707    let a = a.unwrap_timestamp();
2708    let b = b.unwrap_timestamp();
2709    let diff = b.diff_as(&a, unit)?;
2710
2711    Ok(Datum::Int64(diff))
2712}
2713
2714fn date_diff_timestamptz<'a>(unit: Datum, a: Datum, b: Datum) -> Result<Datum<'a>, EvalError> {
2715    let unit = unit.unwrap_str();
2716    let unit = unit
2717        .parse()
2718        .map_err(|_| EvalError::InvalidDatePart(unit.into()))?;
2719
2720    let a = a.unwrap_timestamptz();
2721    let b = b.unwrap_timestamptz();
2722    let diff = b.diff_as(&a, unit)?;
2723
2724    Ok(Datum::Int64(diff))
2725}
2726
2727fn date_diff_date<'a>(unit: Datum, a: Datum, b: Datum) -> Result<Datum<'a>, EvalError> {
2728    let unit = unit.unwrap_str();
2729    let unit = unit
2730        .parse()
2731        .map_err(|_| EvalError::InvalidDatePart(unit.into()))?;
2732
2733    let a = a.unwrap_date();
2734    let b = b.unwrap_date();
2735
2736    // Convert the Date into a timestamp so we can calculate age.
2737    let a_ts = CheckedTimestamp::try_from(NaiveDate::from(a).and_hms_opt(0, 0, 0).unwrap())?;
2738    let b_ts = CheckedTimestamp::try_from(NaiveDate::from(b).and_hms_opt(0, 0, 0).unwrap())?;
2739    let diff = b_ts.diff_as(&a_ts, unit)?;
2740
2741    Ok(Datum::Int64(diff))
2742}
2743
2744fn date_diff_time<'a>(unit: Datum, a: Datum, b: Datum) -> Result<Datum<'a>, EvalError> {
2745    let unit = unit.unwrap_str();
2746    let unit = unit
2747        .parse()
2748        .map_err(|_| EvalError::InvalidDatePart(unit.into()))?;
2749
2750    let a = a.unwrap_time();
2751    let b = b.unwrap_time();
2752
2753    // Convert the Time into a timestamp so we can calculate age.
2754    let a_ts =
2755        CheckedTimestamp::try_from(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap().and_time(a))?;
2756    let b_ts =
2757        CheckedTimestamp::try_from(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap().and_time(b))?;
2758    let diff = b_ts.diff_as(&a_ts, unit)?;
2759
2760    Ok(Datum::Int64(diff))
2761}
2762
2763/// Parses a named timezone like `EST` or `America/New_York`, or a fixed-offset timezone like `-05:00`.
2764///
2765/// The interpretation of fixed offsets depend on whether the POSIX or ISO 8601 standard is being
2766/// used.
2767pub(crate) fn parse_timezone(tz: &str, spec: TimezoneSpec) -> Result<Timezone, EvalError> {
2768    Timezone::parse(tz, spec).map_err(|_| EvalError::InvalidTimezone(tz.into()))
2769}
2770
2771/// Converts the time datum `b`, which is assumed to be in UTC, to the timezone that the interval datum `a` is assumed
2772/// to represent. The interval is not allowed to hold months, but there are no limits on the amount of seconds.
2773/// The interval acts like a `chrono::FixedOffset`, without the `-86,400 < x < 86,400` limitation.
2774fn timezone_interval_time(a: Datum<'_>, b: Datum<'_>) -> Result<Datum<'static>, EvalError> {
2775    let interval = a.unwrap_interval();
2776    if interval.months != 0 {
2777        Err(EvalError::InvalidTimezoneInterval)
2778    } else {
2779        Ok(b.unwrap_time()
2780            .overflowing_add_signed(interval.duration_as_chrono())
2781            .0
2782            .into())
2783    }
2784}
2785
2786/// Converts the timestamp datum `b`, which is assumed to be in the time of the timezone datum `a` to a timestamptz
2787/// in UTC. The interval is not allowed to hold months, but there are no limits on the amount of seconds.
2788/// The interval acts like a `chrono::FixedOffset`, without the `-86,400 < x < 86,400` limitation.
2789fn timezone_interval_timestamp(a: Datum<'_>, b: Datum<'_>) -> Result<Datum<'static>, EvalError> {
2790    let interval = a.unwrap_interval();
2791    if interval.months != 0 {
2792        Err(EvalError::InvalidTimezoneInterval)
2793    } else {
2794        match b
2795            .unwrap_timestamp()
2796            .checked_sub_signed(interval.duration_as_chrono())
2797        {
2798            Some(sub) => Ok(DateTime::from_naive_utc_and_offset(sub, Utc).try_into()?),
2799            None => Err(EvalError::TimestampOutOfRange),
2800        }
2801    }
2802}
2803
2804/// Converts the UTC timestamptz datum `b`, to the local timestamp of the timezone datum `a`.
2805/// The interval is not allowed to hold months, but there are no limits on the amount of seconds.
2806/// The interval acts like a `chrono::FixedOffset`, without the `-86,400 < x < 86,400` limitation.
2807fn timezone_interval_timestamptz(a: Datum<'_>, b: Datum<'_>) -> Result<Datum<'static>, EvalError> {
2808    let interval = a.unwrap_interval();
2809    if interval.months != 0 {
2810        return Err(EvalError::InvalidTimezoneInterval);
2811    }
2812    match b
2813        .unwrap_timestamptz()
2814        .naive_utc()
2815        .checked_add_signed(interval.duration_as_chrono())
2816    {
2817        Some(dt) => Ok(dt.try_into()?),
2818        None => Err(EvalError::TimestampOutOfRange),
2819    }
2820}
2821
2822fn timezone_offset<'a>(
2823    a: Datum<'a>,
2824    b: Datum<'a>,
2825    temp_storage: &'a RowArena,
2826) -> Result<Datum<'a>, EvalError> {
2827    let tz_str = a.unwrap_str();
2828    let tz = match Tz::from_str_insensitive(tz_str) {
2829        Ok(tz) => tz,
2830        Err(_) => return Err(EvalError::InvalidIanaTimezoneId(tz_str.into())),
2831    };
2832    let offset = tz.offset_from_utc_datetime(&b.unwrap_timestamptz().naive_utc());
2833    Ok(temp_storage.make_datum(|packer| {
2834        packer.push_list_with(|packer| {
2835            packer.push(Datum::from(offset.abbreviation()));
2836            packer.push(Datum::from(offset.base_utc_offset()));
2837            packer.push(Datum::from(offset.dst_offset()));
2838        });
2839    }))
2840}
2841
2842/// Determines if an mz_aclitem contains one of the specified privileges. This will return true if
2843/// any of the listed privileges are contained in the mz_aclitem.
2844fn mz_acl_item_contains_privilege(a: Datum<'_>, b: Datum<'_>) -> Result<Datum<'static>, EvalError> {
2845    let mz_acl_item = a.unwrap_mz_acl_item();
2846    let privileges = b.unwrap_str();
2847    let acl_mode = AclMode::parse_multiple_privileges(privileges)
2848        .map_err(|e: anyhow::Error| EvalError::InvalidPrivileges(e.to_string().into()))?;
2849    let contains = !mz_acl_item.acl_mode.intersection(acl_mode).is_empty();
2850    Ok(contains.into())
2851}
2852
2853// transliterated from postgres/src/backend/utils/adt/misc.c
2854fn parse_ident<'a>(
2855    a: Datum<'a>,
2856    b: Datum<'a>,
2857    temp_storage: &'a RowArena,
2858) -> Result<Datum<'a>, EvalError> {
2859    fn is_ident_start(c: char) -> bool {
2860        matches!(c, 'A'..='Z' | 'a'..='z' | '_' | '\u{80}'..=char::MAX)
2861    }
2862
2863    fn is_ident_cont(c: char) -> bool {
2864        matches!(c, '0'..='9' | '$') || is_ident_start(c)
2865    }
2866
2867    let ident = a.unwrap_str();
2868    let strict = b.unwrap_bool();
2869
2870    let mut elems = vec![];
2871    let buf = &mut LexBuf::new(ident);
2872
2873    let mut after_dot = false;
2874
2875    buf.take_while(|ch| ch.is_ascii_whitespace());
2876
2877    loop {
2878        let mut missing_ident = true;
2879
2880        let c = buf.next();
2881
2882        if c == Some('"') {
2883            let s = buf.take_while(|ch| !matches!(ch, '"'));
2884
2885            if buf.next() != Some('"') {
2886                return Err(EvalError::InvalidIdentifier {
2887                    ident: ident.into(),
2888                    detail: Some("String has unclosed double quotes.".into()),
2889                });
2890            }
2891            elems.push(Datum::String(s));
2892            missing_ident = false;
2893        } else if c.map(is_ident_start).unwrap_or(false) {
2894            buf.prev();
2895            let s = buf.take_while(is_ident_cont);
2896            let s = temp_storage.push_string(s.to_ascii_lowercase());
2897            elems.push(Datum::String(s));
2898            missing_ident = false;
2899        }
2900
2901        if missing_ident {
2902            if c == Some('.') {
2903                return Err(EvalError::InvalidIdentifier {
2904                    ident: ident.into(),
2905                    detail: Some("No valid identifier before \".\".".into()),
2906                });
2907            } else if after_dot {
2908                return Err(EvalError::InvalidIdentifier {
2909                    ident: ident.into(),
2910                    detail: Some("No valid identifier after \".\".".into()),
2911                });
2912            } else {
2913                return Err(EvalError::InvalidIdentifier {
2914                    ident: ident.into(),
2915                    detail: None,
2916                });
2917            }
2918        }
2919
2920        buf.take_while(|ch| ch.is_ascii_whitespace());
2921
2922        match buf.next() {
2923            Some('.') => {
2924                after_dot = true;
2925
2926                buf.take_while(|ch| ch.is_ascii_whitespace());
2927            }
2928            Some(_) if strict => {
2929                return Err(EvalError::InvalidIdentifier {
2930                    ident: ident.into(),
2931                    detail: None,
2932                });
2933            }
2934            _ => break,
2935        }
2936    }
2937
2938    Ok(temp_storage.try_make_datum(|packer| {
2939        packer.try_push_array(
2940            &[ArrayDimension {
2941                lower_bound: 1,
2942                length: elems.len(),
2943            }],
2944            elems,
2945        )
2946    })?)
2947}
2948
2949fn string_to_array<'a>(
2950    string_datum: Datum<'a>,
2951    delimiter: Datum<'a>,
2952    null_string: Datum<'a>,
2953    temp_storage: &'a RowArena,
2954) -> Result<Datum<'a>, EvalError> {
2955    if string_datum.is_null() {
2956        return Ok(Datum::Null);
2957    }
2958
2959    let string = string_datum.unwrap_str();
2960
2961    if string.is_empty() {
2962        let mut row = Row::default();
2963        let mut packer = row.packer();
2964        packer.try_push_array(&[], std::iter::empty::<Datum>())?;
2965
2966        return Ok(temp_storage.push_unary_row(row));
2967    }
2968
2969    if delimiter.is_null() {
2970        let split_all_chars_delimiter = "";
2971        return string_to_array_impl(string, split_all_chars_delimiter, null_string, temp_storage);
2972    }
2973
2974    let delimiter = delimiter.unwrap_str();
2975
2976    if delimiter.is_empty() {
2977        let mut row = Row::default();
2978        let mut packer = row.packer();
2979        packer.try_push_array(
2980            &[ArrayDimension {
2981                lower_bound: 1,
2982                length: 1,
2983            }],
2984            vec![string].into_iter().map(Datum::String),
2985        )?;
2986
2987        Ok(temp_storage.push_unary_row(row))
2988    } else {
2989        string_to_array_impl(string, delimiter, null_string, temp_storage)
2990    }
2991}
2992
2993fn string_to_array_impl<'a>(
2994    string: &str,
2995    delimiter: &str,
2996    null_string: Datum<'a>,
2997    temp_storage: &'a RowArena,
2998) -> Result<Datum<'a>, EvalError> {
2999    let mut row = Row::default();
3000    let mut packer = row.packer();
3001
3002    let result = string.split(delimiter);
3003    let found: Vec<&str> = if delimiter.is_empty() {
3004        result.filter(|s| !s.is_empty()).collect()
3005    } else {
3006        result.collect()
3007    };
3008    let array_dimensions = [ArrayDimension {
3009        lower_bound: 1,
3010        length: found.len(),
3011    }];
3012
3013    if null_string.is_null() {
3014        packer.try_push_array(&array_dimensions, found.into_iter().map(Datum::String))?;
3015    } else {
3016        let null_string = null_string.unwrap_str();
3017        let found_datums = found.into_iter().map(|chunk| {
3018            if chunk.eq(null_string) {
3019                Datum::Null
3020            } else {
3021                Datum::String(chunk)
3022            }
3023        });
3024
3025        packer.try_push_array(&array_dimensions, found_datums)?;
3026    }
3027
3028    Ok(temp_storage.push_unary_row(row))
3029}
3030
3031fn regexp_split_to_array<'a>(
3032    text: Datum<'a>,
3033    regexp: Datum<'a>,
3034    flags: Datum<'a>,
3035    temp_storage: &'a RowArena,
3036) -> Result<Datum<'a>, EvalError> {
3037    let text = text.unwrap_str();
3038    let regexp = regexp.unwrap_str();
3039    let flags = flags.unwrap_str();
3040    let regexp = build_regex(regexp, flags)?;
3041    regexp_split_to_array_re(text, &regexp, temp_storage)
3042}
3043
3044fn regexp_split_to_array_re<'a>(
3045    text: &str,
3046    regexp: &Regex,
3047    temp_storage: &'a RowArena,
3048) -> Result<Datum<'a>, EvalError> {
3049    let found = mz_regexp::regexp_split_to_array(text, regexp);
3050    let mut row = Row::default();
3051    let mut packer = row.packer();
3052    packer.try_push_array(
3053        &[ArrayDimension {
3054            lower_bound: 1,
3055            length: found.len(),
3056        }],
3057        found.into_iter().map(Datum::String),
3058    )?;
3059    Ok(temp_storage.push_unary_row(row))
3060}
3061
3062fn pretty_sql<'a>(
3063    sql: Datum<'a>,
3064    width: Datum<'a>,
3065    temp_storage: &'a RowArena,
3066) -> Result<Datum<'a>, EvalError> {
3067    let sql = sql.unwrap_str();
3068    let width = width.unwrap_int32();
3069    let width =
3070        usize::try_from(width).map_err(|_| EvalError::PrettyError("invalid width".into()))?;
3071    let pretty = pretty_str(
3072        sql,
3073        PrettyConfig {
3074            width,
3075            format_mode: FormatMode::Simple,
3076        },
3077    )
3078    .map_err(|e| EvalError::PrettyError(e.to_string().into()))?;
3079    let pretty = temp_storage.push_string(pretty);
3080    Ok(Datum::String(pretty))
3081}
3082
3083fn starts_with<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
3084    let a = a.unwrap_str();
3085    let b = b.unwrap_str();
3086    Datum::from(a.starts_with(b))
3087}
3088
3089#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
3090pub enum BinaryFunc {
3091    AddInt16,
3092    AddInt32,
3093    AddInt64,
3094    AddUInt16,
3095    AddUInt32,
3096    AddUInt64,
3097    AddFloat32,
3098    AddFloat64,
3099    AddInterval,
3100    AddTimestampInterval,
3101    AddTimestampTzInterval,
3102    AddDateInterval,
3103    AddDateTime,
3104    AddTimeInterval,
3105    AddNumeric,
3106    AgeTimestamp,
3107    AgeTimestampTz,
3108    BitAndInt16,
3109    BitAndInt32,
3110    BitAndInt64,
3111    BitAndUInt16,
3112    BitAndUInt32,
3113    BitAndUInt64,
3114    BitOrInt16,
3115    BitOrInt32,
3116    BitOrInt64,
3117    BitOrUInt16,
3118    BitOrUInt32,
3119    BitOrUInt64,
3120    BitXorInt16,
3121    BitXorInt32,
3122    BitXorInt64,
3123    BitXorUInt16,
3124    BitXorUInt32,
3125    BitXorUInt64,
3126    BitShiftLeftInt16,
3127    BitShiftLeftInt32,
3128    BitShiftLeftInt64,
3129    BitShiftLeftUInt16,
3130    BitShiftLeftUInt32,
3131    BitShiftLeftUInt64,
3132    BitShiftRightInt16,
3133    BitShiftRightInt32,
3134    BitShiftRightInt64,
3135    BitShiftRightUInt16,
3136    BitShiftRightUInt32,
3137    BitShiftRightUInt64,
3138    SubInt16,
3139    SubInt32,
3140    SubInt64,
3141    SubUInt16,
3142    SubUInt32,
3143    SubUInt64,
3144    SubFloat32,
3145    SubFloat64,
3146    SubInterval,
3147    SubTimestamp,
3148    SubTimestampTz,
3149    SubTimestampInterval,
3150    SubTimestampTzInterval,
3151    SubDate,
3152    SubDateInterval,
3153    SubTime,
3154    SubTimeInterval,
3155    SubNumeric,
3156    MulInt16,
3157    MulInt32,
3158    MulInt64,
3159    MulUInt16,
3160    MulUInt32,
3161    MulUInt64,
3162    MulFloat32,
3163    MulFloat64,
3164    MulNumeric,
3165    MulInterval,
3166    DivInt16,
3167    DivInt32,
3168    DivInt64,
3169    DivUInt16,
3170    DivUInt32,
3171    DivUInt64,
3172    DivFloat32,
3173    DivFloat64,
3174    DivNumeric,
3175    DivInterval,
3176    ModInt16,
3177    ModInt32,
3178    ModInt64,
3179    ModUInt16,
3180    ModUInt32,
3181    ModUInt64,
3182    ModFloat32,
3183    ModFloat64,
3184    ModNumeric,
3185    RoundNumeric,
3186    Eq,
3187    NotEq,
3188    Lt,
3189    Lte,
3190    Gt,
3191    Gte,
3192    LikeEscape,
3193    IsLikeMatch { case_insensitive: bool },
3194    IsRegexpMatch { case_insensitive: bool },
3195    ToCharTimestamp,
3196    ToCharTimestampTz,
3197    DateBinTimestamp,
3198    DateBinTimestampTz,
3199    ExtractInterval,
3200    ExtractTime,
3201    ExtractTimestamp,
3202    ExtractTimestampTz,
3203    ExtractDate,
3204    DatePartInterval,
3205    DatePartTime,
3206    DatePartTimestamp,
3207    DatePartTimestampTz,
3208    DateTruncTimestamp,
3209    DateTruncTimestampTz,
3210    DateTruncInterval,
3211    TimezoneTimestamp,
3212    TimezoneTimestampTz,
3213    TimezoneIntervalTimestamp,
3214    TimezoneIntervalTimestampTz,
3215    TimezoneIntervalTime,
3216    TimezoneOffset,
3217    TextConcat,
3218    JsonbGetInt64,
3219    JsonbGetInt64Stringify,
3220    JsonbGetString,
3221    JsonbGetStringStringify,
3222    JsonbGetPath,
3223    JsonbGetPathStringify,
3224    JsonbContainsString,
3225    JsonbConcat,
3226    JsonbContainsJsonb,
3227    JsonbDeleteInt64,
3228    JsonbDeleteString,
3229    MapContainsKey,
3230    MapGetValue,
3231    MapContainsAllKeys,
3232    MapContainsAnyKeys,
3233    MapContainsMap,
3234    ConvertFrom,
3235    Left,
3236    Position,
3237    Right,
3238    RepeatString,
3239    Trim,
3240    TrimLeading,
3241    TrimTrailing,
3242    EncodedBytesCharLength,
3243    ListLengthMax { max_layer: usize },
3244    ArrayContains,
3245    ArrayContainsArray { rev: bool },
3246    ArrayLength,
3247    ArrayLower,
3248    ArrayRemove,
3249    ArrayUpper,
3250    ArrayArrayConcat,
3251    ListListConcat,
3252    ListElementConcat,
3253    ElementListConcat,
3254    ListRemove,
3255    ListContainsList { rev: bool },
3256    DigestString,
3257    DigestBytes,
3258    MzRenderTypmod,
3259    Encode,
3260    Decode,
3261    LogNumeric,
3262    Power,
3263    PowerNumeric,
3264    GetBit,
3265    GetByte,
3266    ConstantTimeEqBytes,
3267    ConstantTimeEqString,
3268    RangeContainsElem { elem_type: ScalarType, rev: bool },
3269    RangeContainsRange { rev: bool },
3270    RangeOverlaps,
3271    RangeAfter,
3272    RangeBefore,
3273    RangeOverleft,
3274    RangeOverright,
3275    RangeAdjacent,
3276    RangeUnion,
3277    RangeIntersection,
3278    RangeDifference,
3279    UuidGenerateV5,
3280    MzAclItemContainsPrivilege,
3281    ParseIdent,
3282    PrettySql,
3283    RegexpReplace { regex: Regex, limit: usize },
3284    StartsWith,
3285}
3286
3287impl BinaryFunc {
3288    pub fn eval<'a>(
3289        &'a self,
3290        datums: &[Datum<'a>],
3291        temp_storage: &'a RowArena,
3292        a_expr: &'a MirScalarExpr,
3293        b_expr: &'a MirScalarExpr,
3294    ) -> Result<Datum<'a>, EvalError> {
3295        let a = a_expr.eval(datums, temp_storage)?;
3296        let b = b_expr.eval(datums, temp_storage)?;
3297        if self.propagates_nulls() && (a.is_null() || b.is_null()) {
3298            return Ok(Datum::Null);
3299        }
3300        match self {
3301            BinaryFunc::AddInt16 => add_int16(a, b),
3302            BinaryFunc::AddInt32 => add_int32(a, b),
3303            BinaryFunc::AddInt64 => add_int64(a, b),
3304            BinaryFunc::AddUInt16 => add_uint16(a, b),
3305            BinaryFunc::AddUInt32 => add_uint32(a, b),
3306            BinaryFunc::AddUInt64 => add_uint64(a, b),
3307            BinaryFunc::AddFloat32 => add_float32(a, b),
3308            BinaryFunc::AddFloat64 => add_float64(a, b),
3309            BinaryFunc::AddTimestampInterval => {
3310                add_timestamplike_interval(a.unwrap_timestamp(), b.unwrap_interval())
3311            }
3312            BinaryFunc::AddTimestampTzInterval => {
3313                add_timestamplike_interval(a.unwrap_timestamptz(), b.unwrap_interval())
3314            }
3315            BinaryFunc::AddDateTime => add_date_time(a, b),
3316            BinaryFunc::AddDateInterval => add_date_interval(a, b),
3317            BinaryFunc::AddTimeInterval => Ok(add_time_interval(a, b)),
3318            BinaryFunc::AddNumeric => add_numeric(a, b),
3319            BinaryFunc::AddInterval => add_interval(a, b),
3320            BinaryFunc::AgeTimestamp => age_timestamp(a, b),
3321            BinaryFunc::AgeTimestampTz => age_timestamptz(a, b),
3322            BinaryFunc::BitAndInt16 => Ok(bit_and_int16(a, b)),
3323            BinaryFunc::BitAndInt32 => Ok(bit_and_int32(a, b)),
3324            BinaryFunc::BitAndInt64 => Ok(bit_and_int64(a, b)),
3325            BinaryFunc::BitAndUInt16 => Ok(bit_and_uint16(a, b)),
3326            BinaryFunc::BitAndUInt32 => Ok(bit_and_uint32(a, b)),
3327            BinaryFunc::BitAndUInt64 => Ok(bit_and_uint64(a, b)),
3328            BinaryFunc::BitOrInt16 => Ok(bit_or_int16(a, b)),
3329            BinaryFunc::BitOrInt32 => Ok(bit_or_int32(a, b)),
3330            BinaryFunc::BitOrInt64 => Ok(bit_or_int64(a, b)),
3331            BinaryFunc::BitOrUInt16 => Ok(bit_or_uint16(a, b)),
3332            BinaryFunc::BitOrUInt32 => Ok(bit_or_uint32(a, b)),
3333            BinaryFunc::BitOrUInt64 => Ok(bit_or_uint64(a, b)),
3334            BinaryFunc::BitXorInt16 => Ok(bit_xor_int16(a, b)),
3335            BinaryFunc::BitXorInt32 => Ok(bit_xor_int32(a, b)),
3336            BinaryFunc::BitXorInt64 => Ok(bit_xor_int64(a, b)),
3337            BinaryFunc::BitXorUInt16 => Ok(bit_xor_uint16(a, b)),
3338            BinaryFunc::BitXorUInt32 => Ok(bit_xor_uint32(a, b)),
3339            BinaryFunc::BitXorUInt64 => Ok(bit_xor_uint64(a, b)),
3340            BinaryFunc::BitShiftLeftInt16 => Ok(bit_shift_left_int16(a, b)),
3341            BinaryFunc::BitShiftLeftInt32 => Ok(bit_shift_left_int32(a, b)),
3342            BinaryFunc::BitShiftLeftInt64 => Ok(bit_shift_left_int64(a, b)),
3343            BinaryFunc::BitShiftLeftUInt16 => Ok(bit_shift_left_uint16(a, b)),
3344            BinaryFunc::BitShiftLeftUInt32 => Ok(bit_shift_left_uint32(a, b)),
3345            BinaryFunc::BitShiftLeftUInt64 => Ok(bit_shift_left_uint64(a, b)),
3346            BinaryFunc::BitShiftRightInt16 => Ok(bit_shift_right_int16(a, b)),
3347            BinaryFunc::BitShiftRightInt32 => Ok(bit_shift_right_int32(a, b)),
3348            BinaryFunc::BitShiftRightInt64 => Ok(bit_shift_right_int64(a, b)),
3349            BinaryFunc::BitShiftRightUInt16 => Ok(bit_shift_right_uint16(a, b)),
3350            BinaryFunc::BitShiftRightUInt32 => Ok(bit_shift_right_uint32(a, b)),
3351            BinaryFunc::BitShiftRightUInt64 => Ok(bit_shift_right_uint64(a, b)),
3352            BinaryFunc::SubInt16 => sub_int16(a, b),
3353            BinaryFunc::SubInt32 => sub_int32(a, b),
3354            BinaryFunc::SubInt64 => sub_int64(a, b),
3355            BinaryFunc::SubUInt16 => sub_uint16(a, b),
3356            BinaryFunc::SubUInt32 => sub_uint32(a, b),
3357            BinaryFunc::SubUInt64 => sub_uint64(a, b),
3358            BinaryFunc::SubFloat32 => sub_float32(a, b),
3359            BinaryFunc::SubFloat64 => sub_float64(a, b),
3360            BinaryFunc::SubTimestamp => Ok(sub_timestamp(a, b)),
3361            BinaryFunc::SubTimestampTz => Ok(sub_timestamptz(a, b)),
3362            BinaryFunc::SubTimestampInterval => sub_timestamplike_interval(a.unwrap_timestamp(), b),
3363            BinaryFunc::SubTimestampTzInterval => {
3364                sub_timestamplike_interval(a.unwrap_timestamptz(), b)
3365            }
3366            BinaryFunc::SubInterval => sub_interval(a, b),
3367            BinaryFunc::SubDate => Ok(sub_date(a, b)),
3368            BinaryFunc::SubDateInterval => sub_date_interval(a, b),
3369            BinaryFunc::SubTime => Ok(sub_time(a, b)),
3370            BinaryFunc::SubTimeInterval => Ok(sub_time_interval(a, b)),
3371            BinaryFunc::SubNumeric => sub_numeric(a, b),
3372            BinaryFunc::MulInt16 => mul_int16(a, b),
3373            BinaryFunc::MulInt32 => mul_int32(a, b),
3374            BinaryFunc::MulInt64 => mul_int64(a, b),
3375            BinaryFunc::MulUInt16 => mul_uint16(a, b),
3376            BinaryFunc::MulUInt32 => mul_uint32(a, b),
3377            BinaryFunc::MulUInt64 => mul_uint64(a, b),
3378            BinaryFunc::MulFloat32 => mul_float32(a, b),
3379            BinaryFunc::MulFloat64 => mul_float64(a, b),
3380            BinaryFunc::MulNumeric => mul_numeric(a, b),
3381            BinaryFunc::MulInterval => mul_interval(a, b),
3382            BinaryFunc::DivInt16 => div_int16(a, b),
3383            BinaryFunc::DivInt32 => div_int32(a, b),
3384            BinaryFunc::DivInt64 => div_int64(a, b),
3385            BinaryFunc::DivUInt16 => div_uint16(a, b),
3386            BinaryFunc::DivUInt32 => div_uint32(a, b),
3387            BinaryFunc::DivUInt64 => div_uint64(a, b),
3388            BinaryFunc::DivFloat32 => div_float32(a, b),
3389            BinaryFunc::DivFloat64 => div_float64(a, b),
3390            BinaryFunc::DivNumeric => div_numeric(a, b),
3391            BinaryFunc::DivInterval => div_interval(a, b),
3392            BinaryFunc::ModInt16 => mod_int16(a, b),
3393            BinaryFunc::ModInt32 => mod_int32(a, b),
3394            BinaryFunc::ModInt64 => mod_int64(a, b),
3395            BinaryFunc::ModUInt16 => mod_uint16(a, b),
3396            BinaryFunc::ModUInt32 => mod_uint32(a, b),
3397            BinaryFunc::ModUInt64 => mod_uint64(a, b),
3398            BinaryFunc::ModFloat32 => mod_float32(a, b),
3399            BinaryFunc::ModFloat64 => mod_float64(a, b),
3400            BinaryFunc::ModNumeric => mod_numeric(a, b),
3401            BinaryFunc::Eq => Ok(eq(a, b)),
3402            BinaryFunc::NotEq => Ok(not_eq(a, b)),
3403            BinaryFunc::Lt => Ok(lt(a, b)),
3404            BinaryFunc::Lte => Ok(lte(a, b)),
3405            BinaryFunc::Gt => Ok(gt(a, b)),
3406            BinaryFunc::Gte => Ok(gte(a, b)),
3407            BinaryFunc::LikeEscape => like_escape(a, b, temp_storage),
3408            BinaryFunc::IsLikeMatch { case_insensitive } => {
3409                is_like_match_dynamic(a, b, *case_insensitive)
3410            }
3411            BinaryFunc::IsRegexpMatch { case_insensitive } => {
3412                is_regexp_match_dynamic(a, b, *case_insensitive)
3413            }
3414            BinaryFunc::ToCharTimestamp => Ok(to_char_timestamplike(
3415                a.unwrap_timestamp().deref(),
3416                b.unwrap_str(),
3417                temp_storage,
3418            )),
3419            BinaryFunc::ToCharTimestampTz => Ok(to_char_timestamplike(
3420                a.unwrap_timestamptz().deref(),
3421                b.unwrap_str(),
3422                temp_storage,
3423            )),
3424            BinaryFunc::DateBinTimestamp => date_bin(
3425                a.unwrap_interval(),
3426                b.unwrap_timestamp(),
3427                CheckedTimestamp::from_timestamplike(
3428                    DateTime::from_timestamp(0, 0).unwrap().naive_utc(),
3429                )
3430                .expect("must fit"),
3431            ),
3432            BinaryFunc::DateBinTimestampTz => date_bin(
3433                a.unwrap_interval(),
3434                b.unwrap_timestamptz(),
3435                CheckedTimestamp::from_timestamplike(DateTime::from_timestamp(0, 0).unwrap())
3436                    .expect("must fit"),
3437            ),
3438            BinaryFunc::ExtractInterval => date_part_interval::<Numeric>(a, b),
3439            BinaryFunc::ExtractTime => date_part_time::<Numeric>(a, b),
3440            BinaryFunc::ExtractTimestamp => {
3441                date_part_timestamp::<_, Numeric>(a, b.unwrap_timestamp().deref())
3442            }
3443            BinaryFunc::ExtractTimestampTz => {
3444                date_part_timestamp::<_, Numeric>(a, b.unwrap_timestamptz().deref())
3445            }
3446            BinaryFunc::ExtractDate => extract_date_units(a, b),
3447            BinaryFunc::DatePartInterval => date_part_interval::<f64>(a, b),
3448            BinaryFunc::DatePartTime => date_part_time::<f64>(a, b),
3449            BinaryFunc::DatePartTimestamp => {
3450                date_part_timestamp::<_, f64>(a, b.unwrap_timestamp().deref())
3451            }
3452            BinaryFunc::DatePartTimestampTz => {
3453                date_part_timestamp::<_, f64>(a, b.unwrap_timestamptz().deref())
3454            }
3455            BinaryFunc::DateTruncTimestamp => date_trunc(a, b.unwrap_timestamp().deref()),
3456            BinaryFunc::DateTruncInterval => date_trunc_interval(a, b),
3457            BinaryFunc::DateTruncTimestampTz => date_trunc(a, b.unwrap_timestamptz().deref()),
3458            BinaryFunc::TimezoneTimestamp => parse_timezone(a.unwrap_str(), TimezoneSpec::Posix)
3459                .and_then(|tz| timezone_timestamp(tz, b.unwrap_timestamp().into()).map(Into::into)),
3460            BinaryFunc::TimezoneTimestampTz => parse_timezone(a.unwrap_str(), TimezoneSpec::Posix)
3461                .and_then(|tz| {
3462                    Ok(timezone_timestamptz(tz, b.unwrap_timestamptz().into())?.try_into()?)
3463                }),
3464            BinaryFunc::TimezoneIntervalTimestamp => timezone_interval_timestamp(a, b),
3465            BinaryFunc::TimezoneIntervalTimestampTz => timezone_interval_timestamptz(a, b),
3466            BinaryFunc::TimezoneIntervalTime => timezone_interval_time(a, b),
3467            BinaryFunc::TimezoneOffset => timezone_offset(a, b, temp_storage),
3468            BinaryFunc::TextConcat => Ok(text_concat_binary(a, b, temp_storage)),
3469            BinaryFunc::JsonbGetInt64 => Ok(jsonb_get_int64(a, b, temp_storage, false)),
3470            BinaryFunc::JsonbGetInt64Stringify => Ok(jsonb_get_int64(a, b, temp_storage, true)),
3471            BinaryFunc::JsonbGetString => Ok(jsonb_get_string(a, b, temp_storage, false)),
3472            BinaryFunc::JsonbGetStringStringify => Ok(jsonb_get_string(a, b, temp_storage, true)),
3473            BinaryFunc::JsonbGetPath => Ok(jsonb_get_path(a, b, temp_storage, false)),
3474            BinaryFunc::JsonbGetPathStringify => Ok(jsonb_get_path(a, b, temp_storage, true)),
3475            BinaryFunc::JsonbContainsString => Ok(jsonb_contains_string(a, b)),
3476            BinaryFunc::JsonbConcat => Ok(jsonb_concat(a, b, temp_storage)),
3477            BinaryFunc::JsonbContainsJsonb => Ok(jsonb_contains_jsonb(a, b)),
3478            BinaryFunc::JsonbDeleteInt64 => Ok(jsonb_delete_int64(a, b, temp_storage)),
3479            BinaryFunc::JsonbDeleteString => Ok(jsonb_delete_string(a, b, temp_storage)),
3480            BinaryFunc::MapContainsKey => Ok(map_contains_key(a, b)),
3481            BinaryFunc::MapGetValue => Ok(map_get_value(a, b)),
3482            BinaryFunc::MapContainsAllKeys => Ok(map_contains_all_keys(a, b)),
3483            BinaryFunc::MapContainsAnyKeys => Ok(map_contains_any_keys(a, b)),
3484            BinaryFunc::MapContainsMap => Ok(map_contains_map(a, b)),
3485            BinaryFunc::RoundNumeric => round_numeric_binary(a, b),
3486            BinaryFunc::ConvertFrom => convert_from(a, b),
3487            BinaryFunc::Encode => encode(a, b, temp_storage),
3488            BinaryFunc::Decode => decode(a, b, temp_storage),
3489            BinaryFunc::Left => left(a, b),
3490            BinaryFunc::Position => position(a, b),
3491            BinaryFunc::Right => right(a, b),
3492            BinaryFunc::Trim => Ok(trim(a, b)),
3493            BinaryFunc::TrimLeading => Ok(trim_leading(a, b)),
3494            BinaryFunc::TrimTrailing => Ok(trim_trailing(a, b)),
3495            BinaryFunc::EncodedBytesCharLength => encoded_bytes_char_length(a, b),
3496            BinaryFunc::ListLengthMax { max_layer } => list_length_max(a, b, *max_layer),
3497            BinaryFunc::ArrayLength => array_length(a, b),
3498            BinaryFunc::ArrayContains => Ok(array_contains(a, b)),
3499            BinaryFunc::ArrayContainsArray { rev: false } => Ok(array_contains_array(a, b)),
3500            BinaryFunc::ArrayContainsArray { rev: true } => Ok(array_contains_array(b, a)),
3501            BinaryFunc::ArrayLower => Ok(array_lower(a, b)),
3502            BinaryFunc::ArrayRemove => array_remove(a, b, temp_storage),
3503            BinaryFunc::ArrayUpper => array_upper(a, b),
3504            BinaryFunc::ArrayArrayConcat => array_array_concat(a, b, temp_storage),
3505            BinaryFunc::ListListConcat => Ok(list_list_concat(a, b, temp_storage)),
3506            BinaryFunc::ListElementConcat => Ok(list_element_concat(a, b, temp_storage)),
3507            BinaryFunc::ElementListConcat => Ok(element_list_concat(a, b, temp_storage)),
3508            BinaryFunc::ListRemove => Ok(list_remove(a, b, temp_storage)),
3509            BinaryFunc::ListContainsList { rev: false } => Ok(list_contains_list(a, b)),
3510            BinaryFunc::ListContainsList { rev: true } => Ok(list_contains_list(b, a)),
3511            BinaryFunc::DigestString => digest_string(a, b, temp_storage),
3512            BinaryFunc::DigestBytes => digest_bytes(a, b, temp_storage),
3513            BinaryFunc::MzRenderTypmod => mz_render_typmod(a, b, temp_storage),
3514            BinaryFunc::LogNumeric => log_base_numeric(a, b),
3515            BinaryFunc::Power => power(a, b),
3516            BinaryFunc::PowerNumeric => power_numeric(a, b),
3517            BinaryFunc::RepeatString => repeat_string(a, b, temp_storage),
3518            BinaryFunc::GetBit => get_bit(a, b),
3519            BinaryFunc::GetByte => get_byte(a, b),
3520            BinaryFunc::ConstantTimeEqBytes => constant_time_eq_bytes(a, b),
3521            BinaryFunc::ConstantTimeEqString => constant_time_eq_string(a, b),
3522            BinaryFunc::RangeContainsElem { elem_type, rev: _ } => Ok(match elem_type {
3523                ScalarType::Int32 => contains_range_elem::<i32>(a, b),
3524                ScalarType::Int64 => contains_range_elem::<i64>(a, b),
3525                ScalarType::Date => contains_range_elem::<Date>(a, b),
3526                ScalarType::Numeric { .. } => contains_range_elem::<OrderedDecimal<Numeric>>(a, b),
3527                ScalarType::Timestamp { .. } => {
3528                    contains_range_elem::<CheckedTimestamp<NaiveDateTime>>(a, b)
3529                }
3530                ScalarType::TimestampTz { .. } => {
3531                    contains_range_elem::<CheckedTimestamp<DateTime<Utc>>>(a, b)
3532                }
3533                _ => unreachable!(),
3534            }),
3535            BinaryFunc::RangeContainsRange { rev: false } => Ok(range_contains_range(a, b)),
3536            BinaryFunc::RangeContainsRange { rev: true } => Ok(range_contains_range_rev(a, b)),
3537            BinaryFunc::RangeOverlaps => Ok(range_overlaps(a, b)),
3538            BinaryFunc::RangeAfter => Ok(range_after(a, b)),
3539            BinaryFunc::RangeBefore => Ok(range_before(a, b)),
3540            BinaryFunc::RangeOverleft => Ok(range_overleft(a, b)),
3541            BinaryFunc::RangeOverright => Ok(range_overright(a, b)),
3542            BinaryFunc::RangeAdjacent => Ok(range_adjacent(a, b)),
3543            BinaryFunc::RangeUnion => range_union(a, b, temp_storage),
3544            BinaryFunc::RangeIntersection => range_intersection(a, b, temp_storage),
3545            BinaryFunc::RangeDifference => range_difference(a, b, temp_storage),
3546            BinaryFunc::UuidGenerateV5 => Ok(uuid_generate_v5(a, b)),
3547            BinaryFunc::MzAclItemContainsPrivilege => mz_acl_item_contains_privilege(a, b),
3548            BinaryFunc::ParseIdent => parse_ident(a, b, temp_storage),
3549            BinaryFunc::PrettySql => pretty_sql(a, b, temp_storage),
3550            BinaryFunc::RegexpReplace { regex, limit } => {
3551                regexp_replace_static(a, b, regex, *limit, temp_storage)
3552            }
3553            BinaryFunc::StartsWith => Ok(starts_with(a, b)),
3554        }
3555    }
3556
3557    pub fn output_type(&self, input1_type: ColumnType, input2_type: ColumnType) -> ColumnType {
3558        use BinaryFunc::*;
3559        let in_nullable = input1_type.nullable || input2_type.nullable;
3560        match self {
3561            Eq
3562            | NotEq
3563            | Lt
3564            | Lte
3565            | Gt
3566            | Gte
3567            | ArrayContains
3568            | ArrayContainsArray { .. }
3569            // like and regexp produce errors on invalid like-strings or regexes
3570            | IsLikeMatch { .. }
3571            | IsRegexpMatch { .. } => ScalarType::Bool.nullable(in_nullable),
3572
3573            ToCharTimestamp | ToCharTimestampTz | ConvertFrom | Left | Right | Trim
3574            | TrimLeading | TrimTrailing | LikeEscape => ScalarType::String.nullable(in_nullable),
3575
3576            AddInt16 | SubInt16 | MulInt16 | DivInt16 | ModInt16 | BitAndInt16 | BitOrInt16
3577            | BitXorInt16 | BitShiftLeftInt16 | BitShiftRightInt16 => {
3578                ScalarType::Int16.nullable(in_nullable)
3579            }
3580
3581            AddInt32
3582            | SubInt32
3583            | MulInt32
3584            | DivInt32
3585            | ModInt32
3586            | BitAndInt32
3587            | BitOrInt32
3588            | BitXorInt32
3589            | BitShiftLeftInt32
3590            | BitShiftRightInt32
3591            | EncodedBytesCharLength
3592            | SubDate => ScalarType::Int32.nullable(in_nullable),
3593
3594            AddInt64 | SubInt64 | MulInt64 | DivInt64 | ModInt64 | BitAndInt64 | BitOrInt64
3595            | BitXorInt64 | BitShiftLeftInt64 | BitShiftRightInt64 => {
3596                ScalarType::Int64.nullable(in_nullable)
3597            }
3598
3599            AddUInt16 | SubUInt16 | MulUInt16 | DivUInt16 | ModUInt16 | BitAndUInt16
3600            | BitOrUInt16 | BitXorUInt16 | BitShiftLeftUInt16 | BitShiftRightUInt16 => {
3601                ScalarType::UInt16.nullable(in_nullable)
3602            }
3603
3604            AddUInt32 | SubUInt32 | MulUInt32 | DivUInt32 | ModUInt32 | BitAndUInt32
3605            | BitOrUInt32 | BitXorUInt32 | BitShiftLeftUInt32 | BitShiftRightUInt32 => {
3606                ScalarType::UInt32.nullable(in_nullable)
3607            }
3608
3609            AddUInt64 | SubUInt64 | MulUInt64 | DivUInt64 | ModUInt64 | BitAndUInt64
3610            | BitOrUInt64 | BitXorUInt64 | BitShiftLeftUInt64 | BitShiftRightUInt64 => {
3611                ScalarType::UInt64.nullable(in_nullable)
3612            }
3613
3614            AddFloat32 | SubFloat32 | MulFloat32 | DivFloat32 | ModFloat32 => {
3615                ScalarType::Float32.nullable(in_nullable)
3616            }
3617
3618            AddFloat64 | SubFloat64 | MulFloat64 | DivFloat64 | ModFloat64 => {
3619                ScalarType::Float64.nullable(in_nullable)
3620            }
3621
3622            AddInterval | SubInterval | SubTimestamp | SubTimestampTz | MulInterval
3623            | DivInterval => ScalarType::Interval.nullable(in_nullable),
3624
3625            AgeTimestamp | AgeTimestampTz => ScalarType::Interval.nullable(in_nullable),
3626
3627            AddTimestampInterval
3628            | SubTimestampInterval
3629            | AddTimestampTzInterval
3630            | SubTimestampTzInterval
3631            | AddTimeInterval
3632            | SubTimeInterval => input1_type.nullable(in_nullable),
3633
3634            AddDateInterval | SubDateInterval | AddDateTime | DateBinTimestamp
3635            | DateTruncTimestamp => ScalarType::Timestamp { precision: None }.nullable(in_nullable),
3636
3637            DateTruncInterval => ScalarType::Interval.nullable(in_nullable),
3638
3639            TimezoneTimestampTz | TimezoneIntervalTimestampTz => {
3640                ScalarType::Timestamp { precision: None }.nullable(in_nullable)
3641            }
3642
3643            ExtractInterval | ExtractTime | ExtractTimestamp | ExtractTimestampTz | ExtractDate => {
3644                ScalarType::Numeric { max_scale: None }.nullable(in_nullable)
3645            }
3646
3647            DatePartInterval | DatePartTime | DatePartTimestamp | DatePartTimestampTz => {
3648                ScalarType::Float64.nullable(true)
3649            }
3650
3651            DateBinTimestampTz | DateTruncTimestampTz => ScalarType::TimestampTz { precision: None }.nullable(true),
3652
3653            TimezoneTimestamp | TimezoneIntervalTimestamp => {
3654                ScalarType::TimestampTz { precision: None }.nullable(in_nullable)
3655            }
3656
3657            TimezoneIntervalTime => ScalarType::Time.nullable(in_nullable),
3658
3659            TimezoneOffset => ScalarType::Record {
3660                fields: [
3661                    ("abbrev".into(), ScalarType::String.nullable(false)),
3662                    ("base_utc_offset".into(), ScalarType::Interval.nullable(false)),
3663                    ("dst_offset".into(), ScalarType::Interval.nullable(false)),
3664                ].into(),
3665                custom_id: None,
3666            }.nullable(true),
3667
3668            SubTime => ScalarType::Interval.nullable(in_nullable),
3669
3670            MzRenderTypmod | TextConcat => ScalarType::String.nullable(in_nullable),
3671
3672            JsonbGetInt64Stringify
3673            | JsonbGetStringStringify
3674            | JsonbGetPathStringify => ScalarType::String.nullable(true),
3675
3676            JsonbGetInt64
3677            | JsonbGetString
3678            | JsonbGetPath
3679            | JsonbConcat
3680            | JsonbDeleteInt64
3681            | JsonbDeleteString => ScalarType::Jsonb.nullable(true),
3682
3683            JsonbContainsString | JsonbContainsJsonb | MapContainsKey | MapContainsAllKeys
3684            | MapContainsAnyKeys | MapContainsMap => ScalarType::Bool.nullable(in_nullable),
3685
3686            MapGetValue => input1_type
3687                .scalar_type
3688                .unwrap_map_value_type()
3689                .clone()
3690                .nullable(true),
3691
3692            ArrayLength | ArrayLower | ArrayUpper => ScalarType::Int32.nullable(true),
3693
3694            ListLengthMax { .. } => ScalarType::Int32.nullable(true),
3695
3696            ArrayArrayConcat | ArrayRemove | ListListConcat | ListElementConcat | ListRemove => {
3697                input1_type.scalar_type.without_modifiers().nullable(true)
3698            }
3699
3700            ElementListConcat => input2_type.scalar_type.without_modifiers().nullable(true),
3701
3702            ListContainsList { .. } =>  ScalarType::Bool.nullable(in_nullable),
3703
3704            DigestString | DigestBytes => ScalarType::Bytes.nullable(in_nullable),
3705            Position => ScalarType::Int32.nullable(in_nullable),
3706            Encode => ScalarType::String.nullable(in_nullable),
3707            Decode => ScalarType::Bytes.nullable(in_nullable),
3708            Power => ScalarType::Float64.nullable(in_nullable),
3709            RepeatString => input1_type.scalar_type.nullable(in_nullable),
3710
3711            AddNumeric | DivNumeric | LogNumeric | ModNumeric | MulNumeric | PowerNumeric
3712            | RoundNumeric | SubNumeric => {
3713                ScalarType::Numeric { max_scale: None }.nullable(in_nullable)
3714            }
3715
3716            GetBit => ScalarType::Int32.nullable(in_nullable),
3717            GetByte => ScalarType::Int32.nullable(in_nullable),
3718
3719            ConstantTimeEqBytes | ConstantTimeEqString => {
3720                ScalarType::Bool.nullable(in_nullable)
3721            },
3722
3723            UuidGenerateV5 => ScalarType::Uuid.nullable(in_nullable),
3724
3725            RangeContainsElem { .. }
3726            | RangeContainsRange { .. }
3727            | RangeOverlaps
3728            | RangeAfter
3729            | RangeBefore
3730            | RangeOverleft
3731            | RangeOverright
3732            | RangeAdjacent => ScalarType::Bool.nullable(in_nullable),
3733
3734            RangeUnion | RangeIntersection | RangeDifference => {
3735                soft_assert_eq_or_log!(
3736                    input1_type.scalar_type.without_modifiers(),
3737                    input2_type.scalar_type.without_modifiers()
3738                );
3739                input1_type.scalar_type.without_modifiers().nullable(true)
3740            }
3741
3742            MzAclItemContainsPrivilege => ScalarType::Bool.nullable(in_nullable),
3743
3744            ParseIdent => ScalarType::Array(Box::new(ScalarType::String)).nullable(in_nullable),
3745            PrettySql => ScalarType::String.nullable(in_nullable),
3746            RegexpReplace { .. } => ScalarType::String.nullable(in_nullable),
3747
3748            StartsWith => ScalarType::Bool.nullable(in_nullable),
3749        }
3750    }
3751
3752    /// Whether the function output is NULL if any of its inputs are NULL.
3753    pub fn propagates_nulls(&self) -> bool {
3754        // NOTE: The following is a list of the binary functions
3755        // that **DO NOT** propagate nulls.
3756        !matches!(
3757            self,
3758            BinaryFunc::ArrayArrayConcat
3759                | BinaryFunc::ListListConcat
3760                | BinaryFunc::ListElementConcat
3761                | BinaryFunc::ElementListConcat
3762                | BinaryFunc::ArrayRemove
3763                | BinaryFunc::ListRemove
3764        )
3765    }
3766
3767    /// Whether the function might return NULL even if none of its inputs are
3768    /// NULL.
3769    ///
3770    /// This is presently conservative, and may indicate that a function
3771    /// introduces nulls even when it does not.
3772    pub fn introduces_nulls(&self) -> bool {
3773        use BinaryFunc::*;
3774        match self {
3775            AddInt16
3776            | AddInt32
3777            | AddInt64
3778            | AddUInt16
3779            | AddUInt32
3780            | AddUInt64
3781            | AddFloat32
3782            | AddFloat64
3783            | AddInterval
3784            | AddTimestampInterval
3785            | AddTimestampTzInterval
3786            | AddDateInterval
3787            | AddDateTime
3788            | AddTimeInterval
3789            | AddNumeric
3790            | AgeTimestamp
3791            | AgeTimestampTz
3792            | BitAndInt16
3793            | BitAndInt32
3794            | BitAndInt64
3795            | BitAndUInt16
3796            | BitAndUInt32
3797            | BitAndUInt64
3798            | BitOrInt16
3799            | BitOrInt32
3800            | BitOrInt64
3801            | BitOrUInt16
3802            | BitOrUInt32
3803            | BitOrUInt64
3804            | BitXorInt16
3805            | BitXorInt32
3806            | BitXorInt64
3807            | BitXorUInt16
3808            | BitXorUInt32
3809            | BitXorUInt64
3810            | BitShiftLeftInt16
3811            | BitShiftLeftInt32
3812            | BitShiftLeftInt64
3813            | BitShiftLeftUInt16
3814            | BitShiftLeftUInt32
3815            | BitShiftLeftUInt64
3816            | BitShiftRightInt16
3817            | BitShiftRightInt32
3818            | BitShiftRightInt64
3819            | BitShiftRightUInt16
3820            | BitShiftRightUInt32
3821            | BitShiftRightUInt64
3822            | SubInt16
3823            | SubInt32
3824            | SubInt64
3825            | SubUInt16
3826            | SubUInt32
3827            | SubUInt64
3828            | SubFloat32
3829            | SubFloat64
3830            | SubInterval
3831            | SubTimestamp
3832            | SubTimestampTz
3833            | SubTimestampInterval
3834            | SubTimestampTzInterval
3835            | SubDate
3836            | SubDateInterval
3837            | SubTime
3838            | SubTimeInterval
3839            | SubNumeric
3840            | MulInt16
3841            | MulInt32
3842            | MulInt64
3843            | MulUInt16
3844            | MulUInt32
3845            | MulUInt64
3846            | MulFloat32
3847            | MulFloat64
3848            | MulNumeric
3849            | MulInterval
3850            | DivInt16
3851            | DivInt32
3852            | DivInt64
3853            | DivUInt16
3854            | DivUInt32
3855            | DivUInt64
3856            | DivFloat32
3857            | DivFloat64
3858            | DivNumeric
3859            | DivInterval
3860            | ModInt16
3861            | ModInt32
3862            | ModInt64
3863            | ModUInt16
3864            | ModUInt32
3865            | ModUInt64
3866            | ModFloat32
3867            | ModFloat64
3868            | ModNumeric
3869            | RoundNumeric
3870            | Eq
3871            | NotEq
3872            | Lt
3873            | Lte
3874            | Gt
3875            | Gte
3876            | LikeEscape
3877            | IsLikeMatch { .. }
3878            | IsRegexpMatch { .. }
3879            | ToCharTimestamp
3880            | ToCharTimestampTz
3881            | ConstantTimeEqBytes
3882            | ConstantTimeEqString
3883            | DateBinTimestamp
3884            | DateBinTimestampTz
3885            | ExtractInterval
3886            | ExtractTime
3887            | ExtractTimestamp
3888            | ExtractTimestampTz
3889            | ExtractDate
3890            | DatePartInterval
3891            | DatePartTime
3892            | DatePartTimestamp
3893            | DatePartTimestampTz
3894            | DateTruncTimestamp
3895            | DateTruncTimestampTz
3896            | DateTruncInterval
3897            | TimezoneTimestamp
3898            | TimezoneTimestampTz
3899            | TimezoneIntervalTimestamp
3900            | TimezoneIntervalTimestampTz
3901            | TimezoneIntervalTime
3902            | TimezoneOffset
3903            | TextConcat
3904            | JsonbContainsString
3905            | JsonbContainsJsonb
3906            | MapContainsKey
3907            | MapContainsAllKeys
3908            | MapContainsAnyKeys
3909            | MapContainsMap
3910            | ConvertFrom
3911            | Left
3912            | Position
3913            | Right
3914            | RepeatString
3915            | Trim
3916            | TrimLeading
3917            | TrimTrailing
3918            | EncodedBytesCharLength
3919            | ArrayContains
3920            | ArrayRemove
3921            | ArrayContainsArray { .. }
3922            | ArrayArrayConcat
3923            | ListListConcat
3924            | ListElementConcat
3925            | ElementListConcat
3926            | ListContainsList { .. }
3927            | ListRemove
3928            | DigestString
3929            | DigestBytes
3930            | MzRenderTypmod
3931            | Encode
3932            | Decode
3933            | LogNumeric
3934            | Power
3935            | PowerNumeric
3936            | GetBit
3937            | GetByte
3938            | RangeContainsElem { .. }
3939            | RangeContainsRange { .. }
3940            | RangeOverlaps
3941            | RangeAfter
3942            | RangeBefore
3943            | RangeOverleft
3944            | RangeOverright
3945            | RangeAdjacent
3946            | RangeUnion
3947            | RangeIntersection
3948            | RangeDifference
3949            | UuidGenerateV5
3950            | MzAclItemContainsPrivilege
3951            | ParseIdent
3952            | PrettySql
3953            | RegexpReplace { .. }
3954            | StartsWith => false,
3955
3956            JsonbGetInt64
3957            | JsonbGetInt64Stringify
3958            | JsonbGetString
3959            | JsonbGetStringStringify
3960            | JsonbGetPath
3961            | JsonbGetPathStringify
3962            | JsonbConcat
3963            | JsonbDeleteInt64
3964            | JsonbDeleteString
3965            | MapGetValue
3966            | ListLengthMax { .. }
3967            | ArrayLength
3968            | ArrayLower
3969            | ArrayUpper => true,
3970        }
3971    }
3972
3973    pub fn is_infix_op(&self) -> bool {
3974        use BinaryFunc::*;
3975        match self {
3976            AddInt16
3977            | AddInt32
3978            | AddInt64
3979            | AddUInt16
3980            | AddUInt32
3981            | AddUInt64
3982            | AddFloat32
3983            | AddFloat64
3984            | AddTimestampInterval
3985            | AddTimestampTzInterval
3986            | AddDateTime
3987            | AddDateInterval
3988            | AddTimeInterval
3989            | AddInterval
3990            | BitAndInt16
3991            | BitAndInt32
3992            | BitAndInt64
3993            | BitAndUInt16
3994            | BitAndUInt32
3995            | BitAndUInt64
3996            | BitOrInt16
3997            | BitOrInt32
3998            | BitOrInt64
3999            | BitOrUInt16
4000            | BitOrUInt32
4001            | BitOrUInt64
4002            | BitXorInt16
4003            | BitXorInt32
4004            | BitXorInt64
4005            | BitXorUInt16
4006            | BitXorUInt32
4007            | BitXorUInt64
4008            | BitShiftLeftInt16
4009            | BitShiftLeftInt32
4010            | BitShiftLeftInt64
4011            | BitShiftLeftUInt16
4012            | BitShiftLeftUInt32
4013            | BitShiftLeftUInt64
4014            | BitShiftRightInt16
4015            | BitShiftRightInt32
4016            | BitShiftRightInt64
4017            | BitShiftRightUInt16
4018            | BitShiftRightUInt32
4019            | BitShiftRightUInt64
4020            | SubInterval
4021            | MulInterval
4022            | DivInterval
4023            | AddNumeric
4024            | SubInt16
4025            | SubInt32
4026            | SubInt64
4027            | SubUInt16
4028            | SubUInt32
4029            | SubUInt64
4030            | SubFloat32
4031            | SubFloat64
4032            | SubTimestamp
4033            | SubTimestampTz
4034            | SubTimestampInterval
4035            | SubTimestampTzInterval
4036            | SubDate
4037            | SubDateInterval
4038            | SubTime
4039            | SubTimeInterval
4040            | SubNumeric
4041            | MulInt16
4042            | MulInt32
4043            | MulInt64
4044            | MulUInt16
4045            | MulUInt32
4046            | MulUInt64
4047            | MulFloat32
4048            | MulFloat64
4049            | MulNumeric
4050            | DivInt16
4051            | DivInt32
4052            | DivInt64
4053            | DivUInt16
4054            | DivUInt32
4055            | DivUInt64
4056            | DivFloat32
4057            | DivFloat64
4058            | DivNumeric
4059            | ModInt16
4060            | ModInt32
4061            | ModInt64
4062            | ModUInt16
4063            | ModUInt32
4064            | ModUInt64
4065            | ModFloat32
4066            | ModFloat64
4067            | ModNumeric
4068            | Eq
4069            | NotEq
4070            | Lt
4071            | Lte
4072            | Gt
4073            | Gte
4074            | JsonbConcat
4075            | JsonbContainsJsonb
4076            | JsonbGetInt64
4077            | JsonbGetInt64Stringify
4078            | JsonbGetString
4079            | JsonbGetStringStringify
4080            | JsonbGetPath
4081            | JsonbGetPathStringify
4082            | JsonbContainsString
4083            | JsonbDeleteInt64
4084            | JsonbDeleteString
4085            | MapContainsKey
4086            | MapGetValue
4087            | MapContainsAllKeys
4088            | MapContainsAnyKeys
4089            | MapContainsMap
4090            | TextConcat
4091            | IsLikeMatch { .. }
4092            | IsRegexpMatch { .. }
4093            | ArrayContains
4094            | ArrayContainsArray { .. }
4095            | ArrayLength
4096            | ArrayLower
4097            | ArrayUpper
4098            | ArrayArrayConcat
4099            | ListListConcat
4100            | ListElementConcat
4101            | ElementListConcat
4102            | ListContainsList { .. }
4103            | RangeContainsElem { .. }
4104            | RangeContainsRange { .. }
4105            | RangeOverlaps
4106            | RangeAfter
4107            | RangeBefore
4108            | RangeOverleft
4109            | RangeOverright
4110            | RangeAdjacent
4111            | RangeUnion
4112            | RangeIntersection
4113            | RangeDifference => true,
4114            ToCharTimestamp
4115            | ToCharTimestampTz
4116            | AgeTimestamp
4117            | AgeTimestampTz
4118            | DateBinTimestamp
4119            | DateBinTimestampTz
4120            | ExtractInterval
4121            | ExtractTime
4122            | ExtractTimestamp
4123            | ExtractTimestampTz
4124            | ExtractDate
4125            | DatePartInterval
4126            | DatePartTime
4127            | DatePartTimestamp
4128            | DatePartTimestampTz
4129            | DateTruncInterval
4130            | DateTruncTimestamp
4131            | DateTruncTimestampTz
4132            | TimezoneTimestamp
4133            | TimezoneTimestampTz
4134            | TimezoneIntervalTimestamp
4135            | TimezoneIntervalTimestampTz
4136            | TimezoneIntervalTime
4137            | TimezoneOffset
4138            | RoundNumeric
4139            | ConvertFrom
4140            | Left
4141            | Position
4142            | Right
4143            | Trim
4144            | TrimLeading
4145            | TrimTrailing
4146            | EncodedBytesCharLength
4147            | ListLengthMax { .. }
4148            | DigestString
4149            | DigestBytes
4150            | MzRenderTypmod
4151            | Encode
4152            | Decode
4153            | LogNumeric
4154            | Power
4155            | PowerNumeric
4156            | RepeatString
4157            | ArrayRemove
4158            | ListRemove
4159            | LikeEscape
4160            | UuidGenerateV5
4161            | GetBit
4162            | GetByte
4163            | MzAclItemContainsPrivilege
4164            | ConstantTimeEqBytes
4165            | ConstantTimeEqString
4166            | ParseIdent
4167            | PrettySql
4168            | RegexpReplace { .. }
4169            | StartsWith => false,
4170        }
4171    }
4172
4173    /// Returns the negation of the given binary function, if it exists.
4174    pub fn negate(&self) -> Option<Self> {
4175        match self {
4176            BinaryFunc::Eq => Some(BinaryFunc::NotEq),
4177            BinaryFunc::NotEq => Some(BinaryFunc::Eq),
4178            BinaryFunc::Lt => Some(BinaryFunc::Gte),
4179            BinaryFunc::Gte => Some(BinaryFunc::Lt),
4180            BinaryFunc::Gt => Some(BinaryFunc::Lte),
4181            BinaryFunc::Lte => Some(BinaryFunc::Gt),
4182            _ => None,
4183        }
4184    }
4185
4186    /// Returns true if the function could introduce an error on non-error inputs.
4187    pub fn could_error(&self) -> bool {
4188        match self {
4189            BinaryFunc::Eq
4190            | BinaryFunc::NotEq
4191            | BinaryFunc::Lt
4192            | BinaryFunc::Gte
4193            | BinaryFunc::Gt
4194            | BinaryFunc::Lte => false,
4195            BinaryFunc::BitAndInt16
4196            | BinaryFunc::BitAndInt32
4197            | BinaryFunc::BitAndInt64
4198            | BinaryFunc::BitAndUInt16
4199            | BinaryFunc::BitAndUInt32
4200            | BinaryFunc::BitAndUInt64
4201            | BinaryFunc::BitOrInt16
4202            | BinaryFunc::BitOrInt32
4203            | BinaryFunc::BitOrInt64
4204            | BinaryFunc::BitOrUInt16
4205            | BinaryFunc::BitOrUInt32
4206            | BinaryFunc::BitOrUInt64
4207            | BinaryFunc::BitXorInt16
4208            | BinaryFunc::BitXorInt32
4209            | BinaryFunc::BitXorInt64
4210            | BinaryFunc::BitXorUInt16
4211            | BinaryFunc::BitXorUInt32
4212            | BinaryFunc::BitXorUInt64
4213            | BinaryFunc::BitShiftLeftInt16
4214            | BinaryFunc::BitShiftLeftInt32
4215            | BinaryFunc::BitShiftLeftInt64
4216            | BinaryFunc::BitShiftLeftUInt16
4217            | BinaryFunc::BitShiftLeftUInt32
4218            | BinaryFunc::BitShiftLeftUInt64
4219            | BinaryFunc::BitShiftRightInt16
4220            | BinaryFunc::BitShiftRightInt32
4221            | BinaryFunc::BitShiftRightInt64
4222            | BinaryFunc::BitShiftRightUInt16
4223            | BinaryFunc::BitShiftRightUInt32
4224            | BinaryFunc::BitShiftRightUInt64 => false,
4225            BinaryFunc::JsonbGetInt64
4226            | BinaryFunc::JsonbGetInt64Stringify
4227            | BinaryFunc::JsonbGetString
4228            | BinaryFunc::JsonbGetStringStringify
4229            | BinaryFunc::JsonbGetPath
4230            | BinaryFunc::JsonbGetPathStringify
4231            | BinaryFunc::JsonbContainsString
4232            | BinaryFunc::JsonbConcat
4233            | BinaryFunc::JsonbContainsJsonb
4234            | BinaryFunc::JsonbDeleteInt64
4235            | BinaryFunc::JsonbDeleteString => false,
4236            BinaryFunc::MapContainsKey
4237            | BinaryFunc::MapGetValue
4238            | BinaryFunc::MapContainsAllKeys
4239            | BinaryFunc::MapContainsAnyKeys
4240            | BinaryFunc::MapContainsMap => false,
4241            BinaryFunc::AddTimeInterval
4242            | BinaryFunc::SubTimestamp
4243            | BinaryFunc::SubTimestampTz
4244            | BinaryFunc::SubDate
4245            | BinaryFunc::SubTime
4246            | BinaryFunc::SubTimeInterval
4247            | BinaryFunc::UuidGenerateV5
4248            | BinaryFunc::RangeContainsRange { .. }
4249            | BinaryFunc::RangeOverlaps
4250            | BinaryFunc::RangeAfter
4251            | BinaryFunc::RangeBefore
4252            | BinaryFunc::RangeOverleft
4253            | BinaryFunc::RangeOverright
4254            | BinaryFunc::RangeAdjacent => false,
4255
4256            _ => true,
4257        }
4258    }
4259
4260    /// Returns true if the function is monotone. (Non-strict; either increasing or decreasing.)
4261    /// Monotone functions map ranges to ranges: ie. given a range of possible inputs, we can
4262    /// determine the range of possible outputs just by mapping the endpoints.
4263    ///
4264    /// This describes the *pointwise* behaviour of the function:
4265    /// ie. the behaviour of any specific argument as the others are held constant. (For example, `a - b` is
4266    /// monotone in the first argument because for any particular value of `b`, increasing `a` will
4267    /// always cause the result to increase... and in the second argument because for any specific `a`,
4268    /// increasing `b` will always cause the result to _decrease_.)
4269    ///
4270    /// This property describes the behaviour of the function over ranges where the function is defined:
4271    /// ie. the arguments and the result are non-error datums.
4272    pub fn is_monotone(&self) -> (bool, bool) {
4273        match self {
4274            BinaryFunc::AddInt16
4275            | BinaryFunc::AddInt32
4276            | BinaryFunc::AddInt64
4277            | BinaryFunc::AddUInt16
4278            | BinaryFunc::AddUInt32
4279            | BinaryFunc::AddUInt64
4280            | BinaryFunc::AddFloat32
4281            | BinaryFunc::AddFloat64
4282            | BinaryFunc::AddInterval
4283            | BinaryFunc::AddTimestampInterval
4284            | BinaryFunc::AddTimestampTzInterval
4285            | BinaryFunc::AddDateInterval
4286            | BinaryFunc::AddDateTime
4287            | BinaryFunc::AddTimeInterval
4288            | BinaryFunc::AddNumeric => (true, true),
4289            BinaryFunc::BitAndInt16
4290            | BinaryFunc::BitAndInt32
4291            | BinaryFunc::BitAndInt64
4292            | BinaryFunc::BitAndUInt16
4293            | BinaryFunc::BitAndUInt32
4294            | BinaryFunc::BitAndUInt64
4295            | BinaryFunc::BitOrInt16
4296            | BinaryFunc::BitOrInt32
4297            | BinaryFunc::BitOrInt64
4298            | BinaryFunc::BitOrUInt16
4299            | BinaryFunc::BitOrUInt32
4300            | BinaryFunc::BitOrUInt64
4301            | BinaryFunc::BitXorInt16
4302            | BinaryFunc::BitXorInt32
4303            | BinaryFunc::BitXorInt64
4304            | BinaryFunc::BitXorUInt16
4305            | BinaryFunc::BitXorUInt32
4306            | BinaryFunc::BitXorUInt64 => (false, false),
4307            // The shift functions wrap, which means they are monotonic in neither argument.
4308            BinaryFunc::BitShiftLeftInt16
4309            | BinaryFunc::BitShiftLeftInt32
4310            | BinaryFunc::BitShiftLeftInt64
4311            | BinaryFunc::BitShiftLeftUInt16
4312            | BinaryFunc::BitShiftLeftUInt32
4313            | BinaryFunc::BitShiftLeftUInt64
4314            | BinaryFunc::BitShiftRightInt16
4315            | BinaryFunc::BitShiftRightInt32
4316            | BinaryFunc::BitShiftRightInt64
4317            | BinaryFunc::BitShiftRightUInt16
4318            | BinaryFunc::BitShiftRightUInt32
4319            | BinaryFunc::BitShiftRightUInt64 => (false, false),
4320            BinaryFunc::SubInt16
4321            | BinaryFunc::SubInt32
4322            | BinaryFunc::SubInt64
4323            | BinaryFunc::SubUInt16
4324            | BinaryFunc::SubUInt32
4325            | BinaryFunc::SubUInt64
4326            | BinaryFunc::SubFloat32
4327            | BinaryFunc::SubFloat64
4328            | BinaryFunc::SubInterval
4329            | BinaryFunc::SubTimestamp
4330            | BinaryFunc::SubTimestampTz
4331            | BinaryFunc::SubTimestampInterval
4332            | BinaryFunc::SubTimestampTzInterval
4333            | BinaryFunc::SubDate
4334            | BinaryFunc::SubDateInterval
4335            | BinaryFunc::SubTime
4336            | BinaryFunc::SubTimeInterval
4337            | BinaryFunc::SubNumeric => (true, true),
4338            BinaryFunc::MulInt16
4339            | BinaryFunc::MulInt32
4340            | BinaryFunc::MulInt64
4341            | BinaryFunc::MulUInt16
4342            | BinaryFunc::MulUInt32
4343            | BinaryFunc::MulUInt64
4344            | BinaryFunc::MulFloat32
4345            | BinaryFunc::MulFloat64
4346            | BinaryFunc::MulNumeric
4347            | BinaryFunc::MulInterval => (true, true),
4348            BinaryFunc::DivInt16
4349            | BinaryFunc::DivInt32
4350            | BinaryFunc::DivInt64
4351            | BinaryFunc::DivUInt16
4352            | BinaryFunc::DivUInt32
4353            | BinaryFunc::DivUInt64
4354            | BinaryFunc::DivFloat32
4355            | BinaryFunc::DivFloat64
4356            | BinaryFunc::DivNumeric
4357            | BinaryFunc::DivInterval => (true, false),
4358            BinaryFunc::ModInt16
4359            | BinaryFunc::ModInt32
4360            | BinaryFunc::ModInt64
4361            | BinaryFunc::ModUInt16
4362            | BinaryFunc::ModUInt32
4363            | BinaryFunc::ModUInt64
4364            | BinaryFunc::ModFloat32
4365            | BinaryFunc::ModFloat64
4366            | BinaryFunc::ModNumeric => (false, false),
4367            BinaryFunc::RoundNumeric => (true, false),
4368            BinaryFunc::Eq | BinaryFunc::NotEq => (false, false),
4369            BinaryFunc::Lt | BinaryFunc::Lte | BinaryFunc::Gt | BinaryFunc::Gte => (true, true),
4370            BinaryFunc::LikeEscape
4371            | BinaryFunc::IsLikeMatch { .. }
4372            | BinaryFunc::IsRegexpMatch { .. } => (false, false),
4373            BinaryFunc::ToCharTimestamp | BinaryFunc::ToCharTimestampTz => (false, false),
4374            BinaryFunc::DateBinTimestamp | BinaryFunc::DateBinTimestampTz => (true, true),
4375            BinaryFunc::AgeTimestamp | BinaryFunc::AgeTimestampTz => (true, true),
4376            // Text concatenation is monotonic in its second argument, because if I change the
4377            // second argument but don't change the first argument, then we won't find a difference
4378            // in that part of the concatenation result that came from the first argument, so we'll
4379            // find the difference that comes from changing the second argument.
4380            // (It's not monotonic in its first argument, because e.g.,
4381            // 'A' < 'AA' but 'AZ' > 'AAZ'.)
4382            BinaryFunc::TextConcat => (false, true),
4383            // `left` is unfortunately not monotonic (at least for negative second arguments),
4384            // because 'aa' < 'z', but `left(_, -1)` makes 'a' > ''.
4385            BinaryFunc::Left => (false, false),
4386            // TODO: can these ever be treated as monotone? It's safe to treat the unary versions
4387            // as monotone in some cases, but only when extracting specific parts.
4388            BinaryFunc::ExtractInterval
4389            | BinaryFunc::ExtractTime
4390            | BinaryFunc::ExtractTimestamp
4391            | BinaryFunc::ExtractTimestampTz
4392            | BinaryFunc::ExtractDate => (false, false),
4393            BinaryFunc::DatePartInterval
4394            | BinaryFunc::DatePartTime
4395            | BinaryFunc::DatePartTimestamp
4396            | BinaryFunc::DatePartTimestampTz => (false, false),
4397            BinaryFunc::DateTruncTimestamp
4398            | BinaryFunc::DateTruncTimestampTz
4399            | BinaryFunc::DateTruncInterval => (false, false),
4400            BinaryFunc::TimezoneTimestamp
4401            | BinaryFunc::TimezoneTimestampTz
4402            | BinaryFunc::TimezoneIntervalTimestamp
4403            | BinaryFunc::TimezoneIntervalTimestampTz
4404            | BinaryFunc::TimezoneIntervalTime
4405            | BinaryFunc::TimezoneOffset => (false, false),
4406            BinaryFunc::JsonbGetInt64
4407            | BinaryFunc::JsonbGetInt64Stringify
4408            | BinaryFunc::JsonbGetString
4409            | BinaryFunc::JsonbGetStringStringify
4410            | BinaryFunc::JsonbGetPath
4411            | BinaryFunc::JsonbGetPathStringify
4412            | BinaryFunc::JsonbContainsString
4413            | BinaryFunc::JsonbConcat
4414            | BinaryFunc::JsonbContainsJsonb
4415            | BinaryFunc::JsonbDeleteInt64
4416            | BinaryFunc::JsonbDeleteString
4417            | BinaryFunc::MapContainsKey
4418            | BinaryFunc::MapGetValue
4419            | BinaryFunc::MapContainsAllKeys
4420            | BinaryFunc::MapContainsAnyKeys
4421            | BinaryFunc::MapContainsMap => (false, false),
4422            BinaryFunc::ConvertFrom
4423            | BinaryFunc::Position
4424            | BinaryFunc::Right
4425            | BinaryFunc::RepeatString
4426            | BinaryFunc::Trim
4427            | BinaryFunc::TrimLeading
4428            | BinaryFunc::TrimTrailing
4429            | BinaryFunc::EncodedBytesCharLength
4430            | BinaryFunc::ListLengthMax { .. }
4431            | BinaryFunc::ArrayContains
4432            | BinaryFunc::ArrayContainsArray { .. }
4433            | BinaryFunc::ArrayLength
4434            | BinaryFunc::ArrayLower
4435            | BinaryFunc::ArrayRemove
4436            | BinaryFunc::ArrayUpper
4437            | BinaryFunc::ArrayArrayConcat
4438            | BinaryFunc::ListListConcat
4439            | BinaryFunc::ListElementConcat
4440            | BinaryFunc::ElementListConcat
4441            | BinaryFunc::ListContainsList { .. }
4442            | BinaryFunc::ListRemove
4443            | BinaryFunc::DigestString
4444            | BinaryFunc::DigestBytes
4445            | BinaryFunc::MzRenderTypmod
4446            | BinaryFunc::Encode
4447            | BinaryFunc::Decode => (false, false),
4448            // TODO: it may be safe to treat these as monotone.
4449            BinaryFunc::LogNumeric | BinaryFunc::Power | BinaryFunc::PowerNumeric => (false, false),
4450            BinaryFunc::GetBit
4451            | BinaryFunc::GetByte
4452            | BinaryFunc::RangeContainsElem { .. }
4453            | BinaryFunc::RangeContainsRange { .. }
4454            | BinaryFunc::RangeOverlaps
4455            | BinaryFunc::RangeAfter
4456            | BinaryFunc::RangeBefore
4457            | BinaryFunc::RangeOverleft
4458            | BinaryFunc::RangeOverright
4459            | BinaryFunc::RangeAdjacent
4460            | BinaryFunc::RangeUnion
4461            | BinaryFunc::RangeIntersection
4462            | BinaryFunc::RangeDifference => (false, false),
4463            BinaryFunc::UuidGenerateV5 => (false, false),
4464            BinaryFunc::MzAclItemContainsPrivilege => (false, false),
4465            BinaryFunc::ParseIdent => (false, false),
4466            BinaryFunc::ConstantTimeEqBytes | BinaryFunc::ConstantTimeEqString => (false, false),
4467            BinaryFunc::PrettySql => (false, false),
4468            BinaryFunc::RegexpReplace { .. } => (false, false),
4469            BinaryFunc::StartsWith => (false, false),
4470        }
4471    }
4472}
4473
4474impl fmt::Display for BinaryFunc {
4475    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4476        match self {
4477            BinaryFunc::AddInt16 => f.write_str("+"),
4478            BinaryFunc::AddInt32 => f.write_str("+"),
4479            BinaryFunc::AddInt64 => f.write_str("+"),
4480            BinaryFunc::AddUInt16 => f.write_str("+"),
4481            BinaryFunc::AddUInt32 => f.write_str("+"),
4482            BinaryFunc::AddUInt64 => f.write_str("+"),
4483            BinaryFunc::AddFloat32 => f.write_str("+"),
4484            BinaryFunc::AddFloat64 => f.write_str("+"),
4485            BinaryFunc::AddNumeric => f.write_str("+"),
4486            BinaryFunc::AddInterval => f.write_str("+"),
4487            BinaryFunc::AddTimestampInterval => f.write_str("+"),
4488            BinaryFunc::AddTimestampTzInterval => f.write_str("+"),
4489            BinaryFunc::AddDateTime => f.write_str("+"),
4490            BinaryFunc::AddDateInterval => f.write_str("+"),
4491            BinaryFunc::AddTimeInterval => f.write_str("+"),
4492            BinaryFunc::AgeTimestamp => f.write_str("age"),
4493            BinaryFunc::AgeTimestampTz => f.write_str("age"),
4494            BinaryFunc::BitAndInt16 => f.write_str("&"),
4495            BinaryFunc::BitAndInt32 => f.write_str("&"),
4496            BinaryFunc::BitAndInt64 => f.write_str("&"),
4497            BinaryFunc::BitAndUInt16 => f.write_str("&"),
4498            BinaryFunc::BitAndUInt32 => f.write_str("&"),
4499            BinaryFunc::BitAndUInt64 => f.write_str("&"),
4500            BinaryFunc::BitOrInt16 => f.write_str("|"),
4501            BinaryFunc::BitOrInt32 => f.write_str("|"),
4502            BinaryFunc::BitOrInt64 => f.write_str("|"),
4503            BinaryFunc::BitOrUInt16 => f.write_str("|"),
4504            BinaryFunc::BitOrUInt32 => f.write_str("|"),
4505            BinaryFunc::BitOrUInt64 => f.write_str("|"),
4506            BinaryFunc::BitXorInt16 => f.write_str("#"),
4507            BinaryFunc::BitXorInt32 => f.write_str("#"),
4508            BinaryFunc::BitXorInt64 => f.write_str("#"),
4509            BinaryFunc::BitXorUInt16 => f.write_str("#"),
4510            BinaryFunc::BitXorUInt32 => f.write_str("#"),
4511            BinaryFunc::BitXorUInt64 => f.write_str("#"),
4512            BinaryFunc::BitShiftLeftInt16 => f.write_str("<<"),
4513            BinaryFunc::BitShiftLeftInt32 => f.write_str("<<"),
4514            BinaryFunc::BitShiftLeftInt64 => f.write_str("<<"),
4515            BinaryFunc::BitShiftLeftUInt16 => f.write_str("<<"),
4516            BinaryFunc::BitShiftLeftUInt32 => f.write_str("<<"),
4517            BinaryFunc::BitShiftLeftUInt64 => f.write_str("<<"),
4518            BinaryFunc::BitShiftRightInt16 => f.write_str(">>"),
4519            BinaryFunc::BitShiftRightInt32 => f.write_str(">>"),
4520            BinaryFunc::BitShiftRightInt64 => f.write_str(">>"),
4521            BinaryFunc::BitShiftRightUInt16 => f.write_str(">>"),
4522            BinaryFunc::BitShiftRightUInt32 => f.write_str(">>"),
4523            BinaryFunc::BitShiftRightUInt64 => f.write_str(">>"),
4524            BinaryFunc::SubInt16 => f.write_str("-"),
4525            BinaryFunc::SubInt32 => f.write_str("-"),
4526            BinaryFunc::SubInt64 => f.write_str("-"),
4527            BinaryFunc::SubUInt16 => f.write_str("-"),
4528            BinaryFunc::SubUInt32 => f.write_str("-"),
4529            BinaryFunc::SubUInt64 => f.write_str("-"),
4530            BinaryFunc::SubFloat32 => f.write_str("-"),
4531            BinaryFunc::SubFloat64 => f.write_str("-"),
4532            BinaryFunc::SubNumeric => f.write_str("-"),
4533            BinaryFunc::SubInterval => f.write_str("-"),
4534            BinaryFunc::SubTimestamp => f.write_str("-"),
4535            BinaryFunc::SubTimestampTz => f.write_str("-"),
4536            BinaryFunc::SubTimestampInterval => f.write_str("-"),
4537            BinaryFunc::SubTimestampTzInterval => f.write_str("-"),
4538            BinaryFunc::SubDate => f.write_str("-"),
4539            BinaryFunc::SubDateInterval => f.write_str("-"),
4540            BinaryFunc::SubTime => f.write_str("-"),
4541            BinaryFunc::SubTimeInterval => f.write_str("-"),
4542            BinaryFunc::MulInt16 => f.write_str("*"),
4543            BinaryFunc::MulInt32 => f.write_str("*"),
4544            BinaryFunc::MulInt64 => f.write_str("*"),
4545            BinaryFunc::MulUInt16 => f.write_str("*"),
4546            BinaryFunc::MulUInt32 => f.write_str("*"),
4547            BinaryFunc::MulUInt64 => f.write_str("*"),
4548            BinaryFunc::MulFloat32 => f.write_str("*"),
4549            BinaryFunc::MulFloat64 => f.write_str("*"),
4550            BinaryFunc::MulNumeric => f.write_str("*"),
4551            BinaryFunc::MulInterval => f.write_str("*"),
4552            BinaryFunc::DivInt16 => f.write_str("/"),
4553            BinaryFunc::DivInt32 => f.write_str("/"),
4554            BinaryFunc::DivInt64 => f.write_str("/"),
4555            BinaryFunc::DivUInt16 => f.write_str("/"),
4556            BinaryFunc::DivUInt32 => f.write_str("/"),
4557            BinaryFunc::DivUInt64 => f.write_str("/"),
4558            BinaryFunc::DivFloat32 => f.write_str("/"),
4559            BinaryFunc::DivFloat64 => f.write_str("/"),
4560            BinaryFunc::DivNumeric => f.write_str("/"),
4561            BinaryFunc::DivInterval => f.write_str("/"),
4562            BinaryFunc::ModInt16 => f.write_str("%"),
4563            BinaryFunc::ModInt32 => f.write_str("%"),
4564            BinaryFunc::ModInt64 => f.write_str("%"),
4565            BinaryFunc::ModUInt16 => f.write_str("%"),
4566            BinaryFunc::ModUInt32 => f.write_str("%"),
4567            BinaryFunc::ModUInt64 => f.write_str("%"),
4568            BinaryFunc::ModFloat32 => f.write_str("%"),
4569            BinaryFunc::ModFloat64 => f.write_str("%"),
4570            BinaryFunc::ModNumeric => f.write_str("%"),
4571            BinaryFunc::Eq => f.write_str("="),
4572            BinaryFunc::NotEq => f.write_str("!="),
4573            BinaryFunc::Lt => f.write_str("<"),
4574            BinaryFunc::Lte => f.write_str("<="),
4575            BinaryFunc::Gt => f.write_str(">"),
4576            BinaryFunc::Gte => f.write_str(">="),
4577            BinaryFunc::LikeEscape => f.write_str("like_escape"),
4578            BinaryFunc::IsLikeMatch {
4579                case_insensitive: false,
4580            } => f.write_str("like"),
4581            BinaryFunc::IsLikeMatch {
4582                case_insensitive: true,
4583            } => f.write_str("ilike"),
4584            BinaryFunc::IsRegexpMatch {
4585                case_insensitive: false,
4586            } => f.write_str("~"),
4587            BinaryFunc::IsRegexpMatch {
4588                case_insensitive: true,
4589            } => f.write_str("~*"),
4590            BinaryFunc::ToCharTimestamp => f.write_str("tocharts"),
4591            BinaryFunc::ToCharTimestampTz => f.write_str("tochartstz"),
4592            BinaryFunc::DateBinTimestamp => f.write_str("bin_unix_epoch_timestamp"),
4593            BinaryFunc::DateBinTimestampTz => f.write_str("bin_unix_epoch_timestamptz"),
4594            BinaryFunc::ExtractInterval => f.write_str("extractiv"),
4595            BinaryFunc::ExtractTime => f.write_str("extractt"),
4596            BinaryFunc::ExtractTimestamp => f.write_str("extractts"),
4597            BinaryFunc::ExtractTimestampTz => f.write_str("extracttstz"),
4598            BinaryFunc::ExtractDate => f.write_str("extractd"),
4599            BinaryFunc::DatePartInterval => f.write_str("date_partiv"),
4600            BinaryFunc::DatePartTime => f.write_str("date_partt"),
4601            BinaryFunc::DatePartTimestamp => f.write_str("date_partts"),
4602            BinaryFunc::DatePartTimestampTz => f.write_str("date_parttstz"),
4603            BinaryFunc::DateTruncTimestamp => f.write_str("date_truncts"),
4604            BinaryFunc::DateTruncInterval => f.write_str("date_trunciv"),
4605            BinaryFunc::DateTruncTimestampTz => f.write_str("date_trunctstz"),
4606            BinaryFunc::TimezoneTimestamp => f.write_str("timezonets"),
4607            BinaryFunc::TimezoneTimestampTz => f.write_str("timezonetstz"),
4608            BinaryFunc::TimezoneIntervalTimestamp => f.write_str("timezoneits"),
4609            BinaryFunc::TimezoneIntervalTimestampTz => f.write_str("timezoneitstz"),
4610            BinaryFunc::TimezoneIntervalTime => f.write_str("timezoneit"),
4611            BinaryFunc::TimezoneOffset => f.write_str("timezone_offset"),
4612            BinaryFunc::TextConcat => f.write_str("||"),
4613            BinaryFunc::JsonbGetInt64 => f.write_str("->"),
4614            BinaryFunc::JsonbGetInt64Stringify => f.write_str("->>"),
4615            BinaryFunc::JsonbGetString => f.write_str("->"),
4616            BinaryFunc::JsonbGetStringStringify => f.write_str("->>"),
4617            BinaryFunc::JsonbGetPath => f.write_str("#>"),
4618            BinaryFunc::JsonbGetPathStringify => f.write_str("#>>"),
4619            BinaryFunc::JsonbContainsString | BinaryFunc::MapContainsKey => f.write_str("?"),
4620            BinaryFunc::JsonbConcat => f.write_str("||"),
4621            BinaryFunc::JsonbContainsJsonb | BinaryFunc::MapContainsMap => f.write_str("@>"),
4622            BinaryFunc::JsonbDeleteInt64 => f.write_str("-"),
4623            BinaryFunc::JsonbDeleteString => f.write_str("-"),
4624            BinaryFunc::MapGetValue => f.write_str("->"),
4625            BinaryFunc::MapContainsAllKeys => f.write_str("?&"),
4626            BinaryFunc::MapContainsAnyKeys => f.write_str("?|"),
4627            BinaryFunc::RoundNumeric => f.write_str("round"),
4628            BinaryFunc::ConvertFrom => f.write_str("convert_from"),
4629            BinaryFunc::Left => f.write_str("left"),
4630            BinaryFunc::Position => f.write_str("position"),
4631            BinaryFunc::Right => f.write_str("right"),
4632            BinaryFunc::Trim => f.write_str("btrim"),
4633            BinaryFunc::TrimLeading => f.write_str("ltrim"),
4634            BinaryFunc::TrimTrailing => f.write_str("rtrim"),
4635            BinaryFunc::EncodedBytesCharLength => f.write_str("length"),
4636            BinaryFunc::ListLengthMax { .. } => f.write_str("list_length_max"),
4637            BinaryFunc::ArrayContains => f.write_str("array_contains"),
4638            BinaryFunc::ArrayContainsArray { rev, .. } => {
4639                f.write_str(if *rev { "<@" } else { "@>" })
4640            }
4641            BinaryFunc::ArrayLength => f.write_str("array_length"),
4642            BinaryFunc::ArrayLower => f.write_str("array_lower"),
4643            BinaryFunc::ArrayRemove => f.write_str("array_remove"),
4644            BinaryFunc::ArrayUpper => f.write_str("array_upper"),
4645            BinaryFunc::ArrayArrayConcat => f.write_str("||"),
4646            BinaryFunc::ListListConcat => f.write_str("||"),
4647            BinaryFunc::ListElementConcat => f.write_str("||"),
4648            BinaryFunc::ElementListConcat => f.write_str("||"),
4649            BinaryFunc::ListRemove => f.write_str("list_remove"),
4650            BinaryFunc::ListContainsList { rev, .. } => f.write_str(if *rev { "<@" } else { "@>" }),
4651            BinaryFunc::DigestString | BinaryFunc::DigestBytes => f.write_str("digest"),
4652            BinaryFunc::MzRenderTypmod => f.write_str("mz_render_typmod"),
4653            BinaryFunc::Encode => f.write_str("encode"),
4654            BinaryFunc::Decode => f.write_str("decode"),
4655            BinaryFunc::LogNumeric => f.write_str("log"),
4656            BinaryFunc::Power => f.write_str("power"),
4657            BinaryFunc::PowerNumeric => f.write_str("power_numeric"),
4658            BinaryFunc::RepeatString => f.write_str("repeat"),
4659            BinaryFunc::GetBit => f.write_str("get_bit"),
4660            BinaryFunc::GetByte => f.write_str("get_byte"),
4661            BinaryFunc::ConstantTimeEqBytes => f.write_str("constant_time_compare_bytes"),
4662            BinaryFunc::ConstantTimeEqString => f.write_str("constant_time_compare_strings"),
4663            BinaryFunc::RangeContainsElem { rev, .. } => {
4664                f.write_str(if *rev { "<@" } else { "@>" })
4665            }
4666            BinaryFunc::RangeContainsRange { rev, .. } => {
4667                f.write_str(if *rev { "<@" } else { "@>" })
4668            }
4669            BinaryFunc::RangeOverlaps => f.write_str("&&"),
4670            BinaryFunc::RangeAfter => f.write_str(">>"),
4671            BinaryFunc::RangeBefore => f.write_str("<<"),
4672            BinaryFunc::RangeOverleft => f.write_str("&<"),
4673            BinaryFunc::RangeOverright => f.write_str("&>"),
4674            BinaryFunc::RangeAdjacent => f.write_str("-|-"),
4675            BinaryFunc::RangeUnion => f.write_str("+"),
4676            BinaryFunc::RangeIntersection => f.write_str("*"),
4677            BinaryFunc::RangeDifference => f.write_str("-"),
4678            BinaryFunc::UuidGenerateV5 => f.write_str("uuid_generate_v5"),
4679            BinaryFunc::MzAclItemContainsPrivilege => f.write_str("mz_aclitem_contains_privilege"),
4680            BinaryFunc::ParseIdent => f.write_str("parse_ident"),
4681            BinaryFunc::PrettySql => f.write_str("pretty_sql"),
4682            BinaryFunc::RegexpReplace { regex, limit } => write!(
4683                f,
4684                "regexp_replace[{}, case_insensitive={}, limit={}]",
4685                regex.pattern().escaped(),
4686                regex.case_insensitive,
4687                limit
4688            ),
4689            BinaryFunc::StartsWith => f.write_str("starts_with"),
4690        }
4691    }
4692}
4693
4694/// An explicit [`Arbitrary`] implementation needed here because of a known
4695/// `proptest` issue.
4696///
4697/// Revert to the derive-macro impementation once the issue[^1] is fixed.
4698///
4699/// [^1]: <https://github.com/AltSysrq/proptest/issues/152>
4700impl Arbitrary for BinaryFunc {
4701    type Parameters = ();
4702
4703    type Strategy = Union<BoxedStrategy<Self>>;
4704
4705    fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
4706        Union::new(vec![
4707            Just(BinaryFunc::AddInt16).boxed(),
4708            Just(BinaryFunc::AddInt32).boxed(),
4709            Just(BinaryFunc::AddInt64).boxed(),
4710            Just(BinaryFunc::AddUInt16).boxed(),
4711            Just(BinaryFunc::AddUInt32).boxed(),
4712            Just(BinaryFunc::AddUInt64).boxed(),
4713            Just(BinaryFunc::AddFloat32).boxed(),
4714            Just(BinaryFunc::AddFloat64).boxed(),
4715            Just(BinaryFunc::AddInterval).boxed(),
4716            Just(BinaryFunc::AddTimestampInterval).boxed(),
4717            Just(BinaryFunc::AddTimestampTzInterval).boxed(),
4718            Just(BinaryFunc::AddDateInterval).boxed(),
4719            Just(BinaryFunc::AddDateTime).boxed(),
4720            Just(BinaryFunc::AddTimeInterval).boxed(),
4721            Just(BinaryFunc::AddNumeric).boxed(),
4722            Just(BinaryFunc::AgeTimestamp).boxed(),
4723            Just(BinaryFunc::AgeTimestampTz).boxed(),
4724            Just(BinaryFunc::BitAndInt16).boxed(),
4725            Just(BinaryFunc::BitAndInt32).boxed(),
4726            Just(BinaryFunc::BitAndInt64).boxed(),
4727            Just(BinaryFunc::BitAndUInt16).boxed(),
4728            Just(BinaryFunc::BitAndUInt32).boxed(),
4729            Just(BinaryFunc::BitAndUInt64).boxed(),
4730            Just(BinaryFunc::BitOrInt16).boxed(),
4731            Just(BinaryFunc::BitOrInt32).boxed(),
4732            Just(BinaryFunc::BitOrInt64).boxed(),
4733            Just(BinaryFunc::BitOrUInt16).boxed(),
4734            Just(BinaryFunc::BitOrUInt32).boxed(),
4735            Just(BinaryFunc::BitOrUInt64).boxed(),
4736            Just(BinaryFunc::BitXorInt16).boxed(),
4737            Just(BinaryFunc::BitXorInt32).boxed(),
4738            Just(BinaryFunc::BitXorInt64).boxed(),
4739            Just(BinaryFunc::BitXorUInt16).boxed(),
4740            Just(BinaryFunc::BitXorUInt32).boxed(),
4741            Just(BinaryFunc::BitXorUInt64).boxed(),
4742            Just(BinaryFunc::BitShiftLeftInt16).boxed(),
4743            Just(BinaryFunc::BitShiftLeftInt32).boxed(),
4744            Just(BinaryFunc::BitShiftLeftInt64).boxed(),
4745            Just(BinaryFunc::BitShiftLeftUInt16).boxed(),
4746            Just(BinaryFunc::BitShiftLeftUInt32).boxed(),
4747            Just(BinaryFunc::BitShiftLeftUInt64).boxed(),
4748            Just(BinaryFunc::BitShiftRightInt16).boxed(),
4749            Just(BinaryFunc::BitShiftRightInt32).boxed(),
4750            Just(BinaryFunc::BitShiftRightInt64).boxed(),
4751            Just(BinaryFunc::BitShiftRightUInt16).boxed(),
4752            Just(BinaryFunc::BitShiftRightUInt32).boxed(),
4753            Just(BinaryFunc::BitShiftRightUInt64).boxed(),
4754            Just(BinaryFunc::SubInt16).boxed(),
4755            Just(BinaryFunc::SubInt32).boxed(),
4756            Just(BinaryFunc::SubInt64).boxed(),
4757            Just(BinaryFunc::SubUInt16).boxed(),
4758            Just(BinaryFunc::SubUInt32).boxed(),
4759            Just(BinaryFunc::SubUInt64).boxed(),
4760            Just(BinaryFunc::SubFloat32).boxed(),
4761            Just(BinaryFunc::SubFloat64).boxed(),
4762            Just(BinaryFunc::SubInterval).boxed(),
4763            Just(BinaryFunc::SubTimestamp).boxed(),
4764            Just(BinaryFunc::SubTimestampTz).boxed(),
4765            Just(BinaryFunc::SubTimestampInterval).boxed(),
4766            Just(BinaryFunc::SubTimestampTzInterval).boxed(),
4767            Just(BinaryFunc::SubDate).boxed(),
4768            Just(BinaryFunc::SubDateInterval).boxed(),
4769            Just(BinaryFunc::SubTime).boxed(),
4770            Just(BinaryFunc::SubTimeInterval).boxed(),
4771            Just(BinaryFunc::SubNumeric).boxed(),
4772            Just(BinaryFunc::MulInt16).boxed(),
4773            Just(BinaryFunc::MulInt32).boxed(),
4774            Just(BinaryFunc::MulInt64).boxed(),
4775            Just(BinaryFunc::MulUInt16).boxed(),
4776            Just(BinaryFunc::MulUInt32).boxed(),
4777            Just(BinaryFunc::MulUInt64).boxed(),
4778            Just(BinaryFunc::MulFloat32).boxed(),
4779            Just(BinaryFunc::MulFloat64).boxed(),
4780            Just(BinaryFunc::MulNumeric).boxed(),
4781            Just(BinaryFunc::MulInterval).boxed(),
4782            Just(BinaryFunc::DivInt16).boxed(),
4783            Just(BinaryFunc::DivInt32).boxed(),
4784            Just(BinaryFunc::DivInt64).boxed(),
4785            Just(BinaryFunc::DivUInt16).boxed(),
4786            Just(BinaryFunc::DivUInt32).boxed(),
4787            Just(BinaryFunc::DivUInt64).boxed(),
4788            Just(BinaryFunc::DivFloat32).boxed(),
4789            Just(BinaryFunc::DivFloat64).boxed(),
4790            Just(BinaryFunc::DivNumeric).boxed(),
4791            Just(BinaryFunc::DivInterval).boxed(),
4792            Just(BinaryFunc::ModInt16).boxed(),
4793            Just(BinaryFunc::ModInt32).boxed(),
4794            Just(BinaryFunc::ModInt64).boxed(),
4795            Just(BinaryFunc::ModUInt16).boxed(),
4796            Just(BinaryFunc::ModUInt32).boxed(),
4797            Just(BinaryFunc::ModUInt64).boxed(),
4798            Just(BinaryFunc::ModFloat32).boxed(),
4799            Just(BinaryFunc::ModFloat64).boxed(),
4800            Just(BinaryFunc::ModNumeric).boxed(),
4801            Just(BinaryFunc::RoundNumeric).boxed(),
4802            Just(BinaryFunc::Eq).boxed(),
4803            Just(BinaryFunc::NotEq).boxed(),
4804            Just(BinaryFunc::Lt).boxed(),
4805            Just(BinaryFunc::Lte).boxed(),
4806            Just(BinaryFunc::Gt).boxed(),
4807            Just(BinaryFunc::Gte).boxed(),
4808            Just(BinaryFunc::LikeEscape).boxed(),
4809            bool::arbitrary()
4810                .prop_map(|case_insensitive| BinaryFunc::IsLikeMatch { case_insensitive })
4811                .boxed(),
4812            bool::arbitrary()
4813                .prop_map(|case_insensitive| BinaryFunc::IsRegexpMatch { case_insensitive })
4814                .boxed(),
4815            Just(BinaryFunc::ToCharTimestamp).boxed(),
4816            Just(BinaryFunc::ToCharTimestampTz).boxed(),
4817            Just(BinaryFunc::DateBinTimestamp).boxed(),
4818            Just(BinaryFunc::DateBinTimestampTz).boxed(),
4819            Just(BinaryFunc::ExtractInterval).boxed(),
4820            Just(BinaryFunc::ExtractTime).boxed(),
4821            Just(BinaryFunc::ExtractTimestamp).boxed(),
4822            Just(BinaryFunc::ExtractTimestampTz).boxed(),
4823            Just(BinaryFunc::ExtractDate).boxed(),
4824            Just(BinaryFunc::DatePartInterval).boxed(),
4825            Just(BinaryFunc::DatePartTime).boxed(),
4826            Just(BinaryFunc::DatePartTimestamp).boxed(),
4827            Just(BinaryFunc::DatePartTimestampTz).boxed(),
4828            Just(BinaryFunc::DateTruncTimestamp).boxed(),
4829            Just(BinaryFunc::DateTruncTimestampTz).boxed(),
4830            Just(BinaryFunc::DateTruncInterval).boxed(),
4831            Just(BinaryFunc::TimezoneTimestamp).boxed(),
4832            Just(BinaryFunc::TimezoneTimestampTz).boxed(),
4833            Just(BinaryFunc::TimezoneIntervalTimestamp).boxed(),
4834            Just(BinaryFunc::TimezoneIntervalTimestampTz).boxed(),
4835            Just(BinaryFunc::TimezoneIntervalTime).boxed(),
4836            Just(BinaryFunc::TimezoneOffset).boxed(),
4837            Just(BinaryFunc::TextConcat).boxed(),
4838            Just(BinaryFunc::JsonbGetInt64).boxed(),
4839            Just(BinaryFunc::JsonbGetInt64Stringify).boxed(),
4840            Just(BinaryFunc::JsonbGetString).boxed(),
4841            Just(BinaryFunc::JsonbGetStringStringify).boxed(),
4842            Just(BinaryFunc::JsonbGetPath).boxed(),
4843            Just(BinaryFunc::JsonbGetPathStringify).boxed(),
4844            Just(BinaryFunc::JsonbContainsString).boxed(),
4845            Just(BinaryFunc::JsonbConcat).boxed(),
4846            Just(BinaryFunc::JsonbContainsJsonb).boxed(),
4847            Just(BinaryFunc::JsonbDeleteInt64).boxed(),
4848            Just(BinaryFunc::JsonbDeleteString).boxed(),
4849            Just(BinaryFunc::MapContainsKey).boxed(),
4850            Just(BinaryFunc::MapGetValue).boxed(),
4851            Just(BinaryFunc::MapContainsAllKeys).boxed(),
4852            Just(BinaryFunc::MapContainsAnyKeys).boxed(),
4853            Just(BinaryFunc::MapContainsMap).boxed(),
4854            Just(BinaryFunc::ConvertFrom).boxed(),
4855            Just(BinaryFunc::Left).boxed(),
4856            Just(BinaryFunc::Position).boxed(),
4857            Just(BinaryFunc::Right).boxed(),
4858            Just(BinaryFunc::RepeatString).boxed(),
4859            Just(BinaryFunc::Trim).boxed(),
4860            Just(BinaryFunc::TrimLeading).boxed(),
4861            Just(BinaryFunc::TrimTrailing).boxed(),
4862            Just(BinaryFunc::EncodedBytesCharLength).boxed(),
4863            usize::arbitrary()
4864                .prop_map(|max_layer| BinaryFunc::ListLengthMax { max_layer })
4865                .boxed(),
4866            Just(BinaryFunc::ArrayContains).boxed(),
4867            Just(BinaryFunc::ArrayLength).boxed(),
4868            Just(BinaryFunc::ArrayLower).boxed(),
4869            Just(BinaryFunc::ArrayRemove).boxed(),
4870            Just(BinaryFunc::ArrayUpper).boxed(),
4871            Just(BinaryFunc::ArrayArrayConcat).boxed(),
4872            Just(BinaryFunc::ListListConcat).boxed(),
4873            Just(BinaryFunc::ListElementConcat).boxed(),
4874            Just(BinaryFunc::ElementListConcat).boxed(),
4875            Just(BinaryFunc::ListRemove).boxed(),
4876            Just(BinaryFunc::DigestString).boxed(),
4877            Just(BinaryFunc::DigestBytes).boxed(),
4878            Just(BinaryFunc::MzRenderTypmod).boxed(),
4879            Just(BinaryFunc::Encode).boxed(),
4880            Just(BinaryFunc::Decode).boxed(),
4881            Just(BinaryFunc::LogNumeric).boxed(),
4882            Just(BinaryFunc::Power).boxed(),
4883            Just(BinaryFunc::PowerNumeric).boxed(),
4884            (bool::arbitrary(), mz_repr::arb_range_type())
4885                .prop_map(|(rev, elem_type)| BinaryFunc::RangeContainsElem { elem_type, rev })
4886                .boxed(),
4887            bool::arbitrary()
4888                .prop_map(|rev| BinaryFunc::RangeContainsRange { rev })
4889                .boxed(),
4890            Just(BinaryFunc::RangeOverlaps).boxed(),
4891            Just(BinaryFunc::RangeAfter).boxed(),
4892            Just(BinaryFunc::RangeBefore).boxed(),
4893            Just(BinaryFunc::RangeOverleft).boxed(),
4894            Just(BinaryFunc::RangeOverright).boxed(),
4895            Just(BinaryFunc::RangeAdjacent).boxed(),
4896            Just(BinaryFunc::RangeUnion).boxed(),
4897            Just(BinaryFunc::RangeIntersection).boxed(),
4898            Just(BinaryFunc::RangeDifference).boxed(),
4899            Just(BinaryFunc::ParseIdent).boxed(),
4900        ])
4901    }
4902}
4903
4904impl RustType<ProtoBinaryFunc> for BinaryFunc {
4905    fn into_proto(&self) -> ProtoBinaryFunc {
4906        use crate::scalar::proto_binary_func::Kind::*;
4907        let kind = match self {
4908            BinaryFunc::AddInt16 => AddInt16(()),
4909            BinaryFunc::AddInt32 => AddInt32(()),
4910            BinaryFunc::AddInt64 => AddInt64(()),
4911            BinaryFunc::AddUInt16 => AddUint16(()),
4912            BinaryFunc::AddUInt32 => AddUint32(()),
4913            BinaryFunc::AddUInt64 => AddUint64(()),
4914            BinaryFunc::AddFloat32 => AddFloat32(()),
4915            BinaryFunc::AddFloat64 => AddFloat64(()),
4916            BinaryFunc::AddInterval => AddInterval(()),
4917            BinaryFunc::AddTimestampInterval => AddTimestampInterval(()),
4918            BinaryFunc::AddTimestampTzInterval => AddTimestampTzInterval(()),
4919            BinaryFunc::AddDateInterval => AddDateInterval(()),
4920            BinaryFunc::AddDateTime => AddDateTime(()),
4921            BinaryFunc::AddTimeInterval => AddTimeInterval(()),
4922            BinaryFunc::AddNumeric => AddNumeric(()),
4923            BinaryFunc::AgeTimestamp => AgeTimestamp(()),
4924            BinaryFunc::AgeTimestampTz => AgeTimestampTz(()),
4925            BinaryFunc::BitAndInt16 => BitAndInt16(()),
4926            BinaryFunc::BitAndInt32 => BitAndInt32(()),
4927            BinaryFunc::BitAndInt64 => BitAndInt64(()),
4928            BinaryFunc::BitAndUInt16 => BitAndUint16(()),
4929            BinaryFunc::BitAndUInt32 => BitAndUint32(()),
4930            BinaryFunc::BitAndUInt64 => BitAndUint64(()),
4931            BinaryFunc::BitOrInt16 => BitOrInt16(()),
4932            BinaryFunc::BitOrInt32 => BitOrInt32(()),
4933            BinaryFunc::BitOrInt64 => BitOrInt64(()),
4934            BinaryFunc::BitOrUInt16 => BitOrUint16(()),
4935            BinaryFunc::BitOrUInt32 => BitOrUint32(()),
4936            BinaryFunc::BitOrUInt64 => BitOrUint64(()),
4937            BinaryFunc::BitXorInt16 => BitXorInt16(()),
4938            BinaryFunc::BitXorInt32 => BitXorInt32(()),
4939            BinaryFunc::BitXorInt64 => BitXorInt64(()),
4940            BinaryFunc::BitXorUInt16 => BitXorUint16(()),
4941            BinaryFunc::BitXorUInt32 => BitXorUint32(()),
4942            BinaryFunc::BitXorUInt64 => BitXorUint64(()),
4943            BinaryFunc::BitShiftLeftInt16 => BitShiftLeftInt16(()),
4944            BinaryFunc::BitShiftLeftInt32 => BitShiftLeftInt32(()),
4945            BinaryFunc::BitShiftLeftInt64 => BitShiftLeftInt64(()),
4946            BinaryFunc::BitShiftLeftUInt16 => BitShiftLeftUint16(()),
4947            BinaryFunc::BitShiftLeftUInt32 => BitShiftLeftUint32(()),
4948            BinaryFunc::BitShiftLeftUInt64 => BitShiftLeftUint64(()),
4949            BinaryFunc::BitShiftRightInt16 => BitShiftRightInt16(()),
4950            BinaryFunc::BitShiftRightInt32 => BitShiftRightInt32(()),
4951            BinaryFunc::BitShiftRightInt64 => BitShiftRightInt64(()),
4952            BinaryFunc::BitShiftRightUInt16 => BitShiftRightUint16(()),
4953            BinaryFunc::BitShiftRightUInt32 => BitShiftRightUint32(()),
4954            BinaryFunc::BitShiftRightUInt64 => BitShiftRightUint64(()),
4955            BinaryFunc::SubInt16 => SubInt16(()),
4956            BinaryFunc::SubInt32 => SubInt32(()),
4957            BinaryFunc::SubInt64 => SubInt64(()),
4958            BinaryFunc::SubUInt16 => SubUint16(()),
4959            BinaryFunc::SubUInt32 => SubUint32(()),
4960            BinaryFunc::SubUInt64 => SubUint64(()),
4961            BinaryFunc::SubFloat32 => SubFloat32(()),
4962            BinaryFunc::SubFloat64 => SubFloat64(()),
4963            BinaryFunc::SubInterval => SubInterval(()),
4964            BinaryFunc::SubTimestamp => SubTimestamp(()),
4965            BinaryFunc::SubTimestampTz => SubTimestampTz(()),
4966            BinaryFunc::SubTimestampInterval => SubTimestampInterval(()),
4967            BinaryFunc::SubTimestampTzInterval => SubTimestampTzInterval(()),
4968            BinaryFunc::SubDate => SubDate(()),
4969            BinaryFunc::SubDateInterval => SubDateInterval(()),
4970            BinaryFunc::SubTime => SubTime(()),
4971            BinaryFunc::SubTimeInterval => SubTimeInterval(()),
4972            BinaryFunc::SubNumeric => SubNumeric(()),
4973            BinaryFunc::MulInt16 => MulInt16(()),
4974            BinaryFunc::MulInt32 => MulInt32(()),
4975            BinaryFunc::MulInt64 => MulInt64(()),
4976            BinaryFunc::MulUInt16 => MulUint16(()),
4977            BinaryFunc::MulUInt32 => MulUint32(()),
4978            BinaryFunc::MulUInt64 => MulUint64(()),
4979            BinaryFunc::MulFloat32 => MulFloat32(()),
4980            BinaryFunc::MulFloat64 => MulFloat64(()),
4981            BinaryFunc::MulNumeric => MulNumeric(()),
4982            BinaryFunc::MulInterval => MulInterval(()),
4983            BinaryFunc::DivInt16 => DivInt16(()),
4984            BinaryFunc::DivInt32 => DivInt32(()),
4985            BinaryFunc::DivInt64 => DivInt64(()),
4986            BinaryFunc::DivUInt16 => DivUint16(()),
4987            BinaryFunc::DivUInt32 => DivUint32(()),
4988            BinaryFunc::DivUInt64 => DivUint64(()),
4989            BinaryFunc::DivFloat32 => DivFloat32(()),
4990            BinaryFunc::DivFloat64 => DivFloat64(()),
4991            BinaryFunc::DivNumeric => DivNumeric(()),
4992            BinaryFunc::DivInterval => DivInterval(()),
4993            BinaryFunc::ModInt16 => ModInt16(()),
4994            BinaryFunc::ModInt32 => ModInt32(()),
4995            BinaryFunc::ModInt64 => ModInt64(()),
4996            BinaryFunc::ModUInt16 => ModUint16(()),
4997            BinaryFunc::ModUInt32 => ModUint32(()),
4998            BinaryFunc::ModUInt64 => ModUint64(()),
4999            BinaryFunc::ModFloat32 => ModFloat32(()),
5000            BinaryFunc::ModFloat64 => ModFloat64(()),
5001            BinaryFunc::ModNumeric => ModNumeric(()),
5002            BinaryFunc::RoundNumeric => RoundNumeric(()),
5003            BinaryFunc::Eq => Eq(()),
5004            BinaryFunc::NotEq => NotEq(()),
5005            BinaryFunc::Lt => Lt(()),
5006            BinaryFunc::Lte => Lte(()),
5007            BinaryFunc::Gt => Gt(()),
5008            BinaryFunc::Gte => Gte(()),
5009            BinaryFunc::LikeEscape => LikeEscape(()),
5010            BinaryFunc::IsLikeMatch { case_insensitive } => IsLikeMatch(*case_insensitive),
5011            BinaryFunc::IsRegexpMatch { case_insensitive } => IsRegexpMatch(*case_insensitive),
5012            BinaryFunc::ToCharTimestamp => ToCharTimestamp(()),
5013            BinaryFunc::ToCharTimestampTz => ToCharTimestampTz(()),
5014            BinaryFunc::DateBinTimestamp => DateBinTimestamp(()),
5015            BinaryFunc::DateBinTimestampTz => DateBinTimestampTz(()),
5016            BinaryFunc::ExtractInterval => ExtractInterval(()),
5017            BinaryFunc::ExtractTime => ExtractTime(()),
5018            BinaryFunc::ExtractTimestamp => ExtractTimestamp(()),
5019            BinaryFunc::ExtractTimestampTz => ExtractTimestampTz(()),
5020            BinaryFunc::ExtractDate => ExtractDate(()),
5021            BinaryFunc::DatePartInterval => DatePartInterval(()),
5022            BinaryFunc::DatePartTime => DatePartTime(()),
5023            BinaryFunc::DatePartTimestamp => DatePartTimestamp(()),
5024            BinaryFunc::DatePartTimestampTz => DatePartTimestampTz(()),
5025            BinaryFunc::DateTruncTimestamp => DateTruncTimestamp(()),
5026            BinaryFunc::DateTruncTimestampTz => DateTruncTimestampTz(()),
5027            BinaryFunc::DateTruncInterval => DateTruncInterval(()),
5028            BinaryFunc::TimezoneTimestamp => TimezoneTimestamp(()),
5029            BinaryFunc::TimezoneTimestampTz => TimezoneTimestampTz(()),
5030            BinaryFunc::TimezoneIntervalTimestamp => TimezoneIntervalTimestamp(()),
5031            BinaryFunc::TimezoneIntervalTimestampTz => TimezoneIntervalTimestampTz(()),
5032            BinaryFunc::TimezoneIntervalTime => TimezoneIntervalTime(()),
5033            BinaryFunc::TimezoneOffset => TimezoneOffset(()),
5034            BinaryFunc::TextConcat => TextConcat(()),
5035            BinaryFunc::JsonbGetInt64 => JsonbGetInt64(()),
5036            BinaryFunc::JsonbGetInt64Stringify => JsonbGetInt64Stringify(()),
5037            BinaryFunc::JsonbGetString => JsonbGetString(()),
5038            BinaryFunc::JsonbGetStringStringify => JsonbGetStringStringify(()),
5039            BinaryFunc::JsonbGetPath => JsonbGetPath(()),
5040            BinaryFunc::JsonbGetPathStringify => JsonbGetPathStringify(()),
5041            BinaryFunc::JsonbContainsString => JsonbContainsString(()),
5042            BinaryFunc::JsonbConcat => JsonbConcat(()),
5043            BinaryFunc::JsonbContainsJsonb => JsonbContainsJsonb(()),
5044            BinaryFunc::JsonbDeleteInt64 => JsonbDeleteInt64(()),
5045            BinaryFunc::JsonbDeleteString => JsonbDeleteString(()),
5046            BinaryFunc::MapContainsKey => MapContainsKey(()),
5047            BinaryFunc::MapGetValue => MapGetValue(()),
5048            BinaryFunc::MapContainsAllKeys => MapContainsAllKeys(()),
5049            BinaryFunc::MapContainsAnyKeys => MapContainsAnyKeys(()),
5050            BinaryFunc::MapContainsMap => MapContainsMap(()),
5051            BinaryFunc::ConvertFrom => ConvertFrom(()),
5052            BinaryFunc::Left => Left(()),
5053            BinaryFunc::Position => Position(()),
5054            BinaryFunc::Right => Right(()),
5055            BinaryFunc::RepeatString => RepeatString(()),
5056            BinaryFunc::Trim => Trim(()),
5057            BinaryFunc::TrimLeading => TrimLeading(()),
5058            BinaryFunc::TrimTrailing => TrimTrailing(()),
5059            BinaryFunc::EncodedBytesCharLength => EncodedBytesCharLength(()),
5060            BinaryFunc::ListLengthMax { max_layer } => ListLengthMax(max_layer.into_proto()),
5061            BinaryFunc::ArrayContains => ArrayContains(()),
5062            BinaryFunc::ArrayContainsArray { rev } => ArrayContainsArray(*rev),
5063            BinaryFunc::ArrayLength => ArrayLength(()),
5064            BinaryFunc::ArrayLower => ArrayLower(()),
5065            BinaryFunc::ArrayRemove => ArrayRemove(()),
5066            BinaryFunc::ArrayUpper => ArrayUpper(()),
5067            BinaryFunc::ArrayArrayConcat => ArrayArrayConcat(()),
5068            BinaryFunc::ListListConcat => ListListConcat(()),
5069            BinaryFunc::ListElementConcat => ListElementConcat(()),
5070            BinaryFunc::ElementListConcat => ElementListConcat(()),
5071            BinaryFunc::ListRemove => ListRemove(()),
5072            BinaryFunc::ListContainsList { rev } => ListContainsList(*rev),
5073            BinaryFunc::DigestString => DigestString(()),
5074            BinaryFunc::DigestBytes => DigestBytes(()),
5075            BinaryFunc::MzRenderTypmod => MzRenderTypmod(()),
5076            BinaryFunc::Encode => Encode(()),
5077            BinaryFunc::Decode => Decode(()),
5078            BinaryFunc::LogNumeric => LogNumeric(()),
5079            BinaryFunc::Power => Power(()),
5080            BinaryFunc::PowerNumeric => PowerNumeric(()),
5081            BinaryFunc::GetBit => GetBit(()),
5082            BinaryFunc::GetByte => GetByte(()),
5083            BinaryFunc::RangeContainsElem { elem_type, rev } => {
5084                RangeContainsElem(crate::scalar::proto_binary_func::ProtoRangeContainsInner {
5085                    elem_type: Some(elem_type.into_proto()),
5086                    rev: *rev,
5087                })
5088            }
5089            BinaryFunc::RangeContainsRange { rev } => RangeContainsRange(*rev),
5090            BinaryFunc::RangeOverlaps => RangeOverlaps(()),
5091            BinaryFunc::RangeAfter => RangeAfter(()),
5092            BinaryFunc::RangeBefore => RangeBefore(()),
5093            BinaryFunc::RangeOverleft => RangeOverleft(()),
5094            BinaryFunc::RangeOverright => RangeOverright(()),
5095            BinaryFunc::RangeAdjacent => RangeAdjacent(()),
5096            BinaryFunc::RangeUnion => RangeUnion(()),
5097            BinaryFunc::RangeIntersection => RangeIntersection(()),
5098            BinaryFunc::RangeDifference => RangeDifference(()),
5099            BinaryFunc::UuidGenerateV5 => UuidGenerateV5(()),
5100            BinaryFunc::MzAclItemContainsPrivilege => MzAclItemContainsPrivilege(()),
5101            BinaryFunc::ParseIdent => ParseIdent(()),
5102            BinaryFunc::ConstantTimeEqBytes => ConstantTimeEqBytes(()),
5103            BinaryFunc::ConstantTimeEqString => ConstantTimeEqString(()),
5104            BinaryFunc::PrettySql => PrettySql(()),
5105            BinaryFunc::RegexpReplace { regex, limit } => {
5106                use crate::scalar::proto_binary_func::*;
5107                RegexpReplace(ProtoRegexpReplace {
5108                    regex: Some(regex.into_proto()),
5109                    limit: limit.into_proto(),
5110                })
5111            }
5112            BinaryFunc::StartsWith => StartsWith(()),
5113        };
5114        ProtoBinaryFunc { kind: Some(kind) }
5115    }
5116
5117    fn from_proto(proto: ProtoBinaryFunc) -> Result<Self, TryFromProtoError> {
5118        use crate::scalar::proto_binary_func::Kind::*;
5119        if let Some(kind) = proto.kind {
5120            match kind {
5121                AddInt16(()) => Ok(BinaryFunc::AddInt16),
5122                AddInt32(()) => Ok(BinaryFunc::AddInt32),
5123                AddInt64(()) => Ok(BinaryFunc::AddInt64),
5124                AddUint16(()) => Ok(BinaryFunc::AddUInt16),
5125                AddUint32(()) => Ok(BinaryFunc::AddUInt32),
5126                AddUint64(()) => Ok(BinaryFunc::AddUInt64),
5127                AddFloat32(()) => Ok(BinaryFunc::AddFloat32),
5128                AddFloat64(()) => Ok(BinaryFunc::AddFloat64),
5129                AddInterval(()) => Ok(BinaryFunc::AddInterval),
5130                AddTimestampInterval(()) => Ok(BinaryFunc::AddTimestampInterval),
5131                AddTimestampTzInterval(()) => Ok(BinaryFunc::AddTimestampTzInterval),
5132                AddDateInterval(()) => Ok(BinaryFunc::AddDateInterval),
5133                AddDateTime(()) => Ok(BinaryFunc::AddDateTime),
5134                AddTimeInterval(()) => Ok(BinaryFunc::AddTimeInterval),
5135                AddNumeric(()) => Ok(BinaryFunc::AddNumeric),
5136                AgeTimestamp(()) => Ok(BinaryFunc::AgeTimestamp),
5137                AgeTimestampTz(()) => Ok(BinaryFunc::AgeTimestampTz),
5138                BitAndInt16(()) => Ok(BinaryFunc::BitAndInt16),
5139                BitAndInt32(()) => Ok(BinaryFunc::BitAndInt32),
5140                BitAndInt64(()) => Ok(BinaryFunc::BitAndInt64),
5141                BitAndUint16(()) => Ok(BinaryFunc::BitAndUInt16),
5142                BitAndUint32(()) => Ok(BinaryFunc::BitAndUInt32),
5143                BitAndUint64(()) => Ok(BinaryFunc::BitAndUInt64),
5144                BitOrInt16(()) => Ok(BinaryFunc::BitOrInt16),
5145                BitOrInt32(()) => Ok(BinaryFunc::BitOrInt32),
5146                BitOrInt64(()) => Ok(BinaryFunc::BitOrInt64),
5147                BitOrUint16(()) => Ok(BinaryFunc::BitOrUInt16),
5148                BitOrUint32(()) => Ok(BinaryFunc::BitOrUInt32),
5149                BitOrUint64(()) => Ok(BinaryFunc::BitOrUInt64),
5150                BitXorInt16(()) => Ok(BinaryFunc::BitXorInt16),
5151                BitXorInt32(()) => Ok(BinaryFunc::BitXorInt32),
5152                BitXorInt64(()) => Ok(BinaryFunc::BitXorInt64),
5153                BitXorUint16(()) => Ok(BinaryFunc::BitXorUInt16),
5154                BitXorUint32(()) => Ok(BinaryFunc::BitXorUInt32),
5155                BitXorUint64(()) => Ok(BinaryFunc::BitXorUInt64),
5156                BitShiftLeftInt16(()) => Ok(BinaryFunc::BitShiftLeftInt16),
5157                BitShiftLeftInt32(()) => Ok(BinaryFunc::BitShiftLeftInt32),
5158                BitShiftLeftInt64(()) => Ok(BinaryFunc::BitShiftLeftInt64),
5159                BitShiftLeftUint16(()) => Ok(BinaryFunc::BitShiftLeftUInt16),
5160                BitShiftLeftUint32(()) => Ok(BinaryFunc::BitShiftLeftUInt32),
5161                BitShiftLeftUint64(()) => Ok(BinaryFunc::BitShiftLeftUInt64),
5162                BitShiftRightInt16(()) => Ok(BinaryFunc::BitShiftRightInt16),
5163                BitShiftRightInt32(()) => Ok(BinaryFunc::BitShiftRightInt32),
5164                BitShiftRightInt64(()) => Ok(BinaryFunc::BitShiftRightInt64),
5165                BitShiftRightUint16(()) => Ok(BinaryFunc::BitShiftRightUInt16),
5166                BitShiftRightUint32(()) => Ok(BinaryFunc::BitShiftRightUInt32),
5167                BitShiftRightUint64(()) => Ok(BinaryFunc::BitShiftRightUInt64),
5168                SubInt16(()) => Ok(BinaryFunc::SubInt16),
5169                SubInt32(()) => Ok(BinaryFunc::SubInt32),
5170                SubInt64(()) => Ok(BinaryFunc::SubInt64),
5171                SubUint16(()) => Ok(BinaryFunc::SubUInt16),
5172                SubUint32(()) => Ok(BinaryFunc::SubUInt32),
5173                SubUint64(()) => Ok(BinaryFunc::SubUInt64),
5174                SubFloat32(()) => Ok(BinaryFunc::SubFloat32),
5175                SubFloat64(()) => Ok(BinaryFunc::SubFloat64),
5176                SubInterval(()) => Ok(BinaryFunc::SubInterval),
5177                SubTimestamp(()) => Ok(BinaryFunc::SubTimestamp),
5178                SubTimestampTz(()) => Ok(BinaryFunc::SubTimestampTz),
5179                SubTimestampInterval(()) => Ok(BinaryFunc::SubTimestampInterval),
5180                SubTimestampTzInterval(()) => Ok(BinaryFunc::SubTimestampTzInterval),
5181                SubDate(()) => Ok(BinaryFunc::SubDate),
5182                SubDateInterval(()) => Ok(BinaryFunc::SubDateInterval),
5183                SubTime(()) => Ok(BinaryFunc::SubTime),
5184                SubTimeInterval(()) => Ok(BinaryFunc::SubTimeInterval),
5185                SubNumeric(()) => Ok(BinaryFunc::SubNumeric),
5186                MulInt16(()) => Ok(BinaryFunc::MulInt16),
5187                MulInt32(()) => Ok(BinaryFunc::MulInt32),
5188                MulInt64(()) => Ok(BinaryFunc::MulInt64),
5189                MulUint16(()) => Ok(BinaryFunc::MulUInt16),
5190                MulUint32(()) => Ok(BinaryFunc::MulUInt32),
5191                MulUint64(()) => Ok(BinaryFunc::MulUInt64),
5192                MulFloat32(()) => Ok(BinaryFunc::MulFloat32),
5193                MulFloat64(()) => Ok(BinaryFunc::MulFloat64),
5194                MulNumeric(()) => Ok(BinaryFunc::MulNumeric),
5195                MulInterval(()) => Ok(BinaryFunc::MulInterval),
5196                DivInt16(()) => Ok(BinaryFunc::DivInt16),
5197                DivInt32(()) => Ok(BinaryFunc::DivInt32),
5198                DivInt64(()) => Ok(BinaryFunc::DivInt64),
5199                DivUint16(()) => Ok(BinaryFunc::DivUInt16),
5200                DivUint32(()) => Ok(BinaryFunc::DivUInt32),
5201                DivUint64(()) => Ok(BinaryFunc::DivUInt64),
5202                DivFloat32(()) => Ok(BinaryFunc::DivFloat32),
5203                DivFloat64(()) => Ok(BinaryFunc::DivFloat64),
5204                DivNumeric(()) => Ok(BinaryFunc::DivNumeric),
5205                DivInterval(()) => Ok(BinaryFunc::DivInterval),
5206                ModInt16(()) => Ok(BinaryFunc::ModInt16),
5207                ModInt32(()) => Ok(BinaryFunc::ModInt32),
5208                ModInt64(()) => Ok(BinaryFunc::ModInt64),
5209                ModUint16(()) => Ok(BinaryFunc::ModUInt16),
5210                ModUint32(()) => Ok(BinaryFunc::ModUInt32),
5211                ModUint64(()) => Ok(BinaryFunc::ModUInt64),
5212                ModFloat32(()) => Ok(BinaryFunc::ModFloat32),
5213                ModFloat64(()) => Ok(BinaryFunc::ModFloat64),
5214                ModNumeric(()) => Ok(BinaryFunc::ModNumeric),
5215                RoundNumeric(()) => Ok(BinaryFunc::RoundNumeric),
5216                Eq(()) => Ok(BinaryFunc::Eq),
5217                NotEq(()) => Ok(BinaryFunc::NotEq),
5218                Lt(()) => Ok(BinaryFunc::Lt),
5219                Lte(()) => Ok(BinaryFunc::Lte),
5220                Gt(()) => Ok(BinaryFunc::Gt),
5221                Gte(()) => Ok(BinaryFunc::Gte),
5222                LikeEscape(()) => Ok(BinaryFunc::LikeEscape),
5223                IsLikeMatch(case_insensitive) => Ok(BinaryFunc::IsLikeMatch { case_insensitive }),
5224                IsRegexpMatch(case_insensitive) => {
5225                    Ok(BinaryFunc::IsRegexpMatch { case_insensitive })
5226                }
5227                ToCharTimestamp(()) => Ok(BinaryFunc::ToCharTimestamp),
5228                ToCharTimestampTz(()) => Ok(BinaryFunc::ToCharTimestampTz),
5229                DateBinTimestamp(()) => Ok(BinaryFunc::DateBinTimestamp),
5230                DateBinTimestampTz(()) => Ok(BinaryFunc::DateBinTimestampTz),
5231                ExtractInterval(()) => Ok(BinaryFunc::ExtractInterval),
5232                ExtractTime(()) => Ok(BinaryFunc::ExtractTime),
5233                ExtractTimestamp(()) => Ok(BinaryFunc::ExtractTimestamp),
5234                ExtractTimestampTz(()) => Ok(BinaryFunc::ExtractTimestampTz),
5235                ExtractDate(()) => Ok(BinaryFunc::ExtractDate),
5236                DatePartInterval(()) => Ok(BinaryFunc::DatePartInterval),
5237                DatePartTime(()) => Ok(BinaryFunc::DatePartTime),
5238                DatePartTimestamp(()) => Ok(BinaryFunc::DatePartTimestamp),
5239                DatePartTimestampTz(()) => Ok(BinaryFunc::DatePartTimestampTz),
5240                DateTruncTimestamp(()) => Ok(BinaryFunc::DateTruncTimestamp),
5241                DateTruncTimestampTz(()) => Ok(BinaryFunc::DateTruncTimestampTz),
5242                DateTruncInterval(()) => Ok(BinaryFunc::DateTruncInterval),
5243                TimezoneTimestamp(()) => Ok(BinaryFunc::TimezoneTimestamp),
5244                TimezoneTimestampTz(()) => Ok(BinaryFunc::TimezoneTimestampTz),
5245                TimezoneIntervalTimestamp(()) => Ok(BinaryFunc::TimezoneIntervalTimestamp),
5246                TimezoneIntervalTimestampTz(()) => Ok(BinaryFunc::TimezoneIntervalTimestampTz),
5247                TimezoneIntervalTime(()) => Ok(BinaryFunc::TimezoneIntervalTime),
5248                TimezoneOffset(()) => Ok(BinaryFunc::TimezoneOffset),
5249                TextConcat(()) => Ok(BinaryFunc::TextConcat),
5250                JsonbGetInt64(()) => Ok(BinaryFunc::JsonbGetInt64),
5251                JsonbGetInt64Stringify(()) => Ok(BinaryFunc::JsonbGetInt64Stringify),
5252                JsonbGetString(()) => Ok(BinaryFunc::JsonbGetString),
5253                JsonbGetStringStringify(()) => Ok(BinaryFunc::JsonbGetStringStringify),
5254                JsonbGetPath(()) => Ok(BinaryFunc::JsonbGetPath),
5255                JsonbGetPathStringify(()) => Ok(BinaryFunc::JsonbGetPathStringify),
5256                JsonbContainsString(()) => Ok(BinaryFunc::JsonbContainsString),
5257                JsonbConcat(()) => Ok(BinaryFunc::JsonbConcat),
5258                JsonbContainsJsonb(()) => Ok(BinaryFunc::JsonbContainsJsonb),
5259                JsonbDeleteInt64(()) => Ok(BinaryFunc::JsonbDeleteInt64),
5260                JsonbDeleteString(()) => Ok(BinaryFunc::JsonbDeleteString),
5261                MapContainsKey(()) => Ok(BinaryFunc::MapContainsKey),
5262                MapGetValue(()) => Ok(BinaryFunc::MapGetValue),
5263                MapContainsAllKeys(()) => Ok(BinaryFunc::MapContainsAllKeys),
5264                MapContainsAnyKeys(()) => Ok(BinaryFunc::MapContainsAnyKeys),
5265                MapContainsMap(()) => Ok(BinaryFunc::MapContainsMap),
5266                ConvertFrom(()) => Ok(BinaryFunc::ConvertFrom),
5267                Left(()) => Ok(BinaryFunc::Left),
5268                Position(()) => Ok(BinaryFunc::Position),
5269                Right(()) => Ok(BinaryFunc::Right),
5270                RepeatString(()) => Ok(BinaryFunc::RepeatString),
5271                Trim(()) => Ok(BinaryFunc::Trim),
5272                TrimLeading(()) => Ok(BinaryFunc::TrimLeading),
5273                TrimTrailing(()) => Ok(BinaryFunc::TrimTrailing),
5274                EncodedBytesCharLength(()) => Ok(BinaryFunc::EncodedBytesCharLength),
5275                ListLengthMax(max_layer) => Ok(BinaryFunc::ListLengthMax {
5276                    max_layer: max_layer.into_rust()?,
5277                }),
5278                ArrayContains(()) => Ok(BinaryFunc::ArrayContains),
5279                ArrayContainsArray(rev) => Ok(BinaryFunc::ArrayContainsArray { rev }),
5280                ArrayLength(()) => Ok(BinaryFunc::ArrayLength),
5281                ArrayLower(()) => Ok(BinaryFunc::ArrayLower),
5282                ArrayRemove(()) => Ok(BinaryFunc::ArrayRemove),
5283                ArrayUpper(()) => Ok(BinaryFunc::ArrayUpper),
5284                ArrayArrayConcat(()) => Ok(BinaryFunc::ArrayArrayConcat),
5285                ListListConcat(()) => Ok(BinaryFunc::ListListConcat),
5286                ListElementConcat(()) => Ok(BinaryFunc::ListElementConcat),
5287                ElementListConcat(()) => Ok(BinaryFunc::ElementListConcat),
5288                ListRemove(()) => Ok(BinaryFunc::ListRemove),
5289                ListContainsList(rev) => Ok(BinaryFunc::ListContainsList { rev }),
5290                DigestString(()) => Ok(BinaryFunc::DigestString),
5291                DigestBytes(()) => Ok(BinaryFunc::DigestBytes),
5292                MzRenderTypmod(()) => Ok(BinaryFunc::MzRenderTypmod),
5293                Encode(()) => Ok(BinaryFunc::Encode),
5294                Decode(()) => Ok(BinaryFunc::Decode),
5295                LogNumeric(()) => Ok(BinaryFunc::LogNumeric),
5296                Power(()) => Ok(BinaryFunc::Power),
5297                PowerNumeric(()) => Ok(BinaryFunc::PowerNumeric),
5298                GetBit(()) => Ok(BinaryFunc::GetBit),
5299                GetByte(()) => Ok(BinaryFunc::GetByte),
5300                RangeContainsElem(inner) => Ok(BinaryFunc::RangeContainsElem {
5301                    elem_type: inner
5302                        .elem_type
5303                        .into_rust_if_some("ProtoRangeContainsInner::elem_type")?,
5304                    rev: inner.rev,
5305                }),
5306                RangeContainsRange(rev) => Ok(BinaryFunc::RangeContainsRange { rev }),
5307                RangeOverlaps(()) => Ok(BinaryFunc::RangeOverlaps),
5308                RangeAfter(()) => Ok(BinaryFunc::RangeAfter),
5309                RangeBefore(()) => Ok(BinaryFunc::RangeBefore),
5310                RangeOverleft(()) => Ok(BinaryFunc::RangeOverleft),
5311                RangeOverright(()) => Ok(BinaryFunc::RangeOverright),
5312                RangeAdjacent(()) => Ok(BinaryFunc::RangeAdjacent),
5313                RangeUnion(()) => Ok(BinaryFunc::RangeUnion),
5314                RangeIntersection(()) => Ok(BinaryFunc::RangeIntersection),
5315                RangeDifference(()) => Ok(BinaryFunc::RangeDifference),
5316                UuidGenerateV5(()) => Ok(BinaryFunc::UuidGenerateV5),
5317                MzAclItemContainsPrivilege(()) => Ok(BinaryFunc::MzAclItemContainsPrivilege),
5318                ParseIdent(()) => Ok(BinaryFunc::ParseIdent),
5319                ConstantTimeEqBytes(()) => Ok(BinaryFunc::ConstantTimeEqBytes),
5320                ConstantTimeEqString(()) => Ok(BinaryFunc::ConstantTimeEqString),
5321                PrettySql(()) => Ok(BinaryFunc::PrettySql),
5322                RegexpReplace(inner) => Ok(BinaryFunc::RegexpReplace {
5323                    regex: inner.regex.into_rust_if_some("ProtoRegexReplace::regex")?,
5324                    limit: inner.limit.into_rust()?,
5325                }),
5326                StartsWith(()) => Ok(BinaryFunc::StartsWith),
5327            }
5328        } else {
5329            Err(TryFromProtoError::missing_field("ProtoBinaryFunc::kind"))
5330        }
5331    }
5332}
5333
5334/// A description of an SQL unary function that has the ability to lazy evaluate its arguments
5335// This trait will eventually be annotated with #[enum_dispatch] to autogenerate the UnaryFunc enum
5336trait LazyUnaryFunc {
5337    fn eval<'a>(
5338        &'a self,
5339        datums: &[Datum<'a>],
5340        temp_storage: &'a RowArena,
5341        a: &'a MirScalarExpr,
5342    ) -> Result<Datum<'a>, EvalError>;
5343
5344    /// The output ColumnType of this function.
5345    fn output_type(&self, input_type: ColumnType) -> ColumnType;
5346
5347    /// Whether this function will produce NULL on NULL input.
5348    fn propagates_nulls(&self) -> bool;
5349
5350    /// Whether this function will produce NULL on non-NULL input.
5351    fn introduces_nulls(&self) -> bool;
5352
5353    /// Whether this function might error on non-error input.
5354    fn could_error(&self) -> bool {
5355        // NB: override this for functions that never error.
5356        true
5357    }
5358
5359    /// Whether this function preserves uniqueness.
5360    ///
5361    /// Uniqueness is preserved when `if f(x) = f(y) then x = y` is true. This
5362    /// is used by the optimizer when a guarantee can be made that a collection
5363    /// with unique items will stay unique when mapped by this function.
5364    ///
5365    /// Note that error results are not covered: Even with `preserves_uniqueness = true`, it can
5366    /// happen that two different inputs produce the same error result. (e.g., in case of a
5367    /// narrowing cast)
5368    ///
5369    /// Functions should conservatively return `false` unless they are certain
5370    /// the above property is true.
5371    fn preserves_uniqueness(&self) -> bool;
5372
5373    /// The [inverse] of this function, if it has one and we have determined it.
5374    ///
5375    /// The optimizer _can_ use this information when selecting indexes, e.g. an
5376    /// indexed column has a cast applied to it, by moving the right inverse of
5377    /// the cast to another value, we can select the indexed column.
5378    ///
5379    /// Note that a value of `None` does not imply that the inverse does not
5380    /// exist; it could also mean we have not yet invested the energy in
5381    /// representing it. For example, in the case of complex casts, such as
5382    /// between two list types, we could determine the right inverse, but doing
5383    /// so is not immediately necessary as this information is only used by the
5384    /// optimizer.
5385    ///
5386    /// ## Right vs. left vs. inverses
5387    /// - Right inverses are when the inverse function preserves uniqueness.
5388    ///   These are the functions that the optimizer uses to move casts between
5389    ///   expressions.
5390    /// - Left inverses are when the function itself preserves uniqueness.
5391    /// - Inverses are when a function is both a right and a left inverse (e.g.,
5392    ///   bit_not_int64 is both a right and left inverse of itself).
5393    ///
5394    /// We call this function `inverse` for simplicity's sake; it doesn't always
5395    /// correspond to the mathematical notion of "inverse." However, in
5396    /// conjunction with checks to `preserves_uniqueness` you can determine
5397    /// which type of inverse we return.
5398    ///
5399    /// [inverse]: https://en.wikipedia.org/wiki/Inverse_function
5400    fn inverse(&self) -> Option<crate::UnaryFunc>;
5401
5402    /// Returns true if the function is monotone. (Non-strict; either increasing or decreasing.)
5403    /// Monotone functions map ranges to ranges: ie. given a range of possible inputs, we can
5404    /// determine the range of possible outputs just by mapping the endpoints.
5405    ///
5406    /// This property describes the behaviour of the function over ranges where the function is defined:
5407    /// ie. the argument and the result are non-error datums.
5408    fn is_monotone(&self) -> bool;
5409}
5410
5411/// A description of an SQL unary function that operates on eagerly evaluated expressions
5412trait EagerUnaryFunc<'a> {
5413    type Input: DatumType<'a, EvalError>;
5414    type Output: DatumType<'a, EvalError>;
5415
5416    fn call(&self, input: Self::Input) -> Self::Output;
5417
5418    /// The output ColumnType of this function
5419    fn output_type(&self, input_type: ColumnType) -> ColumnType;
5420
5421    /// Whether this function will produce NULL on NULL input
5422    fn propagates_nulls(&self) -> bool {
5423        // If the input is not nullable then nulls are propagated
5424        !Self::Input::nullable()
5425    }
5426
5427    /// Whether this function will produce NULL on non-NULL input
5428    fn introduces_nulls(&self) -> bool {
5429        // If the output is nullable then nulls can be introduced
5430        Self::Output::nullable()
5431    }
5432
5433    /// Whether this function could produce an error
5434    fn could_error(&self) -> bool {
5435        Self::Output::fallible()
5436    }
5437
5438    /// Whether this function preserves uniqueness
5439    fn preserves_uniqueness(&self) -> bool {
5440        false
5441    }
5442
5443    fn inverse(&self) -> Option<crate::UnaryFunc> {
5444        None
5445    }
5446
5447    fn is_monotone(&self) -> bool {
5448        false
5449    }
5450}
5451
5452impl<T: for<'a> EagerUnaryFunc<'a>> LazyUnaryFunc for T {
5453    fn eval<'a>(
5454        &'a self,
5455        datums: &[Datum<'a>],
5456        temp_storage: &'a RowArena,
5457        a: &'a MirScalarExpr,
5458    ) -> Result<Datum<'a>, EvalError> {
5459        match T::Input::try_from_result(a.eval(datums, temp_storage)) {
5460            // If we can convert to the input type then we call the function
5461            Ok(input) => self.call(input).into_result(temp_storage),
5462            // If we can't and we got a non-null datum something went wrong in the planner
5463            Err(Ok(datum)) if !datum.is_null() => {
5464                Err(EvalError::Internal("invalid input type".into()))
5465            }
5466            // Otherwise we just propagate NULLs and errors
5467            Err(res) => res,
5468        }
5469    }
5470
5471    fn output_type(&self, input_type: ColumnType) -> ColumnType {
5472        self.output_type(input_type)
5473    }
5474
5475    fn propagates_nulls(&self) -> bool {
5476        self.propagates_nulls()
5477    }
5478
5479    fn introduces_nulls(&self) -> bool {
5480        self.introduces_nulls()
5481    }
5482
5483    fn could_error(&self) -> bool {
5484        self.could_error()
5485    }
5486
5487    fn preserves_uniqueness(&self) -> bool {
5488        self.preserves_uniqueness()
5489    }
5490
5491    fn inverse(&self) -> Option<crate::UnaryFunc> {
5492        self.inverse()
5493    }
5494
5495    fn is_monotone(&self) -> bool {
5496        self.is_monotone()
5497    }
5498}
5499
5500derive_unary!(
5501    Not,
5502    IsNull,
5503    IsTrue,
5504    IsFalse,
5505    BitNotInt16,
5506    BitNotInt32,
5507    BitNotInt64,
5508    BitNotUint16,
5509    BitNotUint32,
5510    BitNotUint64,
5511    NegInt16,
5512    NegInt32,
5513    NegInt64,
5514    NegFloat32,
5515    NegFloat64,
5516    NegNumeric,
5517    NegInterval,
5518    SqrtFloat64,
5519    SqrtNumeric,
5520    CbrtFloat64,
5521    AbsInt16,
5522    AbsInt32,
5523    AbsInt64,
5524    AbsFloat32,
5525    AbsFloat64,
5526    AbsNumeric,
5527    CastBoolToString,
5528    CastBoolToStringNonstandard,
5529    CastBoolToInt32,
5530    CastBoolToInt64,
5531    CastInt16ToFloat32,
5532    CastInt16ToFloat64,
5533    CastInt16ToInt32,
5534    CastInt16ToInt64,
5535    CastInt16ToUint16,
5536    CastInt16ToUint32,
5537    CastInt16ToUint64,
5538    CastInt16ToString,
5539    CastInt2VectorToArray,
5540    CastInt32ToBool,
5541    CastInt32ToFloat32,
5542    CastInt32ToFloat64,
5543    CastInt32ToOid,
5544    CastInt32ToPgLegacyChar,
5545    CastInt32ToInt16,
5546    CastInt32ToInt64,
5547    CastInt32ToUint16,
5548    CastInt32ToUint32,
5549    CastInt32ToUint64,
5550    CastInt32ToString,
5551    CastOidToInt32,
5552    CastOidToInt64,
5553    CastOidToString,
5554    CastOidToRegClass,
5555    CastRegClassToOid,
5556    CastOidToRegProc,
5557    CastRegProcToOid,
5558    CastOidToRegType,
5559    CastRegTypeToOid,
5560    CastInt64ToInt16,
5561    CastInt64ToInt32,
5562    CastInt64ToUint16,
5563    CastInt64ToUint32,
5564    CastInt64ToUint64,
5565    CastInt16ToNumeric,
5566    CastInt32ToNumeric,
5567    CastInt64ToBool,
5568    CastInt64ToNumeric,
5569    CastInt64ToFloat32,
5570    CastInt64ToFloat64,
5571    CastInt64ToOid,
5572    CastInt64ToString,
5573    CastUint16ToUint32,
5574    CastUint16ToUint64,
5575    CastUint16ToInt16,
5576    CastUint16ToInt32,
5577    CastUint16ToInt64,
5578    CastUint16ToNumeric,
5579    CastUint16ToFloat32,
5580    CastUint16ToFloat64,
5581    CastUint16ToString,
5582    CastUint32ToUint16,
5583    CastUint32ToUint64,
5584    CastUint32ToInt16,
5585    CastUint32ToInt32,
5586    CastUint32ToInt64,
5587    CastUint32ToNumeric,
5588    CastUint32ToFloat32,
5589    CastUint32ToFloat64,
5590    CastUint32ToString,
5591    CastUint64ToUint16,
5592    CastUint64ToUint32,
5593    CastUint64ToInt16,
5594    CastUint64ToInt32,
5595    CastUint64ToInt64,
5596    CastUint64ToNumeric,
5597    CastUint64ToFloat32,
5598    CastUint64ToFloat64,
5599    CastUint64ToString,
5600    CastFloat32ToInt16,
5601    CastFloat32ToInt32,
5602    CastFloat32ToInt64,
5603    CastFloat32ToUint16,
5604    CastFloat32ToUint32,
5605    CastFloat32ToUint64,
5606    CastFloat32ToFloat64,
5607    CastFloat32ToString,
5608    CastFloat32ToNumeric,
5609    CastFloat64ToNumeric,
5610    CastFloat64ToInt16,
5611    CastFloat64ToInt32,
5612    CastFloat64ToInt64,
5613    CastFloat64ToUint16,
5614    CastFloat64ToUint32,
5615    CastFloat64ToUint64,
5616    CastFloat64ToFloat32,
5617    CastFloat64ToString,
5618    CastNumericToFloat32,
5619    CastNumericToFloat64,
5620    CastNumericToInt16,
5621    CastNumericToInt32,
5622    CastNumericToInt64,
5623    CastNumericToUint16,
5624    CastNumericToUint32,
5625    CastNumericToUint64,
5626    CastNumericToString,
5627    CastMzTimestampToString,
5628    CastMzTimestampToTimestamp,
5629    CastMzTimestampToTimestampTz,
5630    CastStringToMzTimestamp,
5631    CastUint64ToMzTimestamp,
5632    CastUint32ToMzTimestamp,
5633    CastInt64ToMzTimestamp,
5634    CastInt32ToMzTimestamp,
5635    CastNumericToMzTimestamp,
5636    CastTimestampToMzTimestamp,
5637    CastTimestampTzToMzTimestamp,
5638    CastDateToMzTimestamp,
5639    CastStringToBool,
5640    CastStringToPgLegacyChar,
5641    CastStringToPgLegacyName,
5642    CastStringToBytes,
5643    CastStringToInt16,
5644    CastStringToInt32,
5645    CastStringToInt64,
5646    CastStringToUint16,
5647    CastStringToUint32,
5648    CastStringToUint64,
5649    CastStringToInt2Vector,
5650    CastStringToOid,
5651    CastStringToFloat32,
5652    CastStringToFloat64,
5653    CastStringToDate,
5654    CastStringToArray,
5655    CastStringToList,
5656    CastStringToMap,
5657    CastStringToRange,
5658    CastStringToTime,
5659    CastStringToTimestamp,
5660    CastStringToTimestampTz,
5661    CastStringToInterval,
5662    CastStringToNumeric,
5663    CastStringToUuid,
5664    CastStringToChar,
5665    PadChar,
5666    CastStringToVarChar,
5667    CastCharToString,
5668    CastVarCharToString,
5669    CastDateToTimestamp,
5670    CastDateToTimestampTz,
5671    CastDateToString,
5672    CastTimeToInterval,
5673    CastTimeToString,
5674    CastIntervalToString,
5675    CastIntervalToTime,
5676    CastTimestampToDate,
5677    AdjustTimestampPrecision,
5678    CastTimestampToTimestampTz,
5679    CastTimestampToString,
5680    CastTimestampToTime,
5681    CastTimestampTzToDate,
5682    CastTimestampTzToTimestamp,
5683    AdjustTimestampTzPrecision,
5684    CastTimestampTzToString,
5685    CastTimestampTzToTime,
5686    CastPgLegacyCharToString,
5687    CastPgLegacyCharToChar,
5688    CastPgLegacyCharToVarChar,
5689    CastPgLegacyCharToInt32,
5690    CastBytesToString,
5691    CastStringToJsonb,
5692    CastJsonbToString,
5693    CastJsonbableToJsonb,
5694    CastJsonbToInt16,
5695    CastJsonbToInt32,
5696    CastJsonbToInt64,
5697    CastJsonbToFloat32,
5698    CastJsonbToFloat64,
5699    CastJsonbToNumeric,
5700    CastJsonbToBool,
5701    CastUuidToString,
5702    CastRecordToString,
5703    CastRecord1ToRecord2,
5704    CastArrayToArray,
5705    CastArrayToJsonb,
5706    CastArrayToString,
5707    CastListToString,
5708    CastListToJsonb,
5709    CastList1ToList2,
5710    CastArrayToListOneDim,
5711    CastMapToString,
5712    CastInt2VectorToString,
5713    CastRangeToString,
5714    CeilFloat32,
5715    CeilFloat64,
5716    CeilNumeric,
5717    FloorFloat32,
5718    FloorFloat64,
5719    FloorNumeric,
5720    Ascii,
5721    BitCountBytes,
5722    BitLengthBytes,
5723    BitLengthString,
5724    ByteLengthBytes,
5725    ByteLengthString,
5726    CharLength,
5727    Chr,
5728    IsLikeMatch,
5729    IsRegexpMatch,
5730    RegexpMatch,
5731    ExtractInterval,
5732    ExtractTime,
5733    ExtractTimestamp,
5734    ExtractTimestampTz,
5735    ExtractDate,
5736    DatePartInterval,
5737    DatePartTime,
5738    DatePartTimestamp,
5739    DatePartTimestampTz,
5740    DateTruncTimestamp,
5741    DateTruncTimestampTz,
5742    TimezoneTimestamp,
5743    TimezoneTimestampTz,
5744    TimezoneTime,
5745    ToTimestamp,
5746    ToCharTimestamp,
5747    ToCharTimestampTz,
5748    JustifyDays,
5749    JustifyHours,
5750    JustifyInterval,
5751    JsonbArrayLength,
5752    JsonbTypeof,
5753    JsonbStripNulls,
5754    JsonbPretty,
5755    RoundFloat32,
5756    RoundFloat64,
5757    RoundNumeric,
5758    TruncFloat32,
5759    TruncFloat64,
5760    TruncNumeric,
5761    TrimWhitespace,
5762    TrimLeadingWhitespace,
5763    TrimTrailingWhitespace,
5764    Initcap,
5765    RecordGet,
5766    ListLength,
5767    MapLength,
5768    MapBuildFromRecordList,
5769    Upper,
5770    Lower,
5771    Cos,
5772    Acos,
5773    Cosh,
5774    Acosh,
5775    Sin,
5776    Asin,
5777    Sinh,
5778    Asinh,
5779    Tan,
5780    Atan,
5781    Tanh,
5782    Atanh,
5783    Cot,
5784    Degrees,
5785    Radians,
5786    Log10,
5787    Log10Numeric,
5788    Ln,
5789    LnNumeric,
5790    Exp,
5791    ExpNumeric,
5792    Sleep,
5793    Panic,
5794    AdjustNumericScale,
5795    PgColumnSize,
5796    MzRowSize,
5797    MzTypeName,
5798    StepMzTimestamp,
5799    RangeLower,
5800    RangeUpper,
5801    RangeEmpty,
5802    RangeLowerInc,
5803    RangeUpperInc,
5804    RangeLowerInf,
5805    RangeUpperInf,
5806    MzAclItemGrantor,
5807    MzAclItemGrantee,
5808    MzAclItemPrivileges,
5809    MzFormatPrivileges,
5810    MzValidatePrivileges,
5811    MzValidateRolePrivilege,
5812    AclItemGrantor,
5813    AclItemGrantee,
5814    AclItemPrivileges,
5815    QuoteIdent,
5816    TryParseMonotonicIso8601Timestamp,
5817    RegexpSplitToArray,
5818    PgSizePretty,
5819    Crc32Bytes,
5820    Crc32String,
5821    KafkaMurmur2Bytes,
5822    KafkaMurmur2String,
5823    SeahashBytes,
5824    SeahashString,
5825    Reverse
5826);
5827
5828impl UnaryFunc {
5829    /// If the unary_func represents "IS X", return X.
5830    ///
5831    /// A helper method for being able to print Not(IsX) as IS NOT X.
5832    pub fn is(&self) -> Option<&'static str> {
5833        match self {
5834            UnaryFunc::IsNull(_) => Some("NULL"),
5835            UnaryFunc::IsTrue(_) => Some("TRUE"),
5836            UnaryFunc::IsFalse(_) => Some("FALSE"),
5837            _ => None,
5838        }
5839    }
5840}
5841
5842/// An explicit [`Arbitrary`] implementation needed here because of a known
5843/// `proptest` issue.
5844///
5845/// Revert to the derive-macro implementation once the issue[^1] is fixed.
5846///
5847/// [^1]: <https://github.com/AltSysrq/proptest/issues/152>
5848impl Arbitrary for UnaryFunc {
5849    type Parameters = ();
5850
5851    type Strategy = Union<BoxedStrategy<Self>>;
5852
5853    fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
5854        Union::new(vec![
5855            Not::arbitrary().prop_map_into().boxed(),
5856            IsNull::arbitrary().prop_map_into().boxed(),
5857            IsTrue::arbitrary().prop_map_into().boxed(),
5858            IsFalse::arbitrary().prop_map_into().boxed(),
5859            BitNotInt16::arbitrary().prop_map_into().boxed(),
5860            BitNotInt32::arbitrary().prop_map_into().boxed(),
5861            BitNotInt64::arbitrary().prop_map_into().boxed(),
5862            BitNotUint16::arbitrary().prop_map_into().boxed(),
5863            BitNotUint32::arbitrary().prop_map_into().boxed(),
5864            BitNotUint64::arbitrary().prop_map_into().boxed(),
5865            NegInt16::arbitrary().prop_map_into().boxed(),
5866            NegInt32::arbitrary().prop_map_into().boxed(),
5867            NegInt64::arbitrary().prop_map_into().boxed(),
5868            NegFloat32::arbitrary().prop_map_into().boxed(),
5869            NegFloat64::arbitrary().prop_map_into().boxed(),
5870            NegNumeric::arbitrary().prop_map_into().boxed(),
5871            NegInterval::arbitrary().prop_map_into().boxed(),
5872            SqrtFloat64::arbitrary().prop_map_into().boxed(),
5873            SqrtNumeric::arbitrary().prop_map_into().boxed(),
5874            CbrtFloat64::arbitrary().prop_map_into().boxed(),
5875            AbsInt16::arbitrary().prop_map_into().boxed(),
5876            AbsInt32::arbitrary().prop_map_into().boxed(),
5877            AbsInt64::arbitrary().prop_map_into().boxed(),
5878            AbsFloat32::arbitrary().prop_map_into().boxed(),
5879            AbsFloat64::arbitrary().prop_map_into().boxed(),
5880            AbsNumeric::arbitrary().prop_map_into().boxed(),
5881            CastBoolToString::arbitrary().prop_map_into().boxed(),
5882            CastBoolToStringNonstandard::arbitrary()
5883                .prop_map_into()
5884                .boxed(),
5885            CastBoolToInt32::arbitrary().prop_map_into().boxed(),
5886            CastBoolToInt64::arbitrary().prop_map_into().boxed(),
5887            CastInt16ToFloat32::arbitrary().prop_map_into().boxed(),
5888            CastInt16ToFloat64::arbitrary().prop_map_into().boxed(),
5889            CastInt16ToInt32::arbitrary().prop_map_into().boxed(),
5890            CastInt16ToInt64::arbitrary().prop_map_into().boxed(),
5891            CastInt16ToUint16::arbitrary().prop_map_into().boxed(),
5892            CastInt16ToUint32::arbitrary().prop_map_into().boxed(),
5893            CastInt16ToUint64::arbitrary().prop_map_into().boxed(),
5894            CastInt16ToString::arbitrary().prop_map_into().boxed(),
5895            CastInt2VectorToArray::arbitrary().prop_map_into().boxed(),
5896            CastInt32ToBool::arbitrary().prop_map_into().boxed(),
5897            CastInt32ToFloat32::arbitrary().prop_map_into().boxed(),
5898            CastInt32ToFloat64::arbitrary().prop_map_into().boxed(),
5899            CastInt32ToOid::arbitrary().prop_map_into().boxed(),
5900            CastInt32ToPgLegacyChar::arbitrary().prop_map_into().boxed(),
5901            CastInt32ToInt16::arbitrary().prop_map_into().boxed(),
5902            CastInt32ToInt64::arbitrary().prop_map_into().boxed(),
5903            CastInt32ToUint16::arbitrary().prop_map_into().boxed(),
5904            CastInt32ToUint32::arbitrary().prop_map_into().boxed(),
5905            CastInt32ToUint64::arbitrary().prop_map_into().boxed(),
5906            CastInt32ToString::arbitrary().prop_map_into().boxed(),
5907            CastOidToInt32::arbitrary().prop_map_into().boxed(),
5908            CastOidToInt64::arbitrary().prop_map_into().boxed(),
5909            CastOidToString::arbitrary().prop_map_into().boxed(),
5910            CastOidToRegClass::arbitrary().prop_map_into().boxed(),
5911            CastRegClassToOid::arbitrary().prop_map_into().boxed(),
5912            CastOidToRegProc::arbitrary().prop_map_into().boxed(),
5913            CastRegProcToOid::arbitrary().prop_map_into().boxed(),
5914            CastOidToRegType::arbitrary().prop_map_into().boxed(),
5915            CastRegTypeToOid::arbitrary().prop_map_into().boxed(),
5916            CastInt64ToInt16::arbitrary().prop_map_into().boxed(),
5917            CastInt64ToInt32::arbitrary().prop_map_into().boxed(),
5918            CastInt64ToUint16::arbitrary().prop_map_into().boxed(),
5919            CastInt64ToUint32::arbitrary().prop_map_into().boxed(),
5920            CastInt64ToUint64::arbitrary().prop_map_into().boxed(),
5921            any::<Option<NumericMaxScale>>()
5922                .prop_map(|i| UnaryFunc::CastInt16ToNumeric(CastInt16ToNumeric(i)))
5923                .boxed(),
5924            any::<Option<NumericMaxScale>>()
5925                .prop_map(|i| UnaryFunc::CastInt32ToNumeric(CastInt32ToNumeric(i)))
5926                .boxed(),
5927            CastInt64ToBool::arbitrary().prop_map_into().boxed(),
5928            any::<Option<NumericMaxScale>>()
5929                .prop_map(|i| UnaryFunc::CastInt64ToNumeric(CastInt64ToNumeric(i)))
5930                .boxed(),
5931            CastInt64ToFloat32::arbitrary().prop_map_into().boxed(),
5932            CastInt64ToFloat64::arbitrary().prop_map_into().boxed(),
5933            CastInt64ToOid::arbitrary().prop_map_into().boxed(),
5934            CastInt64ToString::arbitrary().prop_map_into().boxed(),
5935            CastUint16ToUint32::arbitrary().prop_map_into().boxed(),
5936            CastUint16ToUint64::arbitrary().prop_map_into().boxed(),
5937            CastUint16ToInt16::arbitrary().prop_map_into().boxed(),
5938            CastUint16ToInt32::arbitrary().prop_map_into().boxed(),
5939            CastUint16ToInt64::arbitrary().prop_map_into().boxed(),
5940            any::<Option<NumericMaxScale>>()
5941                .prop_map(|i| UnaryFunc::CastUint16ToNumeric(CastUint16ToNumeric(i)))
5942                .boxed(),
5943            CastUint16ToFloat32::arbitrary().prop_map_into().boxed(),
5944            CastUint16ToFloat64::arbitrary().prop_map_into().boxed(),
5945            CastUint16ToString::arbitrary().prop_map_into().boxed(),
5946            CastUint32ToUint16::arbitrary().prop_map_into().boxed(),
5947            CastUint32ToUint64::arbitrary().prop_map_into().boxed(),
5948            CastUint32ToInt32::arbitrary().prop_map_into().boxed(),
5949            CastUint32ToInt64::arbitrary().prop_map_into().boxed(),
5950            any::<Option<NumericMaxScale>>()
5951                .prop_map(|i| UnaryFunc::CastUint32ToNumeric(CastUint32ToNumeric(i)))
5952                .boxed(),
5953            CastUint32ToFloat32::arbitrary().prop_map_into().boxed(),
5954            CastUint32ToFloat64::arbitrary().prop_map_into().boxed(),
5955            CastUint32ToString::arbitrary().prop_map_into().boxed(),
5956            CastUint64ToUint16::arbitrary().prop_map_into().boxed(),
5957            CastUint64ToUint32::arbitrary().prop_map_into().boxed(),
5958            CastUint64ToInt32::arbitrary().prop_map_into().boxed(),
5959            CastUint64ToInt64::arbitrary().prop_map_into().boxed(),
5960            any::<Option<NumericMaxScale>>()
5961                .prop_map(|i| UnaryFunc::CastUint64ToNumeric(CastUint64ToNumeric(i)))
5962                .boxed(),
5963            CastUint64ToFloat32::arbitrary().prop_map_into().boxed(),
5964            CastUint64ToFloat64::arbitrary().prop_map_into().boxed(),
5965            CastUint64ToString::arbitrary().prop_map_into().boxed(),
5966            CastFloat32ToInt16::arbitrary().prop_map_into().boxed(),
5967            CastFloat32ToInt32::arbitrary().prop_map_into().boxed(),
5968            CastFloat32ToInt64::arbitrary().prop_map_into().boxed(),
5969            CastFloat32ToUint16::arbitrary().prop_map_into().boxed(),
5970            CastFloat32ToUint32::arbitrary().prop_map_into().boxed(),
5971            CastFloat32ToUint64::arbitrary().prop_map_into().boxed(),
5972            CastFloat32ToFloat64::arbitrary().prop_map_into().boxed(),
5973            CastFloat32ToString::arbitrary().prop_map_into().boxed(),
5974            any::<Option<NumericMaxScale>>()
5975                .prop_map(|i| UnaryFunc::CastFloat32ToNumeric(CastFloat32ToNumeric(i)))
5976                .boxed(),
5977            any::<Option<NumericMaxScale>>()
5978                .prop_map(|i| UnaryFunc::CastFloat64ToNumeric(CastFloat64ToNumeric(i)))
5979                .boxed(),
5980            CastFloat64ToInt16::arbitrary().prop_map_into().boxed(),
5981            CastFloat64ToInt32::arbitrary().prop_map_into().boxed(),
5982            CastFloat64ToInt64::arbitrary().prop_map_into().boxed(),
5983            CastFloat64ToUint16::arbitrary().prop_map_into().boxed(),
5984            CastFloat64ToUint32::arbitrary().prop_map_into().boxed(),
5985            CastFloat64ToUint64::arbitrary().prop_map_into().boxed(),
5986            CastFloat64ToFloat32::arbitrary().prop_map_into().boxed(),
5987            CastFloat64ToString::arbitrary().prop_map_into().boxed(),
5988            CastNumericToFloat32::arbitrary().prop_map_into().boxed(),
5989            CastNumericToFloat64::arbitrary().prop_map_into().boxed(),
5990            CastNumericToInt16::arbitrary().prop_map_into().boxed(),
5991            CastNumericToInt32::arbitrary().prop_map_into().boxed(),
5992            CastNumericToInt64::arbitrary().prop_map_into().boxed(),
5993            CastNumericToUint16::arbitrary().prop_map_into().boxed(),
5994            CastNumericToUint32::arbitrary().prop_map_into().boxed(),
5995            CastNumericToUint64::arbitrary().prop_map_into().boxed(),
5996            CastNumericToString::arbitrary().prop_map_into().boxed(),
5997            CastStringToBool::arbitrary().prop_map_into().boxed(),
5998            CastStringToPgLegacyChar::arbitrary()
5999                .prop_map_into()
6000                .boxed(),
6001            CastStringToPgLegacyName::arbitrary()
6002                .prop_map_into()
6003                .boxed(),
6004            CastStringToBytes::arbitrary().prop_map_into().boxed(),
6005            CastStringToInt16::arbitrary().prop_map_into().boxed(),
6006            CastStringToInt32::arbitrary().prop_map_into().boxed(),
6007            CastStringToInt64::arbitrary().prop_map_into().boxed(),
6008            CastStringToUint16::arbitrary().prop_map_into().boxed(),
6009            CastStringToUint32::arbitrary().prop_map_into().boxed(),
6010            CastStringToUint64::arbitrary().prop_map_into().boxed(),
6011            CastStringToInt2Vector::arbitrary().prop_map_into().boxed(),
6012            CastStringToOid::arbitrary().prop_map_into().boxed(),
6013            CastStringToFloat32::arbitrary().prop_map_into().boxed(),
6014            CastStringToFloat64::arbitrary().prop_map_into().boxed(),
6015            CastStringToDate::arbitrary().prop_map_into().boxed(),
6016            (any::<ScalarType>(), any::<MirScalarExpr>())
6017                .prop_map(|(return_ty, expr)| {
6018                    UnaryFunc::CastStringToArray(CastStringToArray {
6019                        return_ty,
6020                        cast_expr: Box::new(expr),
6021                    })
6022                })
6023                .boxed(),
6024            (any::<ScalarType>(), any::<MirScalarExpr>())
6025                .prop_map(|(return_ty, expr)| {
6026                    UnaryFunc::CastStringToList(CastStringToList {
6027                        return_ty,
6028                        cast_expr: Box::new(expr),
6029                    })
6030                })
6031                .boxed(),
6032            (any::<ScalarType>(), any::<MirScalarExpr>())
6033                .prop_map(|(return_ty, expr)| {
6034                    UnaryFunc::CastStringToMap(CastStringToMap {
6035                        return_ty,
6036                        cast_expr: Box::new(expr),
6037                    })
6038                })
6039                .boxed(),
6040            (any::<ScalarType>(), any::<MirScalarExpr>())
6041                .prop_map(|(return_ty, expr)| {
6042                    UnaryFunc::CastStringToRange(CastStringToRange {
6043                        return_ty,
6044                        cast_expr: Box::new(expr),
6045                    })
6046                })
6047                .boxed(),
6048            CastStringToTime::arbitrary().prop_map_into().boxed(),
6049            CastStringToTimestamp::arbitrary().prop_map_into().boxed(),
6050            CastStringToTimestampTz::arbitrary().prop_map_into().boxed(),
6051            CastStringToInterval::arbitrary().prop_map_into().boxed(),
6052            CastStringToNumeric::arbitrary().prop_map_into().boxed(),
6053            CastStringToUuid::arbitrary().prop_map_into().boxed(),
6054            CastStringToChar::arbitrary().prop_map_into().boxed(),
6055            PadChar::arbitrary().prop_map_into().boxed(),
6056            CastStringToVarChar::arbitrary().prop_map_into().boxed(),
6057            CastCharToString::arbitrary().prop_map_into().boxed(),
6058            CastVarCharToString::arbitrary().prop_map_into().boxed(),
6059            CastDateToTimestamp::arbitrary().prop_map_into().boxed(),
6060            CastDateToTimestampTz::arbitrary().prop_map_into().boxed(),
6061            CastDateToString::arbitrary().prop_map_into().boxed(),
6062            CastTimeToInterval::arbitrary().prop_map_into().boxed(),
6063            CastTimeToString::arbitrary().prop_map_into().boxed(),
6064            CastIntervalToString::arbitrary().prop_map_into().boxed(),
6065            CastIntervalToTime::arbitrary().prop_map_into().boxed(),
6066            CastTimestampToDate::arbitrary().prop_map_into().boxed(),
6067            CastTimestampToTimestampTz::arbitrary()
6068                .prop_map_into()
6069                .boxed(),
6070            CastTimestampToString::arbitrary().prop_map_into().boxed(),
6071            CastTimestampToTime::arbitrary().prop_map_into().boxed(),
6072            CastTimestampTzToDate::arbitrary().prop_map_into().boxed(),
6073            CastTimestampTzToTimestamp::arbitrary()
6074                .prop_map_into()
6075                .boxed(),
6076            CastTimestampTzToString::arbitrary().prop_map_into().boxed(),
6077            CastTimestampTzToTime::arbitrary().prop_map_into().boxed(),
6078            CastPgLegacyCharToString::arbitrary()
6079                .prop_map_into()
6080                .boxed(),
6081            CastPgLegacyCharToChar::arbitrary().prop_map_into().boxed(),
6082            CastPgLegacyCharToVarChar::arbitrary()
6083                .prop_map_into()
6084                .boxed(),
6085            CastPgLegacyCharToInt32::arbitrary().prop_map_into().boxed(),
6086            CastBytesToString::arbitrary().prop_map_into().boxed(),
6087            CastStringToJsonb::arbitrary().prop_map_into().boxed(),
6088            CastJsonbToString::arbitrary().prop_map_into().boxed(),
6089            CastJsonbableToJsonb::arbitrary().prop_map_into().boxed(),
6090            CastJsonbToInt16::arbitrary().prop_map_into().boxed(),
6091            CastJsonbToInt32::arbitrary().prop_map_into().boxed(),
6092            CastJsonbToInt64::arbitrary().prop_map_into().boxed(),
6093            CastJsonbToFloat32::arbitrary().prop_map_into().boxed(),
6094            CastJsonbToFloat64::arbitrary().prop_map_into().boxed(),
6095            CastJsonbToNumeric::arbitrary().prop_map_into().boxed(),
6096            CastJsonbToBool::arbitrary().prop_map_into().boxed(),
6097            CastUuidToString::arbitrary().prop_map_into().boxed(),
6098            CastRecordToString::arbitrary().prop_map_into().boxed(),
6099            (
6100                any::<ScalarType>(),
6101                proptest::collection::vec(any::<MirScalarExpr>(), 1..5),
6102            )
6103                .prop_map(|(return_ty, cast_exprs)| {
6104                    UnaryFunc::CastRecord1ToRecord2(CastRecord1ToRecord2 {
6105                        return_ty,
6106                        cast_exprs: cast_exprs.into(),
6107                    })
6108                })
6109                .boxed(),
6110            CastArrayToJsonb::arbitrary().prop_map_into().boxed(),
6111            CastArrayToString::arbitrary().prop_map_into().boxed(),
6112            CastListToString::arbitrary().prop_map_into().boxed(),
6113            CastListToJsonb::arbitrary().prop_map_into().boxed(),
6114            (any::<ScalarType>(), any::<MirScalarExpr>())
6115                .prop_map(|(return_ty, expr)| {
6116                    UnaryFunc::CastList1ToList2(CastList1ToList2 {
6117                        return_ty,
6118                        cast_expr: Box::new(expr),
6119                    })
6120                })
6121                .boxed(),
6122            CastArrayToListOneDim::arbitrary().prop_map_into().boxed(),
6123            CastMapToString::arbitrary().prop_map_into().boxed(),
6124            CastInt2VectorToString::arbitrary().prop_map_into().boxed(),
6125            CastRangeToString::arbitrary().prop_map_into().boxed(),
6126            CeilFloat32::arbitrary().prop_map_into().boxed(),
6127            CeilFloat64::arbitrary().prop_map_into().boxed(),
6128            CeilNumeric::arbitrary().prop_map_into().boxed(),
6129            FloorFloat32::arbitrary().prop_map_into().boxed(),
6130            FloorFloat64::arbitrary().prop_map_into().boxed(),
6131            FloorNumeric::arbitrary().prop_map_into().boxed(),
6132            Ascii::arbitrary().prop_map_into().boxed(),
6133            BitCountBytes::arbitrary().prop_map_into().boxed(),
6134            BitLengthBytes::arbitrary().prop_map_into().boxed(),
6135            BitLengthString::arbitrary().prop_map_into().boxed(),
6136            ByteLengthBytes::arbitrary().prop_map_into().boxed(),
6137            ByteLengthString::arbitrary().prop_map_into().boxed(),
6138            CharLength::arbitrary().prop_map_into().boxed(),
6139            Chr::arbitrary().prop_map_into().boxed(),
6140            like_pattern::any_matcher()
6141                .prop_map(|matcher| UnaryFunc::IsLikeMatch(IsLikeMatch(matcher)))
6142                .boxed(),
6143            any_regex()
6144                .prop_map(|regex| UnaryFunc::IsRegexpMatch(IsRegexpMatch(regex)))
6145                .boxed(),
6146            any_regex()
6147                .prop_map(|regex| UnaryFunc::RegexpMatch(RegexpMatch(regex)))
6148                .boxed(),
6149            any_regex()
6150                .prop_map(|regex| UnaryFunc::RegexpSplitToArray(RegexpSplitToArray(regex)))
6151                .boxed(),
6152            ExtractInterval::arbitrary().prop_map_into().boxed(),
6153            ExtractTime::arbitrary().prop_map_into().boxed(),
6154            ExtractTimestamp::arbitrary().prop_map_into().boxed(),
6155            ExtractTimestampTz::arbitrary().prop_map_into().boxed(),
6156            ExtractDate::arbitrary().prop_map_into().boxed(),
6157            DatePartInterval::arbitrary().prop_map_into().boxed(),
6158            DatePartTime::arbitrary().prop_map_into().boxed(),
6159            DatePartTimestamp::arbitrary().prop_map_into().boxed(),
6160            DatePartTimestampTz::arbitrary().prop_map_into().boxed(),
6161            DateTruncTimestamp::arbitrary().prop_map_into().boxed(),
6162            DateTruncTimestampTz::arbitrary().prop_map_into().boxed(),
6163            TimezoneTimestamp::arbitrary().prop_map_into().boxed(),
6164            TimezoneTimestampTz::arbitrary().prop_map_into().boxed(),
6165            TimezoneTime::arbitrary().prop_map_into().boxed(),
6166            ToTimestamp::arbitrary().prop_map_into().boxed(),
6167            JustifyDays::arbitrary().prop_map_into().boxed(),
6168            JustifyHours::arbitrary().prop_map_into().boxed(),
6169            JustifyInterval::arbitrary().prop_map_into().boxed(),
6170            JsonbArrayLength::arbitrary().prop_map_into().boxed(),
6171            JsonbTypeof::arbitrary().prop_map_into().boxed(),
6172            JsonbStripNulls::arbitrary().prop_map_into().boxed(),
6173            JsonbPretty::arbitrary().prop_map_into().boxed(),
6174            RoundFloat32::arbitrary().prop_map_into().boxed(),
6175            RoundFloat64::arbitrary().prop_map_into().boxed(),
6176            RoundNumeric::arbitrary().prop_map_into().boxed(),
6177            TruncFloat32::arbitrary().prop_map_into().boxed(),
6178            TruncFloat64::arbitrary().prop_map_into().boxed(),
6179            TruncNumeric::arbitrary().prop_map_into().boxed(),
6180            TrimWhitespace::arbitrary().prop_map_into().boxed(),
6181            TrimLeadingWhitespace::arbitrary().prop_map_into().boxed(),
6182            TrimTrailingWhitespace::arbitrary().prop_map_into().boxed(),
6183            RecordGet::arbitrary().prop_map_into().boxed(),
6184            ListLength::arbitrary().prop_map_into().boxed(),
6185            (any::<ScalarType>())
6186                .prop_map(|value_type| {
6187                    UnaryFunc::MapBuildFromRecordList(MapBuildFromRecordList { value_type })
6188                })
6189                .boxed(),
6190            MapLength::arbitrary().prop_map_into().boxed(),
6191            Upper::arbitrary().prop_map_into().boxed(),
6192            Lower::arbitrary().prop_map_into().boxed(),
6193            Cos::arbitrary().prop_map_into().boxed(),
6194            Acos::arbitrary().prop_map_into().boxed(),
6195            Cosh::arbitrary().prop_map_into().boxed(),
6196            Acosh::arbitrary().prop_map_into().boxed(),
6197            Sin::arbitrary().prop_map_into().boxed(),
6198            Asin::arbitrary().prop_map_into().boxed(),
6199            Sinh::arbitrary().prop_map_into().boxed(),
6200            Asinh::arbitrary().prop_map_into().boxed(),
6201            Tan::arbitrary().prop_map_into().boxed(),
6202            Atan::arbitrary().prop_map_into().boxed(),
6203            Tanh::arbitrary().prop_map_into().boxed(),
6204            Atanh::arbitrary().prop_map_into().boxed(),
6205            Cot::arbitrary().prop_map_into().boxed(),
6206            Degrees::arbitrary().prop_map_into().boxed(),
6207            Radians::arbitrary().prop_map_into().boxed(),
6208            Log10::arbitrary().prop_map_into().boxed(),
6209            Log10Numeric::arbitrary().prop_map_into().boxed(),
6210            Ln::arbitrary().prop_map_into().boxed(),
6211            LnNumeric::arbitrary().prop_map_into().boxed(),
6212            Exp::arbitrary().prop_map_into().boxed(),
6213            ExpNumeric::arbitrary().prop_map_into().boxed(),
6214            Sleep::arbitrary().prop_map_into().boxed(),
6215            Panic::arbitrary().prop_map_into().boxed(),
6216            AdjustNumericScale::arbitrary().prop_map_into().boxed(),
6217            PgColumnSize::arbitrary().prop_map_into().boxed(),
6218            PgSizePretty::arbitrary().prop_map_into().boxed(),
6219            MzRowSize::arbitrary().prop_map_into().boxed(),
6220            MzTypeName::arbitrary().prop_map_into().boxed(),
6221            RangeLower::arbitrary().prop_map_into().boxed(),
6222            RangeUpper::arbitrary().prop_map_into().boxed(),
6223            RangeEmpty::arbitrary().prop_map_into().boxed(),
6224            RangeLowerInc::arbitrary().prop_map_into().boxed(),
6225            RangeUpperInc::arbitrary().prop_map_into().boxed(),
6226            RangeLowerInf::arbitrary().prop_map_into().boxed(),
6227            RangeUpperInf::arbitrary().prop_map_into().boxed(),
6228            MzAclItemGrantor::arbitrary().prop_map_into().boxed(),
6229            MzAclItemGrantee::arbitrary().prop_map_into().boxed(),
6230            MzAclItemPrivileges::arbitrary().prop_map_into().boxed(),
6231            MzFormatPrivileges::arbitrary().prop_map_into().boxed(),
6232            MzValidatePrivileges::arbitrary().prop_map_into().boxed(),
6233            MzValidateRolePrivilege::arbitrary().prop_map_into().boxed(),
6234            AclItemGrantor::arbitrary().prop_map_into().boxed(),
6235            AclItemGrantee::arbitrary().prop_map_into().boxed(),
6236            AclItemPrivileges::arbitrary().prop_map_into().boxed(),
6237            QuoteIdent::arbitrary().prop_map_into().boxed(),
6238        ])
6239    }
6240}
6241
6242impl RustType<ProtoUnaryFunc> for UnaryFunc {
6243    fn into_proto(&self) -> ProtoUnaryFunc {
6244        use crate::scalar::proto_unary_func::Kind::*;
6245        use crate::scalar::proto_unary_func::*;
6246        let kind = match self {
6247            UnaryFunc::Not(_) => Not(()),
6248            UnaryFunc::IsNull(_) => IsNull(()),
6249            UnaryFunc::IsTrue(_) => IsTrue(()),
6250            UnaryFunc::IsFalse(_) => IsFalse(()),
6251            UnaryFunc::BitNotInt16(_) => BitNotInt16(()),
6252            UnaryFunc::BitNotInt32(_) => BitNotInt32(()),
6253            UnaryFunc::BitNotInt64(_) => BitNotInt64(()),
6254            UnaryFunc::BitNotUint16(_) => BitNotUint16(()),
6255            UnaryFunc::BitNotUint32(_) => BitNotUint32(()),
6256            UnaryFunc::BitNotUint64(_) => BitNotUint64(()),
6257            UnaryFunc::NegInt16(_) => NegInt16(()),
6258            UnaryFunc::NegInt32(_) => NegInt32(()),
6259            UnaryFunc::NegInt64(_) => NegInt64(()),
6260            UnaryFunc::NegFloat32(_) => NegFloat32(()),
6261            UnaryFunc::NegFloat64(_) => NegFloat64(()),
6262            UnaryFunc::NegNumeric(_) => NegNumeric(()),
6263            UnaryFunc::NegInterval(_) => NegInterval(()),
6264            UnaryFunc::SqrtFloat64(_) => SqrtFloat64(()),
6265            UnaryFunc::SqrtNumeric(_) => SqrtNumeric(()),
6266            UnaryFunc::CbrtFloat64(_) => CbrtFloat64(()),
6267            UnaryFunc::AbsInt16(_) => AbsInt16(()),
6268            UnaryFunc::AbsInt32(_) => AbsInt32(()),
6269            UnaryFunc::AbsInt64(_) => AbsInt64(()),
6270            UnaryFunc::AbsFloat32(_) => AbsFloat32(()),
6271            UnaryFunc::AbsFloat64(_) => AbsFloat64(()),
6272            UnaryFunc::AbsNumeric(_) => AbsNumeric(()),
6273            UnaryFunc::CastBoolToString(_) => CastBoolToString(()),
6274            UnaryFunc::CastBoolToStringNonstandard(_) => CastBoolToStringNonstandard(()),
6275            UnaryFunc::CastBoolToInt32(_) => CastBoolToInt32(()),
6276            UnaryFunc::CastBoolToInt64(_) => CastBoolToInt64(()),
6277            UnaryFunc::CastInt16ToFloat32(_) => CastInt16ToFloat32(()),
6278            UnaryFunc::CastInt16ToFloat64(_) => CastInt16ToFloat64(()),
6279            UnaryFunc::CastInt16ToInt32(_) => CastInt16ToInt32(()),
6280            UnaryFunc::CastInt16ToInt64(_) => CastInt16ToInt64(()),
6281            UnaryFunc::CastInt16ToUint16(_) => CastInt16ToUint16(()),
6282            UnaryFunc::CastInt16ToUint32(_) => CastInt16ToUint32(()),
6283            UnaryFunc::CastInt16ToUint64(_) => CastInt16ToUint64(()),
6284            UnaryFunc::CastInt16ToString(_) => CastInt16ToString(()),
6285            UnaryFunc::CastInt2VectorToArray(_) => CastInt2VectorToArray(()),
6286            UnaryFunc::CastInt32ToBool(_) => CastInt32ToBool(()),
6287            UnaryFunc::CastInt32ToFloat32(_) => CastInt32ToFloat32(()),
6288            UnaryFunc::CastInt32ToFloat64(_) => CastInt32ToFloat64(()),
6289            UnaryFunc::CastInt32ToOid(_) => CastInt32ToOid(()),
6290            UnaryFunc::CastInt32ToPgLegacyChar(_) => CastInt32ToPgLegacyChar(()),
6291            UnaryFunc::CastInt32ToInt16(_) => CastInt32ToInt16(()),
6292            UnaryFunc::CastInt32ToInt64(_) => CastInt32ToInt64(()),
6293            UnaryFunc::CastInt32ToUint16(_) => CastInt32ToUint16(()),
6294            UnaryFunc::CastInt32ToUint32(_) => CastInt32ToUint32(()),
6295            UnaryFunc::CastInt32ToUint64(_) => CastInt32ToUint64(()),
6296            UnaryFunc::CastInt32ToString(_) => CastInt32ToString(()),
6297            UnaryFunc::CastOidToInt32(_) => CastOidToInt32(()),
6298            UnaryFunc::CastOidToInt64(_) => CastOidToInt64(()),
6299            UnaryFunc::CastOidToString(_) => CastOidToString(()),
6300            UnaryFunc::CastOidToRegClass(_) => CastOidToRegClass(()),
6301            UnaryFunc::CastRegClassToOid(_) => CastRegClassToOid(()),
6302            UnaryFunc::CastOidToRegProc(_) => CastOidToRegProc(()),
6303            UnaryFunc::CastRegProcToOid(_) => CastRegProcToOid(()),
6304            UnaryFunc::CastOidToRegType(_) => CastOidToRegType(()),
6305            UnaryFunc::CastRegTypeToOid(_) => CastRegTypeToOid(()),
6306            UnaryFunc::CastInt64ToInt16(_) => CastInt64ToInt16(()),
6307            UnaryFunc::CastInt64ToInt32(_) => CastInt64ToInt32(()),
6308            UnaryFunc::CastInt64ToUint16(_) => CastInt64ToUint16(()),
6309            UnaryFunc::CastInt64ToUint32(_) => CastInt64ToUint32(()),
6310            UnaryFunc::CastInt64ToUint64(_) => CastInt64ToUint64(()),
6311            UnaryFunc::CastInt16ToNumeric(func) => CastInt16ToNumeric(func.0.into_proto()),
6312            UnaryFunc::CastInt32ToNumeric(func) => CastInt32ToNumeric(func.0.into_proto()),
6313            UnaryFunc::CastInt64ToBool(_) => CastInt64ToBool(()),
6314            UnaryFunc::CastInt64ToNumeric(func) => CastInt64ToNumeric(func.0.into_proto()),
6315            UnaryFunc::CastInt64ToFloat32(_) => CastInt64ToFloat32(()),
6316            UnaryFunc::CastInt64ToFloat64(_) => CastInt64ToFloat64(()),
6317            UnaryFunc::CastInt64ToOid(_) => CastInt64ToOid(()),
6318            UnaryFunc::CastInt64ToString(_) => CastInt64ToString(()),
6319            UnaryFunc::CastUint16ToUint32(_) => CastUint16ToUint32(()),
6320            UnaryFunc::CastUint16ToUint64(_) => CastUint16ToUint64(()),
6321            UnaryFunc::CastUint16ToInt16(_) => CastUint16ToInt16(()),
6322            UnaryFunc::CastUint16ToInt32(_) => CastUint16ToInt32(()),
6323            UnaryFunc::CastUint16ToInt64(_) => CastUint16ToInt64(()),
6324            UnaryFunc::CastUint16ToNumeric(func) => CastUint16ToNumeric(func.0.into_proto()),
6325            UnaryFunc::CastUint16ToFloat32(_) => CastUint16ToFloat32(()),
6326            UnaryFunc::CastUint16ToFloat64(_) => CastUint16ToFloat64(()),
6327            UnaryFunc::CastUint16ToString(_) => CastUint16ToString(()),
6328            UnaryFunc::CastUint32ToUint16(_) => CastUint32ToUint16(()),
6329            UnaryFunc::CastUint32ToUint64(_) => CastUint32ToUint64(()),
6330            UnaryFunc::CastUint32ToInt16(_) => CastUint32ToInt16(()),
6331            UnaryFunc::CastUint32ToInt32(_) => CastUint32ToInt32(()),
6332            UnaryFunc::CastUint32ToInt64(_) => CastUint32ToInt64(()),
6333            UnaryFunc::CastUint32ToNumeric(func) => CastUint32ToNumeric(func.0.into_proto()),
6334            UnaryFunc::CastUint32ToFloat32(_) => CastUint32ToFloat32(()),
6335            UnaryFunc::CastUint32ToFloat64(_) => CastUint32ToFloat64(()),
6336            UnaryFunc::CastUint32ToString(_) => CastUint32ToString(()),
6337            UnaryFunc::CastUint64ToUint16(_) => CastUint64ToUint16(()),
6338            UnaryFunc::CastUint64ToUint32(_) => CastUint64ToUint32(()),
6339            UnaryFunc::CastUint64ToInt16(_) => CastUint64ToInt16(()),
6340            UnaryFunc::CastUint64ToInt32(_) => CastUint64ToInt32(()),
6341            UnaryFunc::CastUint64ToInt64(_) => CastUint64ToInt64(()),
6342            UnaryFunc::CastUint64ToNumeric(func) => CastUint64ToNumeric(func.0.into_proto()),
6343            UnaryFunc::CastUint64ToFloat32(_) => CastUint64ToFloat32(()),
6344            UnaryFunc::CastUint64ToFloat64(_) => CastUint64ToFloat64(()),
6345            UnaryFunc::CastUint64ToString(_) => CastUint64ToString(()),
6346            UnaryFunc::CastFloat32ToInt16(_) => CastFloat32ToInt16(()),
6347            UnaryFunc::CastFloat32ToInt32(_) => CastFloat32ToInt32(()),
6348            UnaryFunc::CastFloat32ToInt64(_) => CastFloat32ToInt64(()),
6349            UnaryFunc::CastFloat32ToUint16(_) => CastFloat32ToUint16(()),
6350            UnaryFunc::CastFloat32ToUint32(_) => CastFloat32ToUint32(()),
6351            UnaryFunc::CastFloat32ToUint64(_) => CastFloat32ToUint64(()),
6352            UnaryFunc::CastFloat32ToFloat64(_) => CastFloat32ToFloat64(()),
6353            UnaryFunc::CastFloat32ToString(_) => CastFloat32ToString(()),
6354            UnaryFunc::CastFloat32ToNumeric(func) => CastFloat32ToNumeric(func.0.into_proto()),
6355            UnaryFunc::CastFloat64ToNumeric(func) => CastFloat64ToNumeric(func.0.into_proto()),
6356            UnaryFunc::CastFloat64ToInt16(_) => CastFloat64ToInt16(()),
6357            UnaryFunc::CastFloat64ToInt32(_) => CastFloat64ToInt32(()),
6358            UnaryFunc::CastFloat64ToInt64(_) => CastFloat64ToInt64(()),
6359            UnaryFunc::CastFloat64ToUint16(_) => CastFloat64ToUint16(()),
6360            UnaryFunc::CastFloat64ToUint32(_) => CastFloat64ToUint32(()),
6361            UnaryFunc::CastFloat64ToUint64(_) => CastFloat64ToUint64(()),
6362            UnaryFunc::CastFloat64ToFloat32(_) => CastFloat64ToFloat32(()),
6363            UnaryFunc::CastFloat64ToString(_) => CastFloat64ToString(()),
6364            UnaryFunc::CastNumericToFloat32(_) => CastNumericToFloat32(()),
6365            UnaryFunc::CastNumericToFloat64(_) => CastNumericToFloat64(()),
6366            UnaryFunc::CastNumericToInt16(_) => CastNumericToInt16(()),
6367            UnaryFunc::CastNumericToInt32(_) => CastNumericToInt32(()),
6368            UnaryFunc::CastNumericToInt64(_) => CastNumericToInt64(()),
6369            UnaryFunc::CastNumericToUint16(_) => CastNumericToUint16(()),
6370            UnaryFunc::CastNumericToUint32(_) => CastNumericToUint32(()),
6371            UnaryFunc::CastNumericToUint64(_) => CastNumericToUint64(()),
6372            UnaryFunc::CastNumericToString(_) => CastNumericToString(()),
6373            UnaryFunc::CastStringToBool(_) => CastStringToBool(()),
6374            UnaryFunc::CastStringToPgLegacyChar(_) => CastStringToPgLegacyChar(()),
6375            UnaryFunc::CastStringToPgLegacyName(_) => CastStringToPgLegacyName(()),
6376            UnaryFunc::CastStringToBytes(_) => CastStringToBytes(()),
6377            UnaryFunc::CastStringToInt16(_) => CastStringToInt16(()),
6378            UnaryFunc::CastStringToInt32(_) => CastStringToInt32(()),
6379            UnaryFunc::CastStringToInt64(_) => CastStringToInt64(()),
6380            UnaryFunc::CastStringToUint16(_) => CastStringToUint16(()),
6381            UnaryFunc::CastStringToUint32(_) => CastStringToUint32(()),
6382            UnaryFunc::CastStringToUint64(_) => CastStringToUint64(()),
6383            UnaryFunc::CastStringToInt2Vector(_) => CastStringToInt2Vector(()),
6384            UnaryFunc::CastStringToOid(_) => CastStringToOid(()),
6385            UnaryFunc::CastStringToFloat32(_) => CastStringToFloat32(()),
6386            UnaryFunc::CastStringToFloat64(_) => CastStringToFloat64(()),
6387            UnaryFunc::CastStringToDate(_) => CastStringToDate(()),
6388            UnaryFunc::CastStringToArray(inner) => {
6389                CastStringToArray(Box::new(ProtoCastToVariableType {
6390                    return_ty: Some(inner.return_ty.into_proto()),
6391                    cast_expr: Some(inner.cast_expr.into_proto()),
6392                }))
6393            }
6394            UnaryFunc::CastStringToList(inner) => {
6395                CastStringToList(Box::new(ProtoCastToVariableType {
6396                    return_ty: Some(inner.return_ty.into_proto()),
6397                    cast_expr: Some(inner.cast_expr.into_proto()),
6398                }))
6399            }
6400            UnaryFunc::CastStringToMap(inner) => {
6401                CastStringToMap(Box::new(ProtoCastToVariableType {
6402                    return_ty: Some(inner.return_ty.into_proto()),
6403                    cast_expr: Some(inner.cast_expr.into_proto()),
6404                }))
6405            }
6406            UnaryFunc::CastStringToRange(inner) => {
6407                CastStringToRange(Box::new(ProtoCastToVariableType {
6408                    return_ty: Some(inner.return_ty.into_proto()),
6409                    cast_expr: Some(inner.cast_expr.into_proto()),
6410                }))
6411            }
6412            UnaryFunc::CastStringToTime(_) => CastStringToTime(()),
6413            UnaryFunc::CastStringToTimestamp(precision) => {
6414                CastStringToTimestamp(precision.0.into_proto())
6415            }
6416            UnaryFunc::CastStringToTimestampTz(precision) => {
6417                CastStringToTimestampTz(precision.0.into_proto())
6418            }
6419            UnaryFunc::CastStringToInterval(_) => CastStringToInterval(()),
6420            UnaryFunc::CastStringToNumeric(func) => CastStringToNumeric(func.0.into_proto()),
6421            UnaryFunc::CastStringToUuid(_) => CastStringToUuid(()),
6422            UnaryFunc::CastStringToChar(func) => CastStringToChar(ProtoCastStringToChar {
6423                length: func.length.into_proto(),
6424                fail_on_len: func.fail_on_len,
6425            }),
6426            UnaryFunc::PadChar(func) => PadChar(ProtoPadChar {
6427                length: func.length.into_proto(),
6428            }),
6429            UnaryFunc::CastStringToVarChar(func) => CastStringToVarChar(ProtoCastStringToVarChar {
6430                length: func.length.into_proto(),
6431                fail_on_len: func.fail_on_len,
6432            }),
6433            UnaryFunc::CastCharToString(_) => CastCharToString(()),
6434            UnaryFunc::CastVarCharToString(_) => CastVarCharToString(()),
6435            UnaryFunc::CastDateToTimestamp(func) => CastDateToTimestamp(func.0.into_proto()),
6436            UnaryFunc::CastDateToTimestampTz(func) => CastDateToTimestampTz(func.0.into_proto()),
6437            UnaryFunc::CastDateToString(_) => CastDateToString(()),
6438            UnaryFunc::CastTimeToInterval(_) => CastTimeToInterval(()),
6439            UnaryFunc::CastTimeToString(_) => CastTimeToString(()),
6440            UnaryFunc::CastIntervalToString(_) => CastIntervalToString(()),
6441            UnaryFunc::CastIntervalToTime(_) => CastIntervalToTime(()),
6442            UnaryFunc::CastTimestampToDate(_) => CastTimestampToDate(()),
6443            UnaryFunc::AdjustTimestampPrecision(func) => Kind::AdjustTimestampPrecision(
6444                mz_repr::adt::timestamp::ProtoFromToTimestampPrecisions {
6445                    from: func.from.map(|p| p.into_proto()),
6446                    to: func.to.map(|p| p.into_proto()),
6447                },
6448            ),
6449            UnaryFunc::CastTimestampToTimestampTz(func) => CastTimestampToTimestampTz(
6450                mz_repr::adt::timestamp::ProtoFromToTimestampPrecisions {
6451                    from: func.from.map(|p| p.into_proto()),
6452                    to: func.to.map(|p| p.into_proto()),
6453                },
6454            ),
6455            UnaryFunc::CastTimestampToString(_) => CastTimestampToString(()),
6456            UnaryFunc::CastTimestampToTime(_) => CastTimestampToTime(()),
6457            UnaryFunc::CastTimestampTzToDate(_) => CastTimestampTzToDate(()),
6458            UnaryFunc::AdjustTimestampTzPrecision(func) => Kind::AdjustTimestampTzPrecision(
6459                mz_repr::adt::timestamp::ProtoFromToTimestampPrecisions {
6460                    from: func.from.map(|p| p.into_proto()),
6461                    to: func.to.map(|p| p.into_proto()),
6462                },
6463            ),
6464            UnaryFunc::CastTimestampTzToTimestamp(func) => CastTimestampTzToTimestamp(
6465                mz_repr::adt::timestamp::ProtoFromToTimestampPrecisions {
6466                    from: func.from.map(|p| p.into_proto()),
6467                    to: func.to.map(|p| p.into_proto()),
6468                },
6469            ),
6470            UnaryFunc::CastTimestampTzToString(_) => CastTimestampTzToString(()),
6471            UnaryFunc::CastTimestampTzToTime(_) => CastTimestampTzToTime(()),
6472            UnaryFunc::CastPgLegacyCharToString(_) => CastPgLegacyCharToString(()),
6473            UnaryFunc::CastPgLegacyCharToChar(_) => CastPgLegacyCharToChar(()),
6474            UnaryFunc::CastPgLegacyCharToVarChar(_) => CastPgLegacyCharToVarChar(()),
6475            UnaryFunc::CastPgLegacyCharToInt32(_) => CastPgLegacyCharToInt32(()),
6476            UnaryFunc::CastBytesToString(_) => CastBytesToString(()),
6477            UnaryFunc::CastStringToJsonb(_) => CastStringToJsonb(()),
6478            UnaryFunc::CastJsonbToString(_) => CastJsonbToString(()),
6479            UnaryFunc::CastJsonbableToJsonb(_) => CastJsonbableToJsonb(()),
6480            UnaryFunc::CastJsonbToInt16(_) => CastJsonbToInt16(()),
6481            UnaryFunc::CastJsonbToInt32(_) => CastJsonbToInt32(()),
6482            UnaryFunc::CastJsonbToInt64(_) => CastJsonbToInt64(()),
6483            UnaryFunc::CastJsonbToFloat32(_) => CastJsonbToFloat32(()),
6484            UnaryFunc::CastJsonbToFloat64(_) => CastJsonbToFloat64(()),
6485            UnaryFunc::CastJsonbToNumeric(func) => CastJsonbToNumeric(func.0.into_proto()),
6486            UnaryFunc::CastJsonbToBool(_) => CastJsonbToBool(()),
6487            UnaryFunc::CastUuidToString(_) => CastUuidToString(()),
6488            UnaryFunc::CastRecordToString(func) => CastRecordToString(func.ty.into_proto()),
6489            UnaryFunc::CastRecord1ToRecord2(inner) => {
6490                CastRecord1ToRecord2(ProtoCastRecord1ToRecord2 {
6491                    return_ty: Some(inner.return_ty.into_proto()),
6492                    cast_exprs: inner.cast_exprs.into_proto(),
6493                })
6494            }
6495            UnaryFunc::CastArrayToArray(inner) => {
6496                CastArrayToArray(Box::new(ProtoCastToVariableType {
6497                    return_ty: Some(inner.return_ty.into_proto()),
6498                    cast_expr: Some(inner.cast_expr.into_proto()),
6499                }))
6500            }
6501            UnaryFunc::CastArrayToJsonb(inner) => CastArrayToJsonb(inner.cast_element.into_proto()),
6502            UnaryFunc::CastArrayToString(func) => CastArrayToString(func.ty.into_proto()),
6503            UnaryFunc::CastListToJsonb(inner) => CastListToJsonb(inner.cast_element.into_proto()),
6504            UnaryFunc::CastListToString(func) => CastListToString(func.ty.into_proto()),
6505            UnaryFunc::CastList1ToList2(inner) => {
6506                CastList1ToList2(Box::new(ProtoCastToVariableType {
6507                    return_ty: Some(inner.return_ty.into_proto()),
6508                    cast_expr: Some(inner.cast_expr.into_proto()),
6509                }))
6510            }
6511            UnaryFunc::CastArrayToListOneDim(_) => CastArrayToListOneDim(()),
6512            UnaryFunc::CastMapToString(func) => CastMapToString(func.ty.into_proto()),
6513            UnaryFunc::CastInt2VectorToString(_) => CastInt2VectorToString(()),
6514            UnaryFunc::CastRangeToString(func) => CastRangeToString(func.ty.into_proto()),
6515            UnaryFunc::CeilFloat32(_) => CeilFloat32(()),
6516            UnaryFunc::CeilFloat64(_) => CeilFloat64(()),
6517            UnaryFunc::CeilNumeric(_) => CeilNumeric(()),
6518            UnaryFunc::FloorFloat32(_) => FloorFloat32(()),
6519            UnaryFunc::FloorFloat64(_) => FloorFloat64(()),
6520            UnaryFunc::FloorNumeric(_) => FloorNumeric(()),
6521            UnaryFunc::Ascii(_) => Ascii(()),
6522            UnaryFunc::BitCountBytes(_) => BitCountBytes(()),
6523            UnaryFunc::BitLengthBytes(_) => BitLengthBytes(()),
6524            UnaryFunc::BitLengthString(_) => BitLengthString(()),
6525            UnaryFunc::ByteLengthBytes(_) => ByteLengthBytes(()),
6526            UnaryFunc::ByteLengthString(_) => ByteLengthString(()),
6527            UnaryFunc::CharLength(_) => CharLength(()),
6528            UnaryFunc::Chr(_) => Chr(()),
6529            UnaryFunc::IsLikeMatch(pattern) => IsLikeMatch(pattern.0.into_proto()),
6530            UnaryFunc::IsRegexpMatch(regex) => IsRegexpMatch(regex.0.into_proto()),
6531            UnaryFunc::RegexpMatch(regex) => RegexpMatch(regex.0.into_proto()),
6532            UnaryFunc::RegexpSplitToArray(regex) => RegexpSplitToArray(regex.0.into_proto()),
6533            UnaryFunc::ExtractInterval(func) => ExtractInterval(func.0.into_proto()),
6534            UnaryFunc::ExtractTime(func) => ExtractTime(func.0.into_proto()),
6535            UnaryFunc::ExtractTimestamp(func) => ExtractTimestamp(func.0.into_proto()),
6536            UnaryFunc::ExtractTimestampTz(func) => ExtractTimestampTz(func.0.into_proto()),
6537            UnaryFunc::ExtractDate(func) => ExtractDate(func.0.into_proto()),
6538            UnaryFunc::DatePartInterval(func) => DatePartInterval(func.0.into_proto()),
6539            UnaryFunc::DatePartTime(func) => DatePartTime(func.0.into_proto()),
6540            UnaryFunc::DatePartTimestamp(func) => DatePartTimestamp(func.0.into_proto()),
6541            UnaryFunc::DatePartTimestampTz(func) => DatePartTimestampTz(func.0.into_proto()),
6542            UnaryFunc::DateTruncTimestamp(func) => DateTruncTimestamp(func.0.into_proto()),
6543            UnaryFunc::DateTruncTimestampTz(func) => DateTruncTimestampTz(func.0.into_proto()),
6544            UnaryFunc::TimezoneTimestamp(func) => TimezoneTimestamp(func.0.into_proto()),
6545            UnaryFunc::TimezoneTimestampTz(func) => TimezoneTimestampTz(func.0.into_proto()),
6546            UnaryFunc::TimezoneTime(func) => TimezoneTime(ProtoTimezoneTime {
6547                tz: Some(func.tz.into_proto()),
6548                wall_time: Some(func.wall_time.into_proto()),
6549            }),
6550            UnaryFunc::ToTimestamp(_) => ToTimestamp(()),
6551            UnaryFunc::ToCharTimestamp(func) => ToCharTimestamp(ProtoToCharTimestamp {
6552                format_string: func.format_string.into_proto(),
6553                format: Some(func.format.into_proto()),
6554            }),
6555            UnaryFunc::ToCharTimestampTz(func) => ToCharTimestampTz(ProtoToCharTimestamp {
6556                format_string: func.format_string.into_proto(),
6557                format: Some(func.format.into_proto()),
6558            }),
6559            UnaryFunc::JustifyDays(_) => JustifyDays(()),
6560            UnaryFunc::JustifyHours(_) => JustifyHours(()),
6561            UnaryFunc::JustifyInterval(_) => JustifyInterval(()),
6562            UnaryFunc::JsonbArrayLength(_) => JsonbArrayLength(()),
6563            UnaryFunc::JsonbTypeof(_) => JsonbTypeof(()),
6564            UnaryFunc::JsonbStripNulls(_) => JsonbStripNulls(()),
6565            UnaryFunc::JsonbPretty(_) => JsonbPretty(()),
6566            UnaryFunc::RoundFloat32(_) => RoundFloat32(()),
6567            UnaryFunc::RoundFloat64(_) => RoundFloat64(()),
6568            UnaryFunc::RoundNumeric(_) => RoundNumeric(()),
6569            UnaryFunc::TruncFloat32(_) => TruncFloat32(()),
6570            UnaryFunc::TruncFloat64(_) => TruncFloat64(()),
6571            UnaryFunc::TruncNumeric(_) => TruncNumeric(()),
6572            UnaryFunc::TrimWhitespace(_) => TrimWhitespace(()),
6573            UnaryFunc::TrimLeadingWhitespace(_) => TrimLeadingWhitespace(()),
6574            UnaryFunc::TrimTrailingWhitespace(_) => TrimTrailingWhitespace(()),
6575            UnaryFunc::Initcap(_) => Initcap(()),
6576            UnaryFunc::RecordGet(func) => RecordGet(func.0.into_proto()),
6577            UnaryFunc::ListLength(_) => ListLength(()),
6578            UnaryFunc::MapBuildFromRecordList(inner) => {
6579                MapBuildFromRecordList(inner.value_type.into_proto())
6580            }
6581            UnaryFunc::MapLength(_) => MapLength(()),
6582            UnaryFunc::Upper(_) => Upper(()),
6583            UnaryFunc::Lower(_) => Lower(()),
6584            UnaryFunc::Cos(_) => Cos(()),
6585            UnaryFunc::Acos(_) => Acos(()),
6586            UnaryFunc::Cosh(_) => Cosh(()),
6587            UnaryFunc::Acosh(_) => Acosh(()),
6588            UnaryFunc::Sin(_) => Sin(()),
6589            UnaryFunc::Asin(_) => Asin(()),
6590            UnaryFunc::Sinh(_) => Sinh(()),
6591            UnaryFunc::Asinh(_) => Asinh(()),
6592            UnaryFunc::Tan(_) => Tan(()),
6593            UnaryFunc::Atan(_) => Atan(()),
6594            UnaryFunc::Tanh(_) => Tanh(()),
6595            UnaryFunc::Atanh(_) => Atanh(()),
6596            UnaryFunc::Cot(_) => Cot(()),
6597            UnaryFunc::Degrees(_) => Degrees(()),
6598            UnaryFunc::Radians(_) => Radians(()),
6599            UnaryFunc::Log10(_) => Log10(()),
6600            UnaryFunc::Log10Numeric(_) => Log10Numeric(()),
6601            UnaryFunc::Ln(_) => Ln(()),
6602            UnaryFunc::LnNumeric(_) => LnNumeric(()),
6603            UnaryFunc::Exp(_) => Exp(()),
6604            UnaryFunc::ExpNumeric(_) => ExpNumeric(()),
6605            UnaryFunc::Sleep(_) => Sleep(()),
6606            UnaryFunc::Panic(_) => Panic(()),
6607            UnaryFunc::AdjustNumericScale(func) => AdjustNumericScale(func.0.into_proto()),
6608            UnaryFunc::PgColumnSize(_) => PgColumnSize(()),
6609            UnaryFunc::PgSizePretty(_) => PgSizePretty(()),
6610            UnaryFunc::MzRowSize(_) => MzRowSize(()),
6611            UnaryFunc::MzTypeName(_) => MzTypeName(()),
6612            UnaryFunc::CastMzTimestampToString(_) => CastMzTimestampToString(()),
6613            UnaryFunc::CastMzTimestampToTimestamp(_) => CastMzTimestampToTimestamp(()),
6614            UnaryFunc::CastMzTimestampToTimestampTz(_) => CastMzTimestampToTimestampTz(()),
6615            UnaryFunc::CastStringToMzTimestamp(_) => CastStringToMzTimestamp(()),
6616            UnaryFunc::CastUint64ToMzTimestamp(_) => CastUint64ToMzTimestamp(()),
6617            UnaryFunc::CastUint32ToMzTimestamp(_) => CastUint32ToMzTimestamp(()),
6618            UnaryFunc::CastInt64ToMzTimestamp(_) => CastInt64ToMzTimestamp(()),
6619            UnaryFunc::CastInt32ToMzTimestamp(_) => CastInt32ToMzTimestamp(()),
6620            UnaryFunc::CastNumericToMzTimestamp(_) => CastNumericToMzTimestamp(()),
6621            UnaryFunc::CastTimestampToMzTimestamp(_) => CastTimestampToMzTimestamp(()),
6622            UnaryFunc::CastTimestampTzToMzTimestamp(_) => CastTimestampTzToMzTimestamp(()),
6623            UnaryFunc::CastDateToMzTimestamp(_) => CastDateToMzTimestamp(()),
6624            UnaryFunc::StepMzTimestamp(_) => StepMzTimestamp(()),
6625            UnaryFunc::RangeLower(_) => RangeLower(()),
6626            UnaryFunc::RangeUpper(_) => RangeUpper(()),
6627            UnaryFunc::RangeEmpty(_) => RangeEmpty(()),
6628            UnaryFunc::RangeLowerInc(_) => RangeLowerInc(()),
6629            UnaryFunc::RangeUpperInc(_) => RangeUpperInc(()),
6630            UnaryFunc::RangeLowerInf(_) => RangeLowerInf(()),
6631            UnaryFunc::RangeUpperInf(_) => RangeUpperInf(()),
6632            UnaryFunc::MzAclItemGrantor(_) => MzAclItemGrantor(()),
6633            UnaryFunc::MzAclItemGrantee(_) => MzAclItemGrantee(()),
6634            UnaryFunc::MzAclItemPrivileges(_) => MzAclItemPrivileges(()),
6635            UnaryFunc::MzFormatPrivileges(_) => MzFormatPrivileges(()),
6636            UnaryFunc::MzValidatePrivileges(_) => MzValidatePrivileges(()),
6637            UnaryFunc::MzValidateRolePrivilege(_) => MzValidateRolePrivilege(()),
6638            UnaryFunc::AclItemGrantor(_) => AclItemGrantor(()),
6639            UnaryFunc::AclItemGrantee(_) => AclItemGrantee(()),
6640            UnaryFunc::AclItemPrivileges(_) => AclItemPrivileges(()),
6641            UnaryFunc::QuoteIdent(_) => QuoteIdent(()),
6642            UnaryFunc::TryParseMonotonicIso8601Timestamp(_) => {
6643                TryParseMonotonicIso8601Timestamp(())
6644            }
6645            UnaryFunc::Crc32Bytes(_) => Crc32Bytes(()),
6646            UnaryFunc::Crc32String(_) => Crc32String(()),
6647            UnaryFunc::KafkaMurmur2Bytes(_) => KafkaMurmur2Bytes(()),
6648            UnaryFunc::KafkaMurmur2String(_) => KafkaMurmur2String(()),
6649            UnaryFunc::SeahashBytes(_) => SeahashBytes(()),
6650            UnaryFunc::SeahashString(_) => SeahashString(()),
6651            UnaryFunc::Reverse(_) => Reverse(()),
6652        };
6653        ProtoUnaryFunc { kind: Some(kind) }
6654    }
6655
6656    fn from_proto(proto: ProtoUnaryFunc) -> Result<Self, TryFromProtoError> {
6657        use crate::scalar::proto_unary_func::Kind::*;
6658        if let Some(kind) = proto.kind {
6659            match kind {
6660                Not(()) => Ok(impls::Not.into()),
6661                IsNull(()) => Ok(impls::IsNull.into()),
6662                IsTrue(()) => Ok(impls::IsTrue.into()),
6663                IsFalse(()) => Ok(impls::IsFalse.into()),
6664                BitNotInt16(()) => Ok(impls::BitNotInt16.into()),
6665                BitNotInt32(()) => Ok(impls::BitNotInt32.into()),
6666                BitNotInt64(()) => Ok(impls::BitNotInt64.into()),
6667                BitNotUint16(()) => Ok(impls::BitNotUint16.into()),
6668                BitNotUint32(()) => Ok(impls::BitNotUint32.into()),
6669                BitNotUint64(()) => Ok(impls::BitNotUint64.into()),
6670                NegInt16(()) => Ok(impls::NegInt16.into()),
6671                NegInt32(()) => Ok(impls::NegInt32.into()),
6672                NegInt64(()) => Ok(impls::NegInt64.into()),
6673                NegFloat32(()) => Ok(impls::NegFloat32.into()),
6674                NegFloat64(()) => Ok(impls::NegFloat64.into()),
6675                NegNumeric(()) => Ok(impls::NegNumeric.into()),
6676                NegInterval(()) => Ok(impls::NegInterval.into()),
6677                SqrtFloat64(()) => Ok(impls::SqrtFloat64.into()),
6678                SqrtNumeric(()) => Ok(impls::SqrtNumeric.into()),
6679                CbrtFloat64(()) => Ok(impls::CbrtFloat64.into()),
6680                AbsInt16(()) => Ok(impls::AbsInt16.into()),
6681                AbsInt32(()) => Ok(impls::AbsInt32.into()),
6682                AbsInt64(()) => Ok(impls::AbsInt64.into()),
6683                AbsFloat32(()) => Ok(impls::AbsFloat32.into()),
6684                AbsFloat64(()) => Ok(impls::AbsFloat64.into()),
6685                AbsNumeric(()) => Ok(impls::AbsNumeric.into()),
6686                CastBoolToString(()) => Ok(impls::CastBoolToString.into()),
6687                CastBoolToStringNonstandard(()) => Ok(impls::CastBoolToStringNonstandard.into()),
6688                CastBoolToInt32(()) => Ok(impls::CastBoolToInt32.into()),
6689                CastBoolToInt64(()) => Ok(impls::CastBoolToInt64.into()),
6690                CastInt16ToFloat32(()) => Ok(impls::CastInt16ToFloat32.into()),
6691                CastInt16ToFloat64(()) => Ok(impls::CastInt16ToFloat64.into()),
6692                CastInt16ToInt32(()) => Ok(impls::CastInt16ToInt32.into()),
6693                CastInt16ToInt64(()) => Ok(impls::CastInt16ToInt64.into()),
6694                CastInt16ToUint16(()) => Ok(impls::CastInt16ToUint16.into()),
6695                CastInt16ToUint32(()) => Ok(impls::CastInt16ToUint32.into()),
6696                CastInt16ToUint64(()) => Ok(impls::CastInt16ToUint64.into()),
6697                CastInt16ToString(()) => Ok(impls::CastInt16ToString.into()),
6698                CastInt2VectorToArray(()) => Ok(impls::CastInt2VectorToArray.into()),
6699                CastInt32ToBool(()) => Ok(impls::CastInt32ToBool.into()),
6700                CastInt32ToFloat32(()) => Ok(impls::CastInt32ToFloat32.into()),
6701                CastInt32ToFloat64(()) => Ok(impls::CastInt32ToFloat64.into()),
6702                CastInt32ToOid(()) => Ok(impls::CastInt32ToOid.into()),
6703                CastInt32ToPgLegacyChar(()) => Ok(impls::CastInt32ToPgLegacyChar.into()),
6704                CastInt32ToInt16(()) => Ok(impls::CastInt32ToInt16.into()),
6705                CastInt32ToInt64(()) => Ok(impls::CastInt32ToInt64.into()),
6706                CastInt32ToUint16(()) => Ok(impls::CastInt32ToUint16.into()),
6707                CastInt32ToUint32(()) => Ok(impls::CastInt32ToUint32.into()),
6708                CastInt32ToUint64(()) => Ok(impls::CastInt32ToUint64.into()),
6709                CastInt32ToString(()) => Ok(impls::CastInt32ToString.into()),
6710                CastOidToInt32(()) => Ok(impls::CastOidToInt32.into()),
6711                CastOidToInt64(()) => Ok(impls::CastOidToInt64.into()),
6712                CastOidToString(()) => Ok(impls::CastOidToString.into()),
6713                CastOidToRegClass(()) => Ok(impls::CastOidToRegClass.into()),
6714                CastRegClassToOid(()) => Ok(impls::CastRegClassToOid.into()),
6715                CastOidToRegProc(()) => Ok(impls::CastOidToRegProc.into()),
6716                CastRegProcToOid(()) => Ok(impls::CastRegProcToOid.into()),
6717                CastOidToRegType(()) => Ok(impls::CastOidToRegType.into()),
6718                CastRegTypeToOid(()) => Ok(impls::CastRegTypeToOid.into()),
6719                CastInt64ToInt16(()) => Ok(impls::CastInt64ToInt16.into()),
6720                CastInt64ToInt32(()) => Ok(impls::CastInt64ToInt32.into()),
6721                CastInt64ToUint16(()) => Ok(impls::CastInt64ToUint16.into()),
6722                CastInt64ToUint32(()) => Ok(impls::CastInt64ToUint32.into()),
6723                CastInt64ToUint64(()) => Ok(impls::CastInt64ToUint64.into()),
6724                CastInt16ToNumeric(max_scale) => {
6725                    Ok(impls::CastInt16ToNumeric(max_scale.into_rust()?).into())
6726                }
6727                CastInt32ToNumeric(max_scale) => {
6728                    Ok(impls::CastInt32ToNumeric(max_scale.into_rust()?).into())
6729                }
6730                CastInt64ToBool(()) => Ok(impls::CastInt64ToBool.into()),
6731                CastInt64ToNumeric(max_scale) => {
6732                    Ok(impls::CastInt64ToNumeric(max_scale.into_rust()?).into())
6733                }
6734                CastInt64ToFloat32(()) => Ok(impls::CastInt64ToFloat32.into()),
6735                CastInt64ToFloat64(()) => Ok(impls::CastInt64ToFloat64.into()),
6736                CastInt64ToOid(()) => Ok(impls::CastInt64ToOid.into()),
6737                CastInt64ToString(()) => Ok(impls::CastInt64ToString.into()),
6738                CastUint16ToUint32(()) => Ok(impls::CastUint16ToUint32.into()),
6739                CastUint16ToUint64(()) => Ok(impls::CastUint16ToUint64.into()),
6740                CastUint16ToInt16(()) => Ok(impls::CastUint16ToInt16.into()),
6741                CastUint16ToInt32(()) => Ok(impls::CastUint16ToInt32.into()),
6742                CastUint16ToInt64(()) => Ok(impls::CastUint16ToInt64.into()),
6743                CastUint16ToNumeric(max_scale) => {
6744                    Ok(impls::CastUint16ToNumeric(max_scale.into_rust()?).into())
6745                }
6746                CastUint16ToFloat32(()) => Ok(impls::CastUint16ToFloat32.into()),
6747                CastUint16ToFloat64(()) => Ok(impls::CastUint16ToFloat64.into()),
6748                CastUint16ToString(()) => Ok(impls::CastUint16ToString.into()),
6749                CastUint32ToUint16(()) => Ok(impls::CastUint32ToUint16.into()),
6750                CastUint32ToUint64(()) => Ok(impls::CastUint32ToUint64.into()),
6751                CastUint32ToInt16(()) => Ok(impls::CastUint32ToInt16.into()),
6752                CastUint32ToInt32(()) => Ok(impls::CastUint32ToInt32.into()),
6753                CastUint32ToInt64(()) => Ok(impls::CastUint32ToInt64.into()),
6754                CastUint32ToNumeric(max_scale) => {
6755                    Ok(impls::CastUint32ToNumeric(max_scale.into_rust()?).into())
6756                }
6757                CastUint32ToFloat32(()) => Ok(impls::CastUint32ToFloat32.into()),
6758                CastUint32ToFloat64(()) => Ok(impls::CastUint32ToFloat64.into()),
6759                CastUint32ToString(()) => Ok(impls::CastUint32ToString.into()),
6760                CastUint64ToUint16(()) => Ok(impls::CastUint64ToUint16.into()),
6761                CastUint64ToUint32(()) => Ok(impls::CastUint64ToUint32.into()),
6762                CastUint64ToInt16(()) => Ok(impls::CastUint64ToInt16.into()),
6763                CastUint64ToInt32(()) => Ok(impls::CastUint64ToInt32.into()),
6764                CastUint64ToInt64(()) => Ok(impls::CastUint64ToInt64.into()),
6765                CastUint64ToNumeric(max_scale) => {
6766                    Ok(impls::CastUint64ToNumeric(max_scale.into_rust()?).into())
6767                }
6768                CastUint64ToFloat32(()) => Ok(impls::CastUint64ToFloat32.into()),
6769                CastUint64ToFloat64(()) => Ok(impls::CastUint64ToFloat64.into()),
6770                CastUint64ToString(()) => Ok(impls::CastUint64ToString.into()),
6771                CastFloat32ToInt16(()) => Ok(impls::CastFloat32ToInt16.into()),
6772                CastFloat32ToInt32(()) => Ok(impls::CastFloat32ToInt32.into()),
6773                CastFloat32ToInt64(()) => Ok(impls::CastFloat32ToInt64.into()),
6774                CastFloat32ToUint16(()) => Ok(impls::CastFloat32ToUint16.into()),
6775                CastFloat32ToUint32(()) => Ok(impls::CastFloat32ToUint32.into()),
6776                CastFloat32ToUint64(()) => Ok(impls::CastFloat32ToUint64.into()),
6777                CastFloat32ToFloat64(()) => Ok(impls::CastFloat32ToFloat64.into()),
6778                CastFloat32ToString(()) => Ok(impls::CastFloat32ToString.into()),
6779                CastFloat32ToNumeric(max_scale) => {
6780                    Ok(impls::CastFloat32ToNumeric(max_scale.into_rust()?).into())
6781                }
6782                CastFloat64ToNumeric(max_scale) => {
6783                    Ok(impls::CastFloat64ToNumeric(max_scale.into_rust()?).into())
6784                }
6785                CastFloat64ToInt16(()) => Ok(impls::CastFloat64ToInt16.into()),
6786                CastFloat64ToInt32(()) => Ok(impls::CastFloat64ToInt32.into()),
6787                CastFloat64ToInt64(()) => Ok(impls::CastFloat64ToInt64.into()),
6788                CastFloat64ToUint16(()) => Ok(impls::CastFloat64ToUint16.into()),
6789                CastFloat64ToUint32(()) => Ok(impls::CastFloat64ToUint32.into()),
6790                CastFloat64ToUint64(()) => Ok(impls::CastFloat64ToUint64.into()),
6791                CastFloat64ToFloat32(()) => Ok(impls::CastFloat64ToFloat32.into()),
6792                CastFloat64ToString(()) => Ok(impls::CastFloat64ToString.into()),
6793                CastNumericToFloat32(()) => Ok(impls::CastNumericToFloat32.into()),
6794                CastNumericToFloat64(()) => Ok(impls::CastNumericToFloat64.into()),
6795                CastNumericToInt16(()) => Ok(impls::CastNumericToInt16.into()),
6796                CastNumericToInt32(()) => Ok(impls::CastNumericToInt32.into()),
6797                CastNumericToInt64(()) => Ok(impls::CastNumericToInt64.into()),
6798                CastNumericToUint16(()) => Ok(impls::CastNumericToUint16.into()),
6799                CastNumericToUint32(()) => Ok(impls::CastNumericToUint32.into()),
6800                CastNumericToUint64(()) => Ok(impls::CastNumericToUint64.into()),
6801                CastNumericToString(()) => Ok(impls::CastNumericToString.into()),
6802                CastStringToBool(()) => Ok(impls::CastStringToBool.into()),
6803                CastStringToPgLegacyChar(()) => Ok(impls::CastStringToPgLegacyChar.into()),
6804                CastStringToPgLegacyName(()) => Ok(impls::CastStringToPgLegacyName.into()),
6805                CastStringToBytes(()) => Ok(impls::CastStringToBytes.into()),
6806                CastStringToInt16(()) => Ok(impls::CastStringToInt16.into()),
6807                CastStringToInt32(()) => Ok(impls::CastStringToInt32.into()),
6808                CastStringToInt64(()) => Ok(impls::CastStringToInt64.into()),
6809                CastStringToUint16(()) => Ok(impls::CastStringToUint16.into()),
6810                CastStringToUint32(()) => Ok(impls::CastStringToUint32.into()),
6811                CastStringToUint64(()) => Ok(impls::CastStringToUint64.into()),
6812                CastStringToInt2Vector(()) => Ok(impls::CastStringToInt2Vector.into()),
6813                CastStringToOid(()) => Ok(impls::CastStringToOid.into()),
6814                CastStringToFloat32(()) => Ok(impls::CastStringToFloat32.into()),
6815                CastStringToFloat64(()) => Ok(impls::CastStringToFloat64.into()),
6816                CastStringToDate(()) => Ok(impls::CastStringToDate.into()),
6817                CastStringToArray(inner) => Ok(impls::CastStringToArray {
6818                    return_ty: inner
6819                        .return_ty
6820                        .into_rust_if_some("ProtoCastStringToArray::return_ty")?,
6821                    cast_expr: inner
6822                        .cast_expr
6823                        .into_rust_if_some("ProtoCastStringToArray::cast_expr")?,
6824                }
6825                .into()),
6826                CastStringToList(inner) => Ok(impls::CastStringToList {
6827                    return_ty: inner
6828                        .return_ty
6829                        .into_rust_if_some("ProtoCastStringToList::return_ty")?,
6830                    cast_expr: inner
6831                        .cast_expr
6832                        .into_rust_if_some("ProtoCastStringToList::cast_expr")?,
6833                }
6834                .into()),
6835                CastStringToRange(inner) => Ok(impls::CastStringToRange {
6836                    return_ty: inner
6837                        .return_ty
6838                        .into_rust_if_some("ProtoCastStringToRange::return_ty")?,
6839                    cast_expr: inner
6840                        .cast_expr
6841                        .into_rust_if_some("ProtoCastStringToRange::cast_expr")?,
6842                }
6843                .into()),
6844                CastStringToMap(inner) => Ok(impls::CastStringToMap {
6845                    return_ty: inner
6846                        .return_ty
6847                        .into_rust_if_some("ProtoCastStringToMap::return_ty")?,
6848                    cast_expr: inner
6849                        .cast_expr
6850                        .into_rust_if_some("ProtoCastStringToMap::cast_expr")?,
6851                }
6852                .into()),
6853                CastStringToTime(()) => Ok(impls::CastStringToTime.into()),
6854                CastStringToTimestamp(precision) => {
6855                    Ok(impls::CastStringToTimestamp(precision.into_rust()?).into())
6856                }
6857                CastStringToTimestampTz(precision) => {
6858                    Ok(impls::CastStringToTimestampTz(precision.into_rust()?).into())
6859                }
6860                CastStringToInterval(()) => Ok(impls::CastStringToInterval.into()),
6861                CastStringToNumeric(max_scale) => {
6862                    Ok(impls::CastStringToNumeric(max_scale.into_rust()?).into())
6863                }
6864                CastStringToUuid(()) => Ok(impls::CastStringToUuid.into()),
6865                CastStringToChar(func) => Ok(impls::CastStringToChar {
6866                    length: func.length.into_rust()?,
6867                    fail_on_len: func.fail_on_len,
6868                }
6869                .into()),
6870                PadChar(func) => Ok(impls::PadChar {
6871                    length: func.length.into_rust()?,
6872                }
6873                .into()),
6874                CastStringToVarChar(func) => Ok(impls::CastStringToVarChar {
6875                    length: func.length.into_rust()?,
6876                    fail_on_len: func.fail_on_len,
6877                }
6878                .into()),
6879                CastCharToString(()) => Ok(impls::CastCharToString.into()),
6880                CastVarCharToString(()) => Ok(impls::CastVarCharToString.into()),
6881                CastDateToTimestamp(precision) => {
6882                    Ok(impls::CastDateToTimestamp(precision.into_rust()?).into())
6883                }
6884                CastDateToTimestampTz(precision) => {
6885                    Ok(impls::CastDateToTimestampTz(precision.into_rust()?).into())
6886                }
6887                CastDateToString(()) => Ok(impls::CastDateToString.into()),
6888                CastTimeToInterval(()) => Ok(impls::CastTimeToInterval.into()),
6889                CastTimeToString(()) => Ok(impls::CastTimeToString.into()),
6890                CastIntervalToString(()) => Ok(impls::CastIntervalToString.into()),
6891                CastIntervalToTime(()) => Ok(impls::CastIntervalToTime.into()),
6892                CastTimestampToDate(()) => Ok(impls::CastTimestampToDate.into()),
6893                AdjustTimestampPrecision(precisions) => Ok(impls::AdjustTimestampPrecision {
6894                    from: precisions.from.into_rust()?,
6895                    to: precisions.to.into_rust()?,
6896                }
6897                .into()),
6898                CastTimestampToTimestampTz(precisions) => Ok(impls::CastTimestampToTimestampTz {
6899                    from: precisions.from.into_rust()?,
6900                    to: precisions.to.into_rust()?,
6901                }
6902                .into()),
6903                CastTimestampToString(()) => Ok(impls::CastTimestampToString.into()),
6904                CastTimestampToTime(()) => Ok(impls::CastTimestampToTime.into()),
6905                CastTimestampTzToDate(()) => Ok(impls::CastTimestampTzToDate.into()),
6906                CastTimestampTzToTimestamp(precisions) => Ok(impls::CastTimestampTzToTimestamp {
6907                    from: precisions.from.into_rust()?,
6908                    to: precisions.to.into_rust()?,
6909                }
6910                .into()),
6911                AdjustTimestampTzPrecision(precisions) => Ok(impls::AdjustTimestampTzPrecision {
6912                    from: precisions.from.into_rust()?,
6913                    to: precisions.to.into_rust()?,
6914                }
6915                .into()),
6916                CastTimestampTzToString(()) => Ok(impls::CastTimestampTzToString.into()),
6917                CastTimestampTzToTime(()) => Ok(impls::CastTimestampTzToTime.into()),
6918                CastPgLegacyCharToString(()) => Ok(impls::CastPgLegacyCharToString.into()),
6919                CastPgLegacyCharToChar(()) => Ok(impls::CastPgLegacyCharToChar.into()),
6920                CastPgLegacyCharToVarChar(()) => Ok(impls::CastPgLegacyCharToVarChar.into()),
6921                CastPgLegacyCharToInt32(()) => Ok(impls::CastPgLegacyCharToInt32.into()),
6922                CastBytesToString(()) => Ok(impls::CastBytesToString.into()),
6923                CastStringToJsonb(()) => Ok(impls::CastStringToJsonb.into()),
6924                CastJsonbToString(()) => Ok(impls::CastJsonbToString.into()),
6925                CastJsonbableToJsonb(()) => Ok(impls::CastJsonbableToJsonb.into()),
6926                CastJsonbToInt16(()) => Ok(impls::CastJsonbToInt16.into()),
6927                CastJsonbToInt32(()) => Ok(impls::CastJsonbToInt32.into()),
6928                CastJsonbToInt64(()) => Ok(impls::CastJsonbToInt64.into()),
6929                CastJsonbToFloat32(()) => Ok(impls::CastJsonbToFloat32.into()),
6930                CastJsonbToFloat64(()) => Ok(impls::CastJsonbToFloat64.into()),
6931                CastJsonbToNumeric(max_scale) => {
6932                    Ok(impls::CastJsonbToNumeric(max_scale.into_rust()?).into())
6933                }
6934                CastJsonbToBool(()) => Ok(impls::CastJsonbToBool.into()),
6935                CastUuidToString(()) => Ok(impls::CastUuidToString.into()),
6936                CastRecordToString(ty) => Ok(impls::CastRecordToString {
6937                    ty: ty.into_rust()?,
6938                }
6939                .into()),
6940                CastRecord1ToRecord2(inner) => Ok(impls::CastRecord1ToRecord2 {
6941                    return_ty: inner
6942                        .return_ty
6943                        .into_rust_if_some("ProtoCastRecord1ToRecord2::return_ty")?,
6944                    cast_exprs: inner.cast_exprs.into_rust()?,
6945                }
6946                .into()),
6947                CastArrayToArray(inner) => Ok(impls::CastArrayToArray {
6948                    return_ty: inner
6949                        .return_ty
6950                        .into_rust_if_some("ProtoCastArrayToArray::return_ty")?,
6951                    cast_expr: inner
6952                        .cast_expr
6953                        .into_rust_if_some("ProtoCastArrayToArray::cast_expr")?,
6954                }
6955                .into()),
6956                CastArrayToJsonb(cast_element) => Ok(impls::CastArrayToJsonb {
6957                    cast_element: cast_element.into_rust()?,
6958                }
6959                .into()),
6960                CastArrayToString(ty) => Ok(impls::CastArrayToString {
6961                    ty: ty.into_rust()?,
6962                }
6963                .into()),
6964                CastListToJsonb(cast_element) => Ok(impls::CastListToJsonb {
6965                    cast_element: cast_element.into_rust()?,
6966                }
6967                .into()),
6968                CastListToString(ty) => Ok(impls::CastListToString {
6969                    ty: ty.into_rust()?,
6970                }
6971                .into()),
6972                CastList1ToList2(inner) => Ok(impls::CastList1ToList2 {
6973                    return_ty: inner
6974                        .return_ty
6975                        .into_rust_if_some("ProtoCastList1ToList2::return_ty")?,
6976                    cast_expr: inner
6977                        .cast_expr
6978                        .into_rust_if_some("ProtoCastList1ToList2::cast_expr")?,
6979                }
6980                .into()),
6981                CastArrayToListOneDim(()) => Ok(impls::CastArrayToListOneDim.into()),
6982                CastMapToString(ty) => Ok(impls::CastMapToString {
6983                    ty: ty.into_rust()?,
6984                }
6985                .into()),
6986                CastInt2VectorToString(_) => Ok(impls::CastInt2VectorToString.into()),
6987                CastRangeToString(ty) => Ok(impls::CastRangeToString {
6988                    ty: ty.into_rust()?,
6989                }
6990                .into()),
6991                CeilFloat32(_) => Ok(impls::CeilFloat32.into()),
6992                CeilFloat64(_) => Ok(impls::CeilFloat64.into()),
6993                CeilNumeric(_) => Ok(impls::CeilNumeric.into()),
6994                FloorFloat32(_) => Ok(impls::FloorFloat32.into()),
6995                FloorFloat64(_) => Ok(impls::FloorFloat64.into()),
6996                FloorNumeric(_) => Ok(impls::FloorNumeric.into()),
6997                Ascii(_) => Ok(impls::Ascii.into()),
6998                BitCountBytes(_) => Ok(impls::BitCountBytes.into()),
6999                BitLengthBytes(_) => Ok(impls::BitLengthBytes.into()),
7000                BitLengthString(_) => Ok(impls::BitLengthString.into()),
7001                ByteLengthBytes(_) => Ok(impls::ByteLengthBytes.into()),
7002                ByteLengthString(_) => Ok(impls::ByteLengthString.into()),
7003                CharLength(_) => Ok(impls::CharLength.into()),
7004                Chr(_) => Ok(impls::Chr.into()),
7005                IsLikeMatch(pattern) => Ok(impls::IsLikeMatch(pattern.into_rust()?).into()),
7006                IsRegexpMatch(regex) => Ok(impls::IsRegexpMatch(regex.into_rust()?).into()),
7007                RegexpMatch(regex) => Ok(impls::RegexpMatch(regex.into_rust()?).into()),
7008                RegexpSplitToArray(regex) => {
7009                    Ok(impls::RegexpSplitToArray(regex.into_rust()?).into())
7010                }
7011                ExtractInterval(units) => Ok(impls::ExtractInterval(units.into_rust()?).into()),
7012                ExtractTime(units) => Ok(impls::ExtractTime(units.into_rust()?).into()),
7013                ExtractTimestamp(units) => Ok(impls::ExtractTimestamp(units.into_rust()?).into()),
7014                ExtractTimestampTz(units) => {
7015                    Ok(impls::ExtractTimestampTz(units.into_rust()?).into())
7016                }
7017                ExtractDate(units) => Ok(impls::ExtractDate(units.into_rust()?).into()),
7018                DatePartInterval(units) => Ok(impls::DatePartInterval(units.into_rust()?).into()),
7019                DatePartTime(units) => Ok(impls::DatePartTime(units.into_rust()?).into()),
7020                DatePartTimestamp(units) => Ok(impls::DatePartTimestamp(units.into_rust()?).into()),
7021                DatePartTimestampTz(units) => {
7022                    Ok(impls::DatePartTimestampTz(units.into_rust()?).into())
7023                }
7024                DateTruncTimestamp(units) => {
7025                    Ok(impls::DateTruncTimestamp(units.into_rust()?).into())
7026                }
7027                DateTruncTimestampTz(units) => {
7028                    Ok(impls::DateTruncTimestampTz(units.into_rust()?).into())
7029                }
7030                TimezoneTimestamp(tz) => Ok(impls::TimezoneTimestamp(tz.into_rust()?).into()),
7031                TimezoneTimestampTz(tz) => Ok(impls::TimezoneTimestampTz(tz.into_rust()?).into()),
7032                TimezoneTime(func) => Ok(impls::TimezoneTime {
7033                    tz: func.tz.into_rust_if_some("ProtoTimezoneTime::tz")?,
7034                    wall_time: func
7035                        .wall_time
7036                        .into_rust_if_some("ProtoTimezoneTime::wall_time")?,
7037                }
7038                .into()),
7039                ToTimestamp(()) => Ok(impls::ToTimestamp.into()),
7040                ToCharTimestamp(func) => Ok(impls::ToCharTimestamp {
7041                    format_string: func.format_string,
7042                    format: func
7043                        .format
7044                        .into_rust_if_some("ProtoToCharTimestamp::format")?,
7045                }
7046                .into()),
7047                ToCharTimestampTz(func) => Ok(impls::ToCharTimestampTz {
7048                    format_string: func.format_string,
7049                    format: func
7050                        .format
7051                        .into_rust_if_some("ProtoToCharTimestamp::format")?,
7052                }
7053                .into()),
7054                JustifyDays(()) => Ok(impls::JustifyDays.into()),
7055                JustifyHours(()) => Ok(impls::JustifyHours.into()),
7056                JustifyInterval(()) => Ok(impls::JustifyInterval.into()),
7057                JsonbArrayLength(()) => Ok(impls::JsonbArrayLength.into()),
7058                JsonbTypeof(()) => Ok(impls::JsonbTypeof.into()),
7059                JsonbStripNulls(()) => Ok(impls::JsonbStripNulls.into()),
7060                JsonbPretty(()) => Ok(impls::JsonbPretty.into()),
7061                RoundFloat32(()) => Ok(impls::RoundFloat32.into()),
7062                RoundFloat64(()) => Ok(impls::RoundFloat64.into()),
7063                RoundNumeric(()) => Ok(impls::RoundNumeric.into()),
7064                TruncFloat32(()) => Ok(impls::TruncFloat32.into()),
7065                TruncFloat64(()) => Ok(impls::TruncFloat64.into()),
7066                TruncNumeric(()) => Ok(impls::TruncNumeric.into()),
7067                TrimWhitespace(()) => Ok(impls::TrimWhitespace.into()),
7068                TrimLeadingWhitespace(()) => Ok(impls::TrimLeadingWhitespace.into()),
7069                TrimTrailingWhitespace(()) => Ok(impls::TrimTrailingWhitespace.into()),
7070                Initcap(()) => Ok(impls::Initcap.into()),
7071                RecordGet(field) => Ok(impls::RecordGet(field.into_rust()?).into()),
7072                ListLength(()) => Ok(impls::ListLength.into()),
7073                MapBuildFromRecordList(value_type) => Ok(impls::MapBuildFromRecordList {
7074                    value_type: value_type.into_rust()?,
7075                }
7076                .into()),
7077                MapLength(()) => Ok(impls::MapLength.into()),
7078                Upper(()) => Ok(impls::Upper.into()),
7079                Lower(()) => Ok(impls::Lower.into()),
7080                Cos(()) => Ok(impls::Cos.into()),
7081                Acos(()) => Ok(impls::Acos.into()),
7082                Cosh(()) => Ok(impls::Cosh.into()),
7083                Acosh(()) => Ok(impls::Acosh.into()),
7084                Sin(()) => Ok(impls::Sin.into()),
7085                Asin(()) => Ok(impls::Asin.into()),
7086                Sinh(()) => Ok(impls::Sinh.into()),
7087                Asinh(()) => Ok(impls::Asinh.into()),
7088                Tan(()) => Ok(impls::Tan.into()),
7089                Atan(()) => Ok(impls::Atan.into()),
7090                Tanh(()) => Ok(impls::Tanh.into()),
7091                Atanh(()) => Ok(impls::Atanh.into()),
7092                Cot(()) => Ok(impls::Cot.into()),
7093                Degrees(()) => Ok(impls::Degrees.into()),
7094                Radians(()) => Ok(impls::Radians.into()),
7095                Log10(()) => Ok(impls::Log10.into()),
7096                Log10Numeric(()) => Ok(impls::Log10Numeric.into()),
7097                Ln(()) => Ok(impls::Ln.into()),
7098                LnNumeric(()) => Ok(impls::LnNumeric.into()),
7099                Exp(()) => Ok(impls::Exp.into()),
7100                ExpNumeric(()) => Ok(impls::ExpNumeric.into()),
7101                Sleep(()) => Ok(impls::Sleep.into()),
7102                Panic(()) => Ok(impls::Panic.into()),
7103                AdjustNumericScale(max_scale) => {
7104                    Ok(impls::AdjustNumericScale(max_scale.into_rust()?).into())
7105                }
7106                PgColumnSize(()) => Ok(impls::PgColumnSize.into()),
7107                PgSizePretty(()) => Ok(impls::PgSizePretty.into()),
7108                MzRowSize(()) => Ok(impls::MzRowSize.into()),
7109                MzTypeName(()) => Ok(impls::MzTypeName.into()),
7110
7111                CastMzTimestampToString(()) => Ok(impls::CastMzTimestampToString.into()),
7112                CastMzTimestampToTimestamp(()) => Ok(impls::CastMzTimestampToTimestamp.into()),
7113                CastMzTimestampToTimestampTz(()) => Ok(impls::CastMzTimestampToTimestampTz.into()),
7114                CastStringToMzTimestamp(()) => Ok(impls::CastStringToMzTimestamp.into()),
7115                CastUint64ToMzTimestamp(()) => Ok(impls::CastUint64ToMzTimestamp.into()),
7116                CastUint32ToMzTimestamp(()) => Ok(impls::CastUint32ToMzTimestamp.into()),
7117                CastInt64ToMzTimestamp(()) => Ok(impls::CastInt64ToMzTimestamp.into()),
7118                CastInt32ToMzTimestamp(()) => Ok(impls::CastInt32ToMzTimestamp.into()),
7119                CastNumericToMzTimestamp(()) => Ok(impls::CastNumericToMzTimestamp.into()),
7120                CastTimestampToMzTimestamp(()) => Ok(impls::CastTimestampToMzTimestamp.into()),
7121                CastTimestampTzToMzTimestamp(()) => Ok(impls::CastTimestampTzToMzTimestamp.into()),
7122                CastDateToMzTimestamp(()) => Ok(impls::CastDateToMzTimestamp.into()),
7123                StepMzTimestamp(()) => Ok(impls::StepMzTimestamp.into()),
7124                RangeLower(()) => Ok(impls::RangeLower.into()),
7125                RangeUpper(()) => Ok(impls::RangeUpper.into()),
7126                RangeEmpty(()) => Ok(impls::RangeEmpty.into()),
7127                RangeLowerInc(_) => Ok(impls::RangeLowerInc.into()),
7128                RangeUpperInc(_) => Ok(impls::RangeUpperInc.into()),
7129                RangeLowerInf(_) => Ok(impls::RangeLowerInf.into()),
7130                RangeUpperInf(_) => Ok(impls::RangeUpperInf.into()),
7131                MzAclItemGrantor(_) => Ok(impls::MzAclItemGrantor.into()),
7132                MzAclItemGrantee(_) => Ok(impls::MzAclItemGrantee.into()),
7133                MzAclItemPrivileges(_) => Ok(impls::MzAclItemPrivileges.into()),
7134                MzFormatPrivileges(_) => Ok(impls::MzFormatPrivileges.into()),
7135                MzValidatePrivileges(_) => Ok(impls::MzValidatePrivileges.into()),
7136                MzValidateRolePrivilege(_) => Ok(impls::MzValidateRolePrivilege.into()),
7137                AclItemGrantor(_) => Ok(impls::AclItemGrantor.into()),
7138                AclItemGrantee(_) => Ok(impls::AclItemGrantee.into()),
7139                AclItemPrivileges(_) => Ok(impls::AclItemPrivileges.into()),
7140                QuoteIdent(_) => Ok(impls::QuoteIdent.into()),
7141                TryParseMonotonicIso8601Timestamp(_) => {
7142                    Ok(impls::TryParseMonotonicIso8601Timestamp.into())
7143                }
7144                Crc32Bytes(()) => Ok(impls::Crc32Bytes.into()),
7145                Crc32String(()) => Ok(impls::Crc32String.into()),
7146                KafkaMurmur2Bytes(()) => Ok(impls::KafkaMurmur2Bytes.into()),
7147                KafkaMurmur2String(()) => Ok(impls::KafkaMurmur2String.into()),
7148                SeahashBytes(()) => Ok(impls::SeahashBytes.into()),
7149                SeahashString(()) => Ok(impls::SeahashString.into()),
7150                Reverse(()) => Ok(impls::Reverse.into()),
7151            }
7152        } else {
7153            Err(TryFromProtoError::missing_field("ProtoUnaryFunc::kind"))
7154        }
7155    }
7156}
7157
7158impl IntoRustIfSome<UnaryFunc> for Option<Box<ProtoUnaryFunc>> {
7159    fn into_rust_if_some<S: ToString>(self, field: S) -> Result<UnaryFunc, TryFromProtoError> {
7160        let value = self.ok_or_else(|| TryFromProtoError::missing_field(field))?;
7161        (*value).into_rust()
7162    }
7163}
7164
7165fn coalesce<'a>(
7166    datums: &[Datum<'a>],
7167    temp_storage: &'a RowArena,
7168    exprs: &'a [MirScalarExpr],
7169) -> Result<Datum<'a>, EvalError> {
7170    for e in exprs {
7171        let d = e.eval(datums, temp_storage)?;
7172        if !d.is_null() {
7173            return Ok(d);
7174        }
7175    }
7176    Ok(Datum::Null)
7177}
7178
7179fn greatest<'a>(
7180    datums: &[Datum<'a>],
7181    temp_storage: &'a RowArena,
7182    exprs: &'a [MirScalarExpr],
7183) -> Result<Datum<'a>, EvalError> {
7184    let datums = fallible_iterator::convert(exprs.iter().map(|e| e.eval(datums, temp_storage)));
7185    Ok(datums
7186        .filter(|d| Ok(!d.is_null()))
7187        .max()?
7188        .unwrap_or(Datum::Null))
7189}
7190
7191fn least<'a>(
7192    datums: &[Datum<'a>],
7193    temp_storage: &'a RowArena,
7194    exprs: &'a [MirScalarExpr],
7195) -> Result<Datum<'a>, EvalError> {
7196    let datums = fallible_iterator::convert(exprs.iter().map(|e| e.eval(datums, temp_storage)));
7197    Ok(datums
7198        .filter(|d| Ok(!d.is_null()))
7199        .min()?
7200        .unwrap_or(Datum::Null))
7201}
7202
7203fn error_if_null<'a>(
7204    datums: &[Datum<'a>],
7205    temp_storage: &'a RowArena,
7206    exprs: &'a [MirScalarExpr],
7207) -> Result<Datum<'a>, EvalError> {
7208    let first = exprs[0].eval(datums, temp_storage)?;
7209    match first {
7210        Datum::Null => {
7211            let err_msg = match exprs[1].eval(datums, temp_storage)? {
7212                Datum::Null => {
7213                    return Err(EvalError::Internal(
7214                        "unexpected NULL in error side of error_if_null".into(),
7215                    ));
7216                }
7217                o => o.unwrap_str(),
7218            };
7219            Err(EvalError::IfNullError(err_msg.into()))
7220        }
7221        _ => Ok(first),
7222    }
7223}
7224
7225fn text_concat_binary<'a>(a: Datum<'a>, b: Datum<'a>, temp_storage: &'a RowArena) -> Datum<'a> {
7226    let mut buf = String::new();
7227    buf.push_str(a.unwrap_str());
7228    buf.push_str(b.unwrap_str());
7229    Datum::String(temp_storage.push_string(buf))
7230}
7231
7232fn text_concat_variadic<'a>(datums: &[Datum<'a>], temp_storage: &'a RowArena) -> Datum<'a> {
7233    let mut buf = String::new();
7234    for d in datums {
7235        if !d.is_null() {
7236            buf.push_str(d.unwrap_str());
7237        }
7238    }
7239    Datum::String(temp_storage.push_string(buf))
7240}
7241
7242fn text_concat_ws<'a>(datums: &[Datum<'a>], temp_storage: &'a RowArena) -> Datum<'a> {
7243    let ws = match datums[0] {
7244        Datum::Null => return Datum::Null,
7245        d => d.unwrap_str(),
7246    };
7247
7248    let buf = Itertools::join(
7249        &mut datums[1..].iter().filter_map(|d| match d {
7250            Datum::Null => None,
7251            d => Some(d.unwrap_str()),
7252        }),
7253        ws,
7254    );
7255
7256    Datum::String(temp_storage.push_string(buf))
7257}
7258
7259fn pad_leading<'a>(
7260    datums: &[Datum<'a>],
7261    temp_storage: &'a RowArena,
7262) -> Result<Datum<'a>, EvalError> {
7263    let string = datums[0].unwrap_str();
7264
7265    let len = match usize::try_from(datums[1].unwrap_int32()) {
7266        Ok(len) => len,
7267        Err(_) => {
7268            return Err(EvalError::InvalidParameterValue(
7269                "length must be nonnegative".into(),
7270            ));
7271        }
7272    };
7273    if len > MAX_STRING_BYTES {
7274        return Err(EvalError::LengthTooLarge);
7275    }
7276
7277    let pad_string = if datums.len() == 3 {
7278        datums[2].unwrap_str()
7279    } else {
7280        " "
7281    };
7282
7283    let (end_char, end_char_byte_offset) = string
7284        .chars()
7285        .take(len)
7286        .fold((0, 0), |acc, char| (acc.0 + 1, acc.1 + char.len_utf8()));
7287
7288    let mut buf = String::with_capacity(len);
7289    if len == end_char {
7290        buf.push_str(&string[0..end_char_byte_offset]);
7291    } else {
7292        buf.extend(pad_string.chars().cycle().take(len - end_char));
7293        buf.push_str(string);
7294    }
7295
7296    Ok(Datum::String(temp_storage.push_string(buf)))
7297}
7298
7299fn substr<'a>(datums: &[Datum<'a>]) -> Result<Datum<'a>, EvalError> {
7300    let s: &'a str = datums[0].unwrap_str();
7301
7302    let raw_start_idx = i64::from(datums[1].unwrap_int32()) - 1;
7303    let start_idx = match usize::try_from(cmp::max(raw_start_idx, 0)) {
7304        Ok(i) => i,
7305        Err(_) => {
7306            return Err(EvalError::InvalidParameterValue(
7307                format!(
7308                    "substring starting index ({}) exceeds min/max position",
7309                    raw_start_idx
7310                )
7311                .into(),
7312            ));
7313        }
7314    };
7315
7316    let mut char_indices = s.char_indices();
7317    let get_str_index = |(index, _char)| index;
7318
7319    let str_len = s.len();
7320    let start_char_idx = char_indices.nth(start_idx).map_or(str_len, get_str_index);
7321
7322    if datums.len() == 3 {
7323        let end_idx = match i64::from(datums[2].unwrap_int32()) {
7324            e if e < 0 => {
7325                return Err(EvalError::InvalidParameterValue(
7326                    "negative substring length not allowed".into(),
7327                ));
7328            }
7329            e if e == 0 || e + raw_start_idx < 1 => return Ok(Datum::String("")),
7330            e => {
7331                let e = cmp::min(raw_start_idx + e - 1, e - 1);
7332                match usize::try_from(e) {
7333                    Ok(i) => i,
7334                    Err(_) => {
7335                        return Err(EvalError::InvalidParameterValue(
7336                            format!("substring length ({}) exceeds max position", e).into(),
7337                        ));
7338                    }
7339                }
7340            }
7341        };
7342
7343        let end_char_idx = char_indices.nth(end_idx).map_or(str_len, get_str_index);
7344
7345        Ok(Datum::String(&s[start_char_idx..end_char_idx]))
7346    } else {
7347        Ok(Datum::String(&s[start_char_idx..]))
7348    }
7349}
7350
7351fn split_part<'a>(datums: &[Datum<'a>]) -> Result<Datum<'a>, EvalError> {
7352    let string = datums[0].unwrap_str();
7353    let delimiter = datums[1].unwrap_str();
7354
7355    // Provided index value begins at 1, not 0.
7356    let index = match usize::try_from(i64::from(datums[2].unwrap_int32()) - 1) {
7357        Ok(index) => index,
7358        Err(_) => {
7359            return Err(EvalError::InvalidParameterValue(
7360                "field position must be greater than zero".into(),
7361            ));
7362        }
7363    };
7364
7365    // If the provided delimiter is the empty string,
7366    // PostgreSQL does not break the string into individual
7367    // characters. Instead, it generates the following parts: [string].
7368    if delimiter.is_empty() {
7369        if index == 0 {
7370            return Ok(datums[0]);
7371        } else {
7372            return Ok(Datum::String(""));
7373        }
7374    }
7375
7376    // If provided index is greater than the number of split parts,
7377    // return an empty string.
7378    Ok(Datum::String(
7379        string.split(delimiter).nth(index).unwrap_or(""),
7380    ))
7381}
7382
7383fn like_escape<'a>(
7384    a: Datum<'a>,
7385    b: Datum<'a>,
7386    temp_storage: &'a RowArena,
7387) -> Result<Datum<'a>, EvalError> {
7388    let pattern = a.unwrap_str();
7389    let escape = like_pattern::EscapeBehavior::from_str(b.unwrap_str())?;
7390    let normalized = like_pattern::normalize_pattern(pattern, escape)?;
7391    Ok(Datum::String(temp_storage.push_string(normalized)))
7392}
7393
7394fn is_like_match_dynamic<'a>(
7395    a: Datum<'a>,
7396    b: Datum<'a>,
7397    case_insensitive: bool,
7398) -> Result<Datum<'a>, EvalError> {
7399    let haystack = a.unwrap_str();
7400    let needle = like_pattern::compile(b.unwrap_str(), case_insensitive)?;
7401    Ok(Datum::from(needle.is_match(haystack.as_ref())))
7402}
7403
7404fn is_regexp_match_dynamic<'a>(
7405    a: Datum<'a>,
7406    b: Datum<'a>,
7407    case_insensitive: bool,
7408) -> Result<Datum<'a>, EvalError> {
7409    let haystack = a.unwrap_str();
7410    let needle = build_regex(b.unwrap_str(), if case_insensitive { "i" } else { "" })?;
7411    Ok(Datum::from(needle.is_match(haystack)))
7412}
7413
7414fn regexp_match_dynamic<'a>(
7415    datums: &[Datum<'a>],
7416    temp_storage: &'a RowArena,
7417) -> Result<Datum<'a>, EvalError> {
7418    let haystack = datums[0];
7419    let needle = datums[1].unwrap_str();
7420    let flags = match datums.get(2) {
7421        Some(d) => d.unwrap_str(),
7422        None => "",
7423    };
7424    let needle = build_regex(needle, flags)?;
7425    regexp_match_static(haystack, temp_storage, &needle)
7426}
7427
7428fn regexp_match_static<'a>(
7429    haystack: Datum<'a>,
7430    temp_storage: &'a RowArena,
7431    needle: &regex::Regex,
7432) -> Result<Datum<'a>, EvalError> {
7433    let mut row = Row::default();
7434    let mut packer = row.packer();
7435    if needle.captures_len() > 1 {
7436        // The regex contains capture groups, so return an array containing the
7437        // matched text in each capture group, unless the entire match fails.
7438        // Individual capture groups may also be null if that group did not
7439        // participate in the match.
7440        match needle.captures(haystack.unwrap_str()) {
7441            None => packer.push(Datum::Null),
7442            Some(captures) => packer.try_push_array(
7443                &[ArrayDimension {
7444                    lower_bound: 1,
7445                    length: captures.len() - 1,
7446                }],
7447                // Skip the 0th capture group, which is the whole match.
7448                captures.iter().skip(1).map(|mtch| match mtch {
7449                    None => Datum::Null,
7450                    Some(mtch) => Datum::String(mtch.as_str()),
7451                }),
7452            )?,
7453        }
7454    } else {
7455        // The regex contains no capture groups, so return a one-element array
7456        // containing the match, or null if there is no match.
7457        match needle.find(haystack.unwrap_str()) {
7458            None => packer.push(Datum::Null),
7459            Some(mtch) => packer.try_push_array(
7460                &[ArrayDimension {
7461                    lower_bound: 1,
7462                    length: 1,
7463                }],
7464                iter::once(Datum::String(mtch.as_str())),
7465            )?,
7466        };
7467    };
7468    Ok(temp_storage.push_unary_row(row))
7469}
7470
7471fn regexp_replace_dynamic<'a>(
7472    datums: &[Datum<'a>],
7473    temp_storage: &'a RowArena,
7474) -> Result<Datum<'a>, EvalError> {
7475    let source = datums[0];
7476    let pattern = datums[1];
7477    let replacement = datums[2];
7478    let flags = match datums.get(3) {
7479        Some(d) => d.unwrap_str(),
7480        None => "",
7481    };
7482    let (limit, flags) = regexp_replace_parse_flags(flags);
7483    let regexp = build_regex(pattern.unwrap_str(), &flags)?;
7484    regexp_replace_static(source, replacement, &regexp, limit, temp_storage)
7485}
7486
7487/// Sets `limit` based on the presence of 'g' in `flags` for use in `Regex::replacen`,
7488/// and removes 'g' from `flags` if present.
7489pub(crate) fn regexp_replace_parse_flags(flags: &str) -> (usize, Cow<str>) {
7490    // 'g' means to replace all instead of the first. Use a Cow to avoid allocating in the fast
7491    // path. We could switch build_regex to take an iter which would also achieve that.
7492    let (limit, flags) = if flags.contains('g') {
7493        let flags = flags.replace('g', "");
7494        (0, Cow::Owned(flags))
7495    } else {
7496        (1, Cow::Borrowed(flags))
7497    };
7498    (limit, flags)
7499}
7500
7501fn regexp_replace_static<'a>(
7502    source: Datum<'a>,
7503    replacement: Datum<'a>,
7504    regexp: &regex::Regex,
7505    limit: usize,
7506    temp_storage: &'a RowArena,
7507) -> Result<Datum<'a>, EvalError> {
7508    let replaced = match regexp.replacen(source.unwrap_str(), limit, replacement.unwrap_str()) {
7509        Cow::Borrowed(s) => s,
7510        Cow::Owned(s) => temp_storage.push_string(s),
7511    };
7512    Ok(Datum::String(replaced))
7513}
7514
7515pub fn build_regex(needle: &str, flags: &str) -> Result<Regex, EvalError> {
7516    let mut case_insensitive = false;
7517    // Note: Postgres accepts it when both flags are present, taking the last one. We do the same.
7518    for f in flags.chars() {
7519        match f {
7520            'i' => {
7521                case_insensitive = true;
7522            }
7523            'c' => {
7524                case_insensitive = false;
7525            }
7526            _ => return Err(EvalError::InvalidRegexFlag(f)),
7527        }
7528    }
7529    Ok(Regex::new(needle, case_insensitive)?)
7530}
7531
7532pub fn hmac_string<'a>(
7533    datums: &[Datum<'a>],
7534    temp_storage: &'a RowArena,
7535) -> Result<Datum<'a>, EvalError> {
7536    let to_digest = datums[0].unwrap_str().as_bytes();
7537    let key = datums[1].unwrap_str().as_bytes();
7538    let typ = datums[2].unwrap_str();
7539    hmac_inner(to_digest, key, typ, temp_storage)
7540}
7541
7542pub fn hmac_bytes<'a>(
7543    datums: &[Datum<'a>],
7544    temp_storage: &'a RowArena,
7545) -> Result<Datum<'a>, EvalError> {
7546    let to_digest = datums[0].unwrap_bytes();
7547    let key = datums[1].unwrap_bytes();
7548    let typ = datums[2].unwrap_str();
7549    hmac_inner(to_digest, key, typ, temp_storage)
7550}
7551
7552pub fn hmac_inner<'a>(
7553    to_digest: &[u8],
7554    key: &[u8],
7555    typ: &str,
7556    temp_storage: &'a RowArena,
7557) -> Result<Datum<'a>, EvalError> {
7558    let bytes = match typ {
7559        "md5" => {
7560            let mut mac = Hmac::<Md5>::new_from_slice(key).expect("HMAC accepts any key size");
7561            mac.update(to_digest);
7562            mac.finalize().into_bytes().to_vec()
7563        }
7564        "sha1" => {
7565            let mut mac = Hmac::<Sha1>::new_from_slice(key).expect("HMAC accepts any key size");
7566            mac.update(to_digest);
7567            mac.finalize().into_bytes().to_vec()
7568        }
7569        "sha224" => {
7570            let mut mac = Hmac::<Sha224>::new_from_slice(key).expect("HMAC accepts any key size");
7571            mac.update(to_digest);
7572            mac.finalize().into_bytes().to_vec()
7573        }
7574        "sha256" => {
7575            let mut mac = Hmac::<Sha256>::new_from_slice(key).expect("HMAC accepts any key size");
7576            mac.update(to_digest);
7577            mac.finalize().into_bytes().to_vec()
7578        }
7579        "sha384" => {
7580            let mut mac = Hmac::<Sha384>::new_from_slice(key).expect("HMAC accepts any key size");
7581            mac.update(to_digest);
7582            mac.finalize().into_bytes().to_vec()
7583        }
7584        "sha512" => {
7585            let mut mac = Hmac::<Sha512>::new_from_slice(key).expect("HMAC accepts any key size");
7586            mac.update(to_digest);
7587            mac.finalize().into_bytes().to_vec()
7588        }
7589        other => return Err(EvalError::InvalidHashAlgorithm(other.into())),
7590    };
7591    Ok(Datum::Bytes(temp_storage.push_bytes(bytes)))
7592}
7593
7594fn repeat_string<'a>(
7595    string: Datum<'a>,
7596    count: Datum<'a>,
7597    temp_storage: &'a RowArena,
7598) -> Result<Datum<'a>, EvalError> {
7599    let len = usize::try_from(count.unwrap_int32()).unwrap_or(0);
7600    let string = string.unwrap_str();
7601    if (len * string.len()) > MAX_STRING_BYTES {
7602        return Err(EvalError::LengthTooLarge);
7603    }
7604    Ok(Datum::String(temp_storage.push_string(string.repeat(len))))
7605}
7606
7607fn replace<'a>(datums: &[Datum<'a>], temp_storage: &'a RowArena) -> Datum<'a> {
7608    Datum::String(
7609        temp_storage.push_string(
7610            datums[0]
7611                .unwrap_str()
7612                .replace(datums[1].unwrap_str(), datums[2].unwrap_str()),
7613        ),
7614    )
7615}
7616
7617fn translate<'a>(datums: &[Datum<'a>], temp_storage: &'a RowArena) -> Datum<'a> {
7618    let string = datums[0].unwrap_str();
7619    let from = datums[1].unwrap_str().chars().collect::<Vec<_>>();
7620    let to = datums[2].unwrap_str().chars().collect::<Vec<_>>();
7621
7622    Datum::String(
7623        temp_storage.push_string(
7624            string
7625                .chars()
7626                .filter_map(|c| match from.iter().position(|f| f == &c) {
7627                    Some(idx) => to.get(idx).copied(),
7628                    None => Some(c),
7629                })
7630                .collect(),
7631        ),
7632    )
7633}
7634
7635fn jsonb_build_array<'a>(datums: &[Datum<'a>], temp_storage: &'a RowArena) -> Datum<'a> {
7636    temp_storage.make_datum(|packer| {
7637        packer.push_list(datums.into_iter().map(|d| match d {
7638            Datum::Null => Datum::JsonNull,
7639            d => *d,
7640        }))
7641    })
7642}
7643
7644fn jsonb_build_object<'a>(
7645    datums: &[Datum<'a>],
7646    temp_storage: &'a RowArena,
7647) -> Result<Datum<'a>, EvalError> {
7648    let mut kvs = datums.chunks(2).collect::<Vec<_>>();
7649    kvs.sort_by(|kv1, kv2| kv1[0].cmp(&kv2[0]));
7650    kvs.dedup_by(|kv1, kv2| kv1[0] == kv2[0]);
7651    temp_storage.try_make_datum(|packer| {
7652        packer.push_dict_with(|packer| {
7653            for kv in kvs {
7654                let k = kv[0];
7655                if k.is_null() {
7656                    return Err(EvalError::KeyCannotBeNull);
7657                };
7658                let v = match kv[1] {
7659                    Datum::Null => Datum::JsonNull,
7660                    d => d,
7661                };
7662                packer.push(k);
7663                packer.push(v);
7664            }
7665            Ok(())
7666        })
7667    })
7668}
7669
7670fn map_build<'a>(datums: &[Datum<'a>], temp_storage: &'a RowArena) -> Datum<'a> {
7671    // Collect into a `BTreeMap` to provide the same semantics as it.
7672    let map: std::collections::BTreeMap<&str, _> = datums
7673        .into_iter()
7674        .tuples()
7675        .filter_map(|(k, v)| {
7676            if k.is_null() {
7677                None
7678            } else {
7679                Some((k.unwrap_str(), v))
7680            }
7681        })
7682        .collect();
7683
7684    temp_storage.make_datum(|packer| packer.push_dict(map))
7685}
7686
7687/// Constructs a new multidimensional array out of an arbitrary number of
7688/// lower-dimensional arrays.
7689///
7690/// For example, if given three 1D arrays of length 2, this function will
7691/// construct a 2D array with dimensions 3x2.
7692///
7693/// The input datums in `datums` must all be arrays of the same dimensions.
7694/// (The arrays must also be of the same element type, but that is checked by
7695/// the SQL type system, rather than checked here at runtime.)
7696///
7697/// If all input arrays are zero-dimensional arrays, then the output is a zero-
7698/// dimensional array. Otherwise the lower bound of the additional dimension is
7699/// one and the length of the new dimension is equal to `datums.len()`.
7700fn array_create_multidim<'a>(
7701    datums: &[Datum<'a>],
7702    temp_storage: &'a RowArena,
7703) -> Result<Datum<'a>, EvalError> {
7704    // Per PostgreSQL, if all input arrays are zero dimensional, so is the
7705    // output.
7706    if datums.iter().all(|d| d.unwrap_array().dims().is_empty()) {
7707        let dims = &[];
7708        let datums = &[];
7709        let datum = temp_storage.try_make_datum(|packer| packer.try_push_array(dims, datums))?;
7710        return Ok(datum);
7711    }
7712
7713    let mut dims = vec![ArrayDimension {
7714        lower_bound: 1,
7715        length: datums.len(),
7716    }];
7717    if let Some(d) = datums.first() {
7718        dims.extend(d.unwrap_array().dims());
7719    };
7720    let elements = datums
7721        .iter()
7722        .flat_map(|d| d.unwrap_array().elements().iter());
7723    let datum =
7724        temp_storage.try_make_datum(move |packer| packer.try_push_array(&dims, elements))?;
7725    Ok(datum)
7726}
7727
7728/// Constructs a new zero or one dimensional array out of an arbitrary number of
7729/// scalars.
7730///
7731/// If `datums` is empty, constructs a zero-dimensional array. Otherwise,
7732/// constructs a one dimensional array whose lower bound is one and whose length
7733/// is equal to `datums.len()`.
7734fn array_create_scalar<'a>(
7735    datums: &[Datum<'a>],
7736    temp_storage: &'a RowArena,
7737) -> Result<Datum<'a>, EvalError> {
7738    let mut dims = &[ArrayDimension {
7739        lower_bound: 1,
7740        length: datums.len(),
7741    }][..];
7742    if datums.is_empty() {
7743        // Per PostgreSQL, empty arrays are represented with zero dimensions,
7744        // not one dimension of zero length. We write this condition a little
7745        // strangely to satisfy the borrow checker while avoiding an allocation.
7746        dims = &[];
7747    }
7748    let datum = temp_storage.try_make_datum(|packer| packer.try_push_array(dims, datums))?;
7749    Ok(datum)
7750}
7751
7752fn array_to_string<'a>(
7753    datums: &[Datum<'a>],
7754    elem_type: &ScalarType,
7755    temp_storage: &'a RowArena,
7756) -> Result<Datum<'a>, EvalError> {
7757    if datums[0].is_null() || datums[1].is_null() {
7758        return Ok(Datum::Null);
7759    }
7760    let array = datums[0].unwrap_array();
7761    let delimiter = datums[1].unwrap_str();
7762    let null_str = match datums.get(2) {
7763        None | Some(Datum::Null) => None,
7764        Some(d) => Some(d.unwrap_str()),
7765    };
7766
7767    let mut out = String::new();
7768    for elem in array.elements().iter() {
7769        if elem.is_null() {
7770            if let Some(null_str) = null_str {
7771                out.push_str(null_str);
7772                out.push_str(delimiter);
7773            }
7774        } else {
7775            stringify_datum(&mut out, elem, elem_type)?;
7776            out.push_str(delimiter);
7777        }
7778    }
7779    if out.len() > 0 {
7780        // Lop off last delimiter only if string is not empty
7781        out.truncate(out.len() - delimiter.len());
7782    }
7783    Ok(Datum::String(temp_storage.push_string(out)))
7784}
7785
7786fn list_create<'a>(datums: &[Datum<'a>], temp_storage: &'a RowArena) -> Datum<'a> {
7787    temp_storage.make_datum(|packer| packer.push_list(datums))
7788}
7789
7790fn stringify_datum<'a, B>(
7791    buf: &mut B,
7792    d: Datum<'a>,
7793    ty: &ScalarType,
7794) -> Result<strconv::Nestable, EvalError>
7795where
7796    B: FormatBuffer,
7797{
7798    use ScalarType::*;
7799    match &ty {
7800        AclItem => Ok(strconv::format_acl_item(buf, d.unwrap_acl_item())),
7801        Bool => Ok(strconv::format_bool(buf, d.unwrap_bool())),
7802        Int16 => Ok(strconv::format_int16(buf, d.unwrap_int16())),
7803        Int32 => Ok(strconv::format_int32(buf, d.unwrap_int32())),
7804        Int64 => Ok(strconv::format_int64(buf, d.unwrap_int64())),
7805        UInt16 => Ok(strconv::format_uint16(buf, d.unwrap_uint16())),
7806        UInt32 | Oid | RegClass | RegProc | RegType => {
7807            Ok(strconv::format_uint32(buf, d.unwrap_uint32()))
7808        }
7809        UInt64 => Ok(strconv::format_uint64(buf, d.unwrap_uint64())),
7810        Float32 => Ok(strconv::format_float32(buf, d.unwrap_float32())),
7811        Float64 => Ok(strconv::format_float64(buf, d.unwrap_float64())),
7812        Numeric { .. } => Ok(strconv::format_numeric(buf, &d.unwrap_numeric())),
7813        Date => Ok(strconv::format_date(buf, d.unwrap_date())),
7814        Time => Ok(strconv::format_time(buf, d.unwrap_time())),
7815        Timestamp { .. } => Ok(strconv::format_timestamp(buf, &d.unwrap_timestamp())),
7816        TimestampTz { .. } => Ok(strconv::format_timestamptz(buf, &d.unwrap_timestamptz())),
7817        Interval => Ok(strconv::format_interval(buf, d.unwrap_interval())),
7818        Bytes => Ok(strconv::format_bytes(buf, d.unwrap_bytes())),
7819        String | VarChar { .. } | PgLegacyName => Ok(strconv::format_string(buf, d.unwrap_str())),
7820        Char { length } => Ok(strconv::format_string(
7821            buf,
7822            &mz_repr::adt::char::format_str_pad(d.unwrap_str(), *length),
7823        )),
7824        PgLegacyChar => {
7825            format_pg_legacy_char(buf, d.unwrap_uint8())?;
7826            Ok(strconv::Nestable::MayNeedEscaping)
7827        }
7828        Jsonb => Ok(strconv::format_jsonb(buf, JsonbRef::from_datum(d))),
7829        Uuid => Ok(strconv::format_uuid(buf, d.unwrap_uuid())),
7830        Record { fields, .. } => {
7831            let mut fields = fields.iter();
7832            strconv::format_record(buf, &d.unwrap_list(), |buf, d| {
7833                let (_name, ty) = fields.next().unwrap();
7834                if d.is_null() {
7835                    Ok(buf.write_null())
7836                } else {
7837                    stringify_datum(buf.nonnull_buffer(), d, &ty.scalar_type)
7838                }
7839            })
7840        }
7841        Array(elem_type) => strconv::format_array(
7842            buf,
7843            &d.unwrap_array().dims().into_iter().collect::<Vec<_>>(),
7844            &d.unwrap_array().elements(),
7845            |buf, d| {
7846                if d.is_null() {
7847                    Ok(buf.write_null())
7848                } else {
7849                    stringify_datum(buf.nonnull_buffer(), d, elem_type)
7850                }
7851            },
7852        ),
7853        List { element_type, .. } => strconv::format_list(buf, &d.unwrap_list(), |buf, d| {
7854            if d.is_null() {
7855                Ok(buf.write_null())
7856            } else {
7857                stringify_datum(buf.nonnull_buffer(), d, element_type)
7858            }
7859        }),
7860        Map { value_type, .. } => strconv::format_map(buf, &d.unwrap_map(), |buf, d| {
7861            if d.is_null() {
7862                Ok(buf.write_null())
7863            } else {
7864                stringify_datum(buf.nonnull_buffer(), d, value_type)
7865            }
7866        }),
7867        Int2Vector => strconv::format_legacy_vector(buf, &d.unwrap_array().elements(), |buf, d| {
7868            stringify_datum(buf.nonnull_buffer(), d, &ScalarType::Int16)
7869        }),
7870        MzTimestamp { .. } => Ok(strconv::format_mz_timestamp(buf, d.unwrap_mz_timestamp())),
7871        Range { element_type } => strconv::format_range(buf, &d.unwrap_range(), |buf, d| match d {
7872            Some(d) => stringify_datum(buf.nonnull_buffer(), *d, element_type),
7873            None => Ok::<_, EvalError>(buf.write_null()),
7874        }),
7875        MzAclItem => Ok(strconv::format_mz_acl_item(buf, d.unwrap_mz_acl_item())),
7876    }
7877}
7878
7879fn array_index<'a>(datums: &[Datum<'a>], offset: i64) -> Datum<'a> {
7880    mz_ore::soft_assert_no_log!(offset == 0 || offset == 1, "offset must be either 0 or 1");
7881
7882    let array = datums[0].unwrap_array();
7883    let dims = array.dims();
7884    if dims.len() != datums.len() - 1 {
7885        // You missed the datums "layer"
7886        return Datum::Null;
7887    }
7888
7889    let mut final_idx = 0;
7890
7891    for (d, idx) in dims.into_iter().zip_eq(datums[1..].iter()) {
7892        // Lower bound is written in terms of 1-based indexing, which offset accounts for.
7893        let idx = isize::cast_from(idx.unwrap_int64() + offset);
7894
7895        let (lower, upper) = d.dimension_bounds();
7896
7897        // This index missed all of the data at this layer. The dimension bounds are inclusive,
7898        // while range checks are exclusive, so adjust.
7899        if !(lower..upper + 1).contains(&idx) {
7900            return Datum::Null;
7901        }
7902
7903        // We discover how many indices our last index represents physically.
7904        final_idx *= d.length;
7905
7906        // Because both index and lower bound are handled in 1-based indexing, taking their
7907        // difference moves us back into 0-based indexing. Similarly, if the lower bound is
7908        // negative, subtracting a negative value >= to itself ensures its non-negativity.
7909        final_idx += usize::try_from(idx - d.lower_bound)
7910            .expect("previous bounds check ensures phsical index is at least 0");
7911    }
7912
7913    array
7914        .elements()
7915        .iter()
7916        .nth(final_idx)
7917        .unwrap_or(Datum::Null)
7918}
7919
7920// TODO(benesch): remove potentially dangerous usage of `as`.
7921#[allow(clippy::as_conversions)]
7922fn list_index<'a>(datums: &[Datum<'a>]) -> Datum<'a> {
7923    let mut buf = datums[0];
7924
7925    for i in datums[1..].iter() {
7926        if buf.is_null() {
7927            break;
7928        }
7929
7930        let i = i.unwrap_int64();
7931        if i < 1 {
7932            return Datum::Null;
7933        }
7934
7935        buf = buf
7936            .unwrap_list()
7937            .iter()
7938            .nth(i as usize - 1)
7939            .unwrap_or(Datum::Null);
7940    }
7941    buf
7942}
7943
7944// TODO(benesch): remove potentially dangerous usage of `as`.
7945#[allow(clippy::as_conversions)]
7946fn list_slice_linear<'a>(datums: &[Datum<'a>], temp_storage: &'a RowArena) -> Datum<'a> {
7947    assert_eq!(
7948        datums.len() % 2,
7949        1,
7950        "expr::scalar::func::list_slice expects an odd number of arguments; 1 for list + 2 \
7951        for each start-end pair"
7952    );
7953    assert!(
7954        datums.len() > 2,
7955        "expr::scalar::func::list_slice expects at least 3 arguments; 1 for list + at least \
7956        one start-end pair"
7957    );
7958
7959    let mut start_idx = 0;
7960    let mut total_length = usize::MAX;
7961
7962    for (start, end) in datums[1..].iter().tuples::<(_, _)>() {
7963        let start = std::cmp::max(start.unwrap_int64(), 1);
7964        let end = end.unwrap_int64();
7965
7966        // Result should be empty list.
7967        if start > end {
7968            start_idx = 0;
7969            total_length = 0;
7970            break;
7971        }
7972
7973        let start_inner = start as usize - 1;
7974        // Start index only moves to geq positions.
7975        start_idx += start_inner;
7976
7977        // Length index only moves to leq positions
7978        let length_inner = (end - start) as usize + 1;
7979        total_length = std::cmp::min(length_inner, total_length - start_inner);
7980    }
7981
7982    let iter = datums[0]
7983        .unwrap_list()
7984        .iter()
7985        .skip(start_idx)
7986        .take(total_length);
7987
7988    temp_storage.make_datum(|row| {
7989        row.push_list_with(|row| {
7990            // if iter is empty, will get the appropriate empty list.
7991            for d in iter {
7992                row.push(d);
7993            }
7994        });
7995    })
7996}
7997
7998fn create_range<'a>(
7999    datums: &[Datum<'a>],
8000    temp_storage: &'a RowArena,
8001) -> Result<Datum<'a>, EvalError> {
8002    let flags = match datums[2] {
8003        Datum::Null => {
8004            return Err(EvalError::InvalidRange(
8005                range::InvalidRangeError::NullRangeBoundFlags,
8006            ));
8007        }
8008        o => o.unwrap_str(),
8009    };
8010
8011    let (lower_inclusive, upper_inclusive) = range::parse_range_bound_flags(flags)?;
8012
8013    let mut range = Range::new(Some((
8014        RangeBound::new(datums[0], lower_inclusive),
8015        RangeBound::new(datums[1], upper_inclusive),
8016    )));
8017
8018    range.canonicalize()?;
8019
8020    Ok(temp_storage.make_datum(|row| {
8021        row.push_range(range).expect("errors already handled");
8022    }))
8023}
8024
8025fn array_position<'a>(datums: &[Datum<'a>]) -> Result<Datum<'a>, EvalError> {
8026    let array = match datums[0] {
8027        Datum::Null => return Ok(Datum::Null),
8028        o => o.unwrap_array(),
8029    };
8030
8031    if array.dims().len() > 1 {
8032        return Err(EvalError::MultiDimensionalArraySearch);
8033    }
8034
8035    let search = datums[1];
8036    if search == Datum::Null {
8037        return Ok(Datum::Null);
8038    }
8039
8040    let skip: usize = match datums.get(2) {
8041        Some(Datum::Null) => return Err(EvalError::MustNotBeNull("initial position".into())),
8042        None => 0,
8043        Some(o) => usize::try_from(o.unwrap_int32())
8044            .unwrap_or(0)
8045            .saturating_sub(1),
8046    };
8047
8048    let r = array.elements().iter().skip(skip).position(|d| d == search);
8049
8050    Ok(Datum::from(r.map(|p| {
8051        // Adjust count for the amount we skipped, plus 1 for adjustng to PG indexing scheme.
8052        i32::try_from(p + skip + 1).expect("fewer than i32::MAX elements in array")
8053    })))
8054}
8055
8056// TODO(benesch): remove potentially dangerous usage of `as`.
8057#[allow(clippy::as_conversions)]
8058fn make_timestamp<'a>(datums: &[Datum<'a>]) -> Result<Datum<'a>, EvalError> {
8059    let year: i32 = match datums[0].unwrap_int64().try_into() {
8060        Ok(year) => year,
8061        Err(_) => return Ok(Datum::Null),
8062    };
8063    let month: u32 = match datums[1].unwrap_int64().try_into() {
8064        Ok(month) => month,
8065        Err(_) => return Ok(Datum::Null),
8066    };
8067    let day: u32 = match datums[2].unwrap_int64().try_into() {
8068        Ok(day) => day,
8069        Err(_) => return Ok(Datum::Null),
8070    };
8071    let hour: u32 = match datums[3].unwrap_int64().try_into() {
8072        Ok(day) => day,
8073        Err(_) => return Ok(Datum::Null),
8074    };
8075    let minute: u32 = match datums[4].unwrap_int64().try_into() {
8076        Ok(day) => day,
8077        Err(_) => return Ok(Datum::Null),
8078    };
8079    let second_float = datums[5].unwrap_float64();
8080    let second = second_float as u32;
8081    let micros = ((second_float - second as f64) * 1_000_000.0) as u32;
8082    let date = match NaiveDate::from_ymd_opt(year, month, day) {
8083        Some(date) => date,
8084        None => return Ok(Datum::Null),
8085    };
8086    let timestamp = match date.and_hms_micro_opt(hour, minute, second, micros) {
8087        Some(timestamp) => timestamp,
8088        None => return Ok(Datum::Null),
8089    };
8090    Ok(timestamp.try_into()?)
8091}
8092
8093fn position<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
8094    let substring: &'a str = a.unwrap_str();
8095    let string = b.unwrap_str();
8096    let char_index = string.find(substring);
8097
8098    if let Some(char_index) = char_index {
8099        // find the index in char space
8100        let string_prefix = &string[0..char_index];
8101
8102        let num_prefix_chars = string_prefix.chars().count();
8103        let num_prefix_chars = i32::try_from(num_prefix_chars)
8104            .map_err(|_| EvalError::Int32OutOfRange(num_prefix_chars.to_string().into()))?;
8105
8106        Ok(Datum::Int32(num_prefix_chars + 1))
8107    } else {
8108        Ok(Datum::Int32(0))
8109    }
8110}
8111
8112fn left<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
8113    let string: &'a str = a.unwrap_str();
8114    let n = i64::from(b.unwrap_int32());
8115
8116    let mut byte_indices = string.char_indices().map(|(i, _)| i);
8117
8118    let end_in_bytes = match n.cmp(&0) {
8119        Ordering::Equal => 0,
8120        Ordering::Greater => {
8121            let n = usize::try_from(n).map_err(|_| {
8122                EvalError::InvalidParameterValue(format!("invalid parameter n: {:?}", n).into())
8123            })?;
8124            // nth from the back
8125            byte_indices.nth(n).unwrap_or(string.len())
8126        }
8127        Ordering::Less => {
8128            let n = usize::try_from(n.abs() - 1).map_err(|_| {
8129                EvalError::InvalidParameterValue(format!("invalid parameter n: {:?}", n).into())
8130            })?;
8131            byte_indices.rev().nth(n).unwrap_or(0)
8132        }
8133    };
8134
8135    Ok(Datum::String(&string[..end_in_bytes]))
8136}
8137
8138fn right<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
8139    let string: &'a str = a.unwrap_str();
8140    let n = b.unwrap_int32();
8141
8142    let mut byte_indices = string.char_indices().map(|(i, _)| i);
8143
8144    let start_in_bytes = if n == 0 {
8145        string.len()
8146    } else if n > 0 {
8147        let n = usize::try_from(n - 1).map_err(|_| {
8148            EvalError::InvalidParameterValue(format!("invalid parameter n: {:?}", n).into())
8149        })?;
8150        // nth from the back
8151        byte_indices.rev().nth(n).unwrap_or(0)
8152    } else if n == i32::MIN {
8153        // this seems strange but Postgres behaves like this
8154        0
8155    } else {
8156        let n = n.abs();
8157        let n = usize::try_from(n).map_err(|_| {
8158            EvalError::InvalidParameterValue(format!("invalid parameter n: {:?}", n).into())
8159        })?;
8160        byte_indices.nth(n).unwrap_or(string.len())
8161    };
8162
8163    Ok(Datum::String(&string[start_in_bytes..]))
8164}
8165
8166fn trim<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
8167    let trim_chars = b.unwrap_str();
8168
8169    Datum::from(a.unwrap_str().trim_matches(|c| trim_chars.contains(c)))
8170}
8171
8172fn trim_leading<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
8173    let trim_chars = b.unwrap_str();
8174
8175    Datum::from(
8176        a.unwrap_str()
8177            .trim_start_matches(|c| trim_chars.contains(c)),
8178    )
8179}
8180
8181fn trim_trailing<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
8182    let trim_chars = b.unwrap_str();
8183
8184    Datum::from(a.unwrap_str().trim_end_matches(|c| trim_chars.contains(c)))
8185}
8186
8187#[sqlfunc(
8188    is_monotone = "(false, false)",
8189    output_type = "Option<i32>",
8190    is_infix_op = true,
8191    sqlname = "array_length",
8192    propagates_nulls = true,
8193    introduces_nulls = true
8194)]
8195fn array_length<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
8196    let i = match usize::try_from(b.unwrap_int64()) {
8197        Ok(0) | Err(_) => return Ok(Datum::Null),
8198        Ok(n) => n - 1,
8199    };
8200    Ok(match a.unwrap_array().dims().into_iter().nth(i) {
8201        None => Datum::Null,
8202        Some(dim) => Datum::Int32(
8203            dim.length
8204                .try_into()
8205                .map_err(|_| EvalError::Int32OutOfRange(dim.length.to_string().into()))?,
8206        ),
8207    })
8208}
8209
8210// TODO(benesch): remove potentially dangerous usage of `as`.
8211#[allow(clippy::as_conversions)]
8212fn array_lower<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
8213    let i = b.unwrap_int64();
8214    if i < 1 {
8215        return Datum::Null;
8216    }
8217    match a.unwrap_array().dims().into_iter().nth(i as usize - 1) {
8218        Some(_) => Datum::Int32(1),
8219        None => Datum::Null,
8220    }
8221}
8222
8223fn array_remove<'a>(
8224    a: Datum<'a>,
8225    b: Datum<'a>,
8226    temp_storage: &'a RowArena,
8227) -> Result<Datum<'a>, EvalError> {
8228    if a.is_null() {
8229        return Ok(a);
8230    }
8231
8232    let arr = a.unwrap_array();
8233
8234    // Zero-dimensional arrays are empty by definition
8235    if arr.dims().len() == 0 {
8236        return Ok(a);
8237    }
8238
8239    // array_remove only supports one-dimensional arrays
8240    if arr.dims().len() > 1 {
8241        return Err(EvalError::MultidimensionalArrayRemovalNotSupported);
8242    }
8243
8244    let elems: Vec<_> = arr.elements().iter().filter(|v| v != &b).collect();
8245    let mut dims = arr.dims().into_iter().collect::<Vec<_>>();
8246    // This access is safe because `dims` is guaranteed to be non-empty
8247    dims[0] = ArrayDimension {
8248        lower_bound: 1,
8249        length: elems.len(),
8250    };
8251
8252    Ok(temp_storage.try_make_datum(|packer| packer.try_push_array(&dims, elems))?)
8253}
8254
8255// TODO(benesch): remove potentially dangerous usage of `as`.
8256#[allow(clippy::as_conversions)]
8257fn array_upper<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
8258    let i = b.unwrap_int64();
8259    if i < 1 {
8260        return Ok(Datum::Null);
8261    }
8262    Ok(
8263        match a.unwrap_array().dims().into_iter().nth(i as usize - 1) {
8264            Some(dim) => Datum::Int32(
8265                dim.length
8266                    .try_into()
8267                    .map_err(|_| EvalError::Int32OutOfRange(dim.length.to_string().into()))?,
8268            ),
8269            None => Datum::Null,
8270        },
8271    )
8272}
8273
8274// TODO(benesch): remove potentially dangerous usage of `as`.
8275#[allow(clippy::as_conversions)]
8276fn list_length_max<'a>(
8277    a: Datum<'a>,
8278    b: Datum<'a>,
8279    max_layer: usize,
8280) -> Result<Datum<'a>, EvalError> {
8281    fn max_len_on_layer<'a>(d: Datum<'a>, on_layer: i64) -> Option<usize> {
8282        match d {
8283            Datum::List(i) => {
8284                let mut i = i.iter();
8285                if on_layer > 1 {
8286                    let mut max_len = None;
8287                    while let Some(Datum::List(i)) = i.next() {
8288                        max_len =
8289                            std::cmp::max(max_len_on_layer(Datum::List(i), on_layer - 1), max_len);
8290                    }
8291                    max_len
8292                } else {
8293                    Some(i.count())
8294                }
8295            }
8296            Datum::Null => None,
8297            _ => unreachable!(),
8298        }
8299    }
8300
8301    let b = b.unwrap_int64();
8302
8303    if b as usize > max_layer || b < 1 {
8304        Err(EvalError::InvalidLayer { max_layer, val: b })
8305    } else {
8306        match max_len_on_layer(a, b) {
8307            Some(l) => match l.try_into() {
8308                Ok(c) => Ok(Datum::Int32(c)),
8309                Err(_) => Err(EvalError::Int32OutOfRange(l.to_string().into())),
8310            },
8311            None => Ok(Datum::Null),
8312        }
8313    }
8314}
8315
8316fn array_contains<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
8317    let array = Datum::unwrap_array(&b);
8318    Datum::from(array.elements().iter().any(|e| e == a))
8319}
8320
8321fn array_contains_array<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {
8322    let a = a.unwrap_array().elements();
8323    let b = b.unwrap_array().elements();
8324
8325    // NULL is never equal to NULL. If NULL is an element of b, b cannot be contained in a, even if a contains NULL.
8326    if b.iter().contains(&Datum::Null) {
8327        Datum::False
8328    } else {
8329        b.iter()
8330            .all(|item_b| a.iter().any(|item_a| item_a == item_b))
8331            .into()
8332    }
8333}
8334
8335fn array_array_concat<'a>(
8336    a: Datum<'a>,
8337    b: Datum<'a>,
8338    temp_storage: &'a RowArena,
8339) -> Result<Datum<'a>, EvalError> {
8340    if a.is_null() {
8341        return Ok(b);
8342    } else if b.is_null() {
8343        return Ok(a);
8344    }
8345
8346    let a_array = a.unwrap_array();
8347    let b_array = b.unwrap_array();
8348
8349    let a_dims: Vec<ArrayDimension> = a_array.dims().into_iter().collect();
8350    let b_dims: Vec<ArrayDimension> = b_array.dims().into_iter().collect();
8351
8352    let a_ndims = a_dims.len();
8353    let b_ndims = b_dims.len();
8354
8355    // Per PostgreSQL, if either of the input arrays is zero dimensional,
8356    // the output is the other array, no matter their dimensions.
8357    if a_ndims == 0 {
8358        return Ok(b);
8359    } else if b_ndims == 0 {
8360        return Ok(a);
8361    }
8362
8363    // Postgres supports concatenating arrays of different dimensions,
8364    // as long as one of the arrays has the same type as an element of
8365    // the other array, i.e. `int[2][4] || int[4]` (or `int[4] || int[2][4]`)
8366    // works, because each element of `int[2][4]` is an `int[4]`.
8367    // This check is separate from the one below because Postgres gives a
8368    // specific error message if the number of dimensions differs by more
8369    // than one.
8370    // This cast is safe since MAX_ARRAY_DIMENSIONS is 6
8371    // Can be replaced by .abs_diff once it is stabilized
8372    // TODO(benesch): remove potentially dangerous usage of `as`.
8373    #[allow(clippy::as_conversions)]
8374    if (a_ndims as isize - b_ndims as isize).abs() > 1 {
8375        return Err(EvalError::IncompatibleArrayDimensions {
8376            dims: Some((a_ndims, b_ndims)),
8377        });
8378    }
8379
8380    let mut dims;
8381
8382    // After the checks above, we are certain that:
8383    // - neither array is zero dimensional nor empty
8384    // - both arrays have the same number of dimensions, or differ
8385    //   at most by one.
8386    match a_ndims.cmp(&b_ndims) {
8387        // If both arrays have the same number of dimensions, validate
8388        // that their inner dimensions are the same and concatenate the
8389        // arrays.
8390        Ordering::Equal => {
8391            if &a_dims[1..] != &b_dims[1..] {
8392                return Err(EvalError::IncompatibleArrayDimensions { dims: None });
8393            }
8394            dims = vec![ArrayDimension {
8395                lower_bound: a_dims[0].lower_bound,
8396                length: a_dims[0].length + b_dims[0].length,
8397            }];
8398            dims.extend(&a_dims[1..]);
8399        }
8400        // If `a` has less dimensions than `b`, this is an element-array
8401        // concatenation, which requires that `a` has the same dimensions
8402        // as an element of `b`.
8403        Ordering::Less => {
8404            if &a_dims[..] != &b_dims[1..] {
8405                return Err(EvalError::IncompatibleArrayDimensions { dims: None });
8406            }
8407            dims = vec![ArrayDimension {
8408                lower_bound: b_dims[0].lower_bound,
8409                // Since `a` is treated as an element of `b`, the length of
8410                // the first dimension of `b` is incremented by one, as `a` is
8411                // non-empty.
8412                length: b_dims[0].length + 1,
8413            }];
8414            dims.extend(a_dims);
8415        }
8416        // If `a` has more dimensions than `b`, this is an array-element
8417        // concatenation, which requires that `b` has the same dimensions
8418        // as an element of `a`.
8419        Ordering::Greater => {
8420            if &a_dims[1..] != &b_dims[..] {
8421                return Err(EvalError::IncompatibleArrayDimensions { dims: None });
8422            }
8423            dims = vec![ArrayDimension {
8424                lower_bound: a_dims[0].lower_bound,
8425                // Since `b` is treated as an element of `a`, the length of
8426                // the first dimension of `a` is incremented by one, as `b`
8427                // is non-empty.
8428                length: a_dims[0].length + 1,
8429            }];
8430            dims.extend(b_dims);
8431        }
8432    }
8433
8434    let elems = a_array.elements().iter().chain(b_array.elements().iter());
8435
8436    Ok(temp_storage.try_make_datum(|packer| packer.try_push_array(&dims, elems))?)
8437}
8438
8439fn list_list_concat<'a>(a: Datum<'a>, b: Datum<'a>, temp_storage: &'a RowArena) -> Datum<'a> {
8440    if a.is_null() {
8441        return b;
8442    } else if b.is_null() {
8443        return a;
8444    }
8445
8446    let a = a.unwrap_list().iter();
8447    let b = b.unwrap_list().iter();
8448
8449    temp_storage.make_datum(|packer| packer.push_list(a.chain(b)))
8450}
8451
8452fn list_element_concat<'a>(a: Datum<'a>, b: Datum<'a>, temp_storage: &'a RowArena) -> Datum<'a> {
8453    temp_storage.make_datum(|packer| {
8454        packer.push_list_with(|packer| {
8455            if !a.is_null() {
8456                for elem in a.unwrap_list().iter() {
8457                    packer.push(elem);
8458                }
8459            }
8460            packer.push(b);
8461        })
8462    })
8463}
8464
8465fn element_list_concat<'a>(a: Datum<'a>, b: Datum<'a>, temp_storage: &'a RowArena) -> Datum<'a> {
8466    temp_storage.make_datum(|packer| {
8467        packer.push_list_with(|packer| {
8468            packer.push(a);
8469            if !b.is_null() {
8470                for elem in b.unwrap_list().iter() {
8471                    packer.push(elem);
8472                }
8473            }
8474        })
8475    })
8476}
8477
8478fn list_remove<'a>(a: Datum<'a>, b: Datum<'a>, temp_storage: &'a RowArena) -> Datum<'a> {
8479    if a.is_null() {
8480        return a;
8481    }
8482
8483    temp_storage.make_datum(|packer| {
8484        packer.push_list_with(|packer| {
8485            for elem in a.unwrap_list().iter() {
8486                if elem != b {
8487                    packer.push(elem);
8488                }
8489            }
8490        })
8491    })
8492}
8493
8494fn digest_string<'a>(
8495    a: Datum<'a>,
8496    b: Datum<'a>,
8497    temp_storage: &'a RowArena,
8498) -> Result<Datum<'a>, EvalError> {
8499    let to_digest = a.unwrap_str().as_bytes();
8500    digest_inner(to_digest, b, temp_storage)
8501}
8502
8503fn digest_bytes<'a>(
8504    a: Datum<'a>,
8505    b: Datum<'a>,
8506    temp_storage: &'a RowArena,
8507) -> Result<Datum<'a>, EvalError> {
8508    let to_digest = a.unwrap_bytes();
8509    digest_inner(to_digest, b, temp_storage)
8510}
8511
8512fn digest_inner<'a>(
8513    bytes: &[u8],
8514    digest_fn: Datum<'a>,
8515    temp_storage: &'a RowArena,
8516) -> Result<Datum<'a>, EvalError> {
8517    let bytes = match digest_fn.unwrap_str() {
8518        "md5" => Md5::digest(bytes).to_vec(),
8519        "sha1" => Sha1::digest(bytes).to_vec(),
8520        "sha224" => Sha224::digest(bytes).to_vec(),
8521        "sha256" => Sha256::digest(bytes).to_vec(),
8522        "sha384" => Sha384::digest(bytes).to_vec(),
8523        "sha512" => Sha512::digest(bytes).to_vec(),
8524        other => return Err(EvalError::InvalidHashAlgorithm(other.into())),
8525    };
8526    Ok(Datum::Bytes(temp_storage.push_bytes(bytes)))
8527}
8528
8529fn mz_render_typmod<'a>(
8530    oid: Datum<'a>,
8531    typmod: Datum<'a>,
8532    temp_storage: &'a RowArena,
8533) -> Result<Datum<'a>, EvalError> {
8534    let oid = oid.unwrap_uint32();
8535    let typmod = typmod.unwrap_int32();
8536    let s = match Type::from_oid_and_typmod(oid, typmod) {
8537        Ok(typ) => typ.constraint().display_or("").to_string(),
8538        // Match dubious PostgreSQL behavior of outputting the unmodified
8539        // `typmod` when positive if the type OID/typmod is invalid.
8540        Err(_) if typmod >= 0 => format!("({typmod})"),
8541        Err(_) => "".into(),
8542    };
8543    Ok(Datum::String(temp_storage.push_string(s)))
8544}
8545
8546fn make_acl_item<'a>(datums: &[Datum<'a>]) -> Result<Datum<'a>, EvalError> {
8547    let grantee = Oid(datums[0].unwrap_uint32());
8548    let grantor = Oid(datums[1].unwrap_uint32());
8549    let privileges = datums[2].unwrap_str();
8550    let acl_mode = AclMode::parse_multiple_privileges(privileges)
8551        .map_err(|e: anyhow::Error| EvalError::InvalidPrivileges(e.to_string().into()))?;
8552    let is_grantable = datums[3].unwrap_bool();
8553    if is_grantable {
8554        return Err(EvalError::Unsupported {
8555            feature: "GRANT OPTION".into(),
8556            discussion_no: None,
8557        });
8558    }
8559
8560    Ok(Datum::AclItem(AclItem {
8561        grantee,
8562        grantor,
8563        acl_mode,
8564    }))
8565}
8566
8567fn make_mz_acl_item<'a>(datums: &[Datum<'a>]) -> Result<Datum<'a>, EvalError> {
8568    let grantee: RoleId = datums[0]
8569        .unwrap_str()
8570        .parse()
8571        .map_err(|e: anyhow::Error| EvalError::InvalidRoleId(e.to_string().into()))?;
8572    let grantor: RoleId = datums[1]
8573        .unwrap_str()
8574        .parse()
8575        .map_err(|e: anyhow::Error| EvalError::InvalidRoleId(e.to_string().into()))?;
8576    if grantor == RoleId::Public {
8577        return Err(EvalError::InvalidRoleId(
8578            "mz_aclitem grantor cannot be PUBLIC role".into(),
8579        ));
8580    }
8581    let privileges = datums[2].unwrap_str();
8582    let acl_mode = AclMode::parse_multiple_privileges(privileges)
8583        .map_err(|e: anyhow::Error| EvalError::InvalidPrivileges(e.to_string().into()))?;
8584
8585    Ok(Datum::MzAclItem(MzAclItem {
8586        grantee,
8587        grantor,
8588        acl_mode,
8589    }))
8590}
8591
8592fn array_fill<'a>(
8593    datums: &[Datum<'a>],
8594    temp_storage: &'a RowArena,
8595) -> Result<Datum<'a>, EvalError> {
8596    const MAX_SIZE: usize = 1 << 28 - 1;
8597    const NULL_ARR_ERR: &str = "dimension array or low bound array";
8598    const NULL_ELEM_ERR: &str = "dimension values";
8599
8600    let fill = datums[0];
8601    if matches!(fill, Datum::Array(_)) {
8602        return Err(EvalError::Unsupported {
8603            feature: "array_fill with arrays".into(),
8604            discussion_no: None,
8605        });
8606    }
8607
8608    let arr = match datums[1] {
8609        Datum::Null => return Err(EvalError::MustNotBeNull(NULL_ARR_ERR.into())),
8610        o => o.unwrap_array(),
8611    };
8612
8613    let dimensions = arr
8614        .elements()
8615        .iter()
8616        .map(|d| match d {
8617            Datum::Null => Err(EvalError::MustNotBeNull(NULL_ELEM_ERR.into())),
8618            d => Ok(usize::cast_from(u32::reinterpret_cast(d.unwrap_int32()))),
8619        })
8620        .collect::<Result<Vec<_>, _>>()?;
8621
8622    let lower_bounds = match datums.get(2) {
8623        Some(d) => {
8624            let arr = match d {
8625                Datum::Null => return Err(EvalError::MustNotBeNull(NULL_ARR_ERR.into())),
8626                o => o.unwrap_array(),
8627            };
8628
8629            arr.elements()
8630                .iter()
8631                .map(|l| match l {
8632                    Datum::Null => Err(EvalError::MustNotBeNull(NULL_ELEM_ERR.into())),
8633                    l => Ok(isize::cast_from(l.unwrap_int32())),
8634                })
8635                .collect::<Result<Vec<_>, _>>()?
8636        }
8637        None => {
8638            vec![1isize; dimensions.len()]
8639        }
8640    };
8641
8642    if lower_bounds.len() != dimensions.len() {
8643        return Err(EvalError::ArrayFillWrongArraySubscripts);
8644    }
8645
8646    let fill_count: usize = dimensions
8647        .iter()
8648        .cloned()
8649        .map(Some)
8650        .reduce(|a, b| match (a, b) {
8651            (Some(a), Some(b)) => a.checked_mul(b),
8652            _ => None,
8653        })
8654        .flatten()
8655        .ok_or(EvalError::MaxArraySizeExceeded(MAX_SIZE))?;
8656
8657    if matches!(
8658        mz_repr::datum_size(&fill).checked_mul(fill_count),
8659        None | Some(MAX_SIZE..)
8660    ) {
8661        return Err(EvalError::MaxArraySizeExceeded(MAX_SIZE));
8662    }
8663
8664    let array_dimensions = if fill_count == 0 {
8665        vec![ArrayDimension {
8666            lower_bound: 1,
8667            length: 0,
8668        }]
8669    } else {
8670        dimensions
8671            .into_iter()
8672            .zip_eq(lower_bounds)
8673            .map(|(length, lower_bound)| ArrayDimension {
8674                lower_bound,
8675                length,
8676            })
8677            .collect()
8678    };
8679
8680    Ok(temp_storage.try_make_datum(|packer| {
8681        packer.try_push_array(&array_dimensions, vec![fill; fill_count])
8682    })?)
8683}
8684
8685#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
8686pub enum VariadicFunc {
8687    Coalesce,
8688    Greatest,
8689    Least,
8690    Concat,
8691    ConcatWs,
8692    MakeTimestamp,
8693    PadLeading,
8694    Substr,
8695    Replace,
8696    JsonbBuildArray,
8697    JsonbBuildObject,
8698    MapBuild {
8699        value_type: ScalarType,
8700    },
8701    ArrayCreate {
8702        // We need to know the element type to type empty arrays.
8703        elem_type: ScalarType,
8704    },
8705    ArrayToString {
8706        elem_type: ScalarType,
8707    },
8708    ArrayIndex {
8709        // Adjusts the index by offset depending on whether being called on an array or an
8710        // Int2Vector.
8711        offset: i64,
8712    },
8713    ListCreate {
8714        // We need to know the element type to type empty lists.
8715        elem_type: ScalarType,
8716    },
8717    RecordCreate {
8718        field_names: Vec<ColumnName>,
8719    },
8720    ListIndex,
8721    ListSliceLinear,
8722    SplitPart,
8723    RegexpMatch,
8724    HmacString,
8725    HmacBytes,
8726    ErrorIfNull,
8727    DateBinTimestamp,
8728    DateBinTimestampTz,
8729    DateDiffTimestamp,
8730    DateDiffTimestampTz,
8731    DateDiffDate,
8732    DateDiffTime,
8733    And,
8734    Or,
8735    RangeCreate {
8736        elem_type: ScalarType,
8737    },
8738    MakeAclItem,
8739    MakeMzAclItem,
8740    Translate,
8741    ArrayPosition,
8742    ArrayFill {
8743        elem_type: ScalarType,
8744    },
8745    StringToArray,
8746    TimezoneTime,
8747    RegexpSplitToArray,
8748    RegexpReplace,
8749}
8750
8751impl VariadicFunc {
8752    pub fn eval<'a>(
8753        &'a self,
8754        datums: &[Datum<'a>],
8755        temp_storage: &'a RowArena,
8756        exprs: &'a [MirScalarExpr],
8757    ) -> Result<Datum<'a>, EvalError> {
8758        // Evaluate all non-eager functions directly
8759        match self {
8760            VariadicFunc::Coalesce => return coalesce(datums, temp_storage, exprs),
8761            VariadicFunc::Greatest => return greatest(datums, temp_storage, exprs),
8762            VariadicFunc::And => return and(datums, temp_storage, exprs),
8763            VariadicFunc::Or => return or(datums, temp_storage, exprs),
8764            VariadicFunc::ErrorIfNull => return error_if_null(datums, temp_storage, exprs),
8765            VariadicFunc::Least => return least(datums, temp_storage, exprs),
8766            _ => {}
8767        };
8768
8769        // Compute parameters to eager functions
8770        let ds = exprs
8771            .iter()
8772            .map(|e| e.eval(datums, temp_storage))
8773            .collect::<Result<Vec<_>, _>>()?;
8774        // Check NULL propagation
8775        if self.propagates_nulls() && ds.iter().any(|d| d.is_null()) {
8776            return Ok(Datum::Null);
8777        }
8778
8779        // Evaluate eager functions
8780        match self {
8781            VariadicFunc::Coalesce
8782            | VariadicFunc::Greatest
8783            | VariadicFunc::And
8784            | VariadicFunc::Or
8785            | VariadicFunc::ErrorIfNull
8786            | VariadicFunc::Least => unreachable!(),
8787            VariadicFunc::Concat => Ok(text_concat_variadic(&ds, temp_storage)),
8788            VariadicFunc::ConcatWs => Ok(text_concat_ws(&ds, temp_storage)),
8789            VariadicFunc::MakeTimestamp => make_timestamp(&ds),
8790            VariadicFunc::PadLeading => pad_leading(&ds, temp_storage),
8791            VariadicFunc::Substr => substr(&ds),
8792            VariadicFunc::Replace => Ok(replace(&ds, temp_storage)),
8793            VariadicFunc::Translate => Ok(translate(&ds, temp_storage)),
8794            VariadicFunc::JsonbBuildArray => Ok(jsonb_build_array(&ds, temp_storage)),
8795            VariadicFunc::JsonbBuildObject => jsonb_build_object(&ds, temp_storage),
8796            VariadicFunc::MapBuild { .. } => Ok(map_build(&ds, temp_storage)),
8797            VariadicFunc::ArrayCreate {
8798                elem_type: ScalarType::Array(_),
8799            } => array_create_multidim(&ds, temp_storage),
8800            VariadicFunc::ArrayCreate { .. } => array_create_scalar(&ds, temp_storage),
8801            VariadicFunc::ArrayToString { elem_type } => {
8802                array_to_string(&ds, elem_type, temp_storage)
8803            }
8804            VariadicFunc::ArrayIndex { offset } => Ok(array_index(&ds, *offset)),
8805
8806            VariadicFunc::ListCreate { .. } | VariadicFunc::RecordCreate { .. } => {
8807                Ok(list_create(&ds, temp_storage))
8808            }
8809            VariadicFunc::ListIndex => Ok(list_index(&ds)),
8810            VariadicFunc::ListSliceLinear => Ok(list_slice_linear(&ds, temp_storage)),
8811            VariadicFunc::SplitPart => split_part(&ds),
8812            VariadicFunc::RegexpMatch => regexp_match_dynamic(&ds, temp_storage),
8813            VariadicFunc::HmacString => hmac_string(&ds, temp_storage),
8814            VariadicFunc::HmacBytes => hmac_bytes(&ds, temp_storage),
8815            VariadicFunc::DateBinTimestamp => date_bin(
8816                ds[0].unwrap_interval(),
8817                ds[1].unwrap_timestamp(),
8818                ds[2].unwrap_timestamp(),
8819            ),
8820            VariadicFunc::DateBinTimestampTz => date_bin(
8821                ds[0].unwrap_interval(),
8822                ds[1].unwrap_timestamptz(),
8823                ds[2].unwrap_timestamptz(),
8824            ),
8825            VariadicFunc::DateDiffTimestamp => date_diff_timestamp(ds[0], ds[1], ds[2]),
8826            VariadicFunc::DateDiffTimestampTz => date_diff_timestamptz(ds[0], ds[1], ds[2]),
8827            VariadicFunc::DateDiffDate => date_diff_date(ds[0], ds[1], ds[2]),
8828            VariadicFunc::DateDiffTime => date_diff_time(ds[0], ds[1], ds[2]),
8829            VariadicFunc::RangeCreate { .. } => create_range(&ds, temp_storage),
8830            VariadicFunc::MakeAclItem => make_acl_item(&ds),
8831            VariadicFunc::MakeMzAclItem => make_mz_acl_item(&ds),
8832            VariadicFunc::ArrayPosition => array_position(&ds),
8833            VariadicFunc::ArrayFill { .. } => array_fill(&ds, temp_storage),
8834            VariadicFunc::TimezoneTime => parse_timezone(ds[0].unwrap_str(), TimezoneSpec::Posix)
8835                .map(|tz| {
8836                    timezone_time(
8837                        tz,
8838                        ds[1].unwrap_time(),
8839                        &ds[2].unwrap_timestamptz().naive_utc(),
8840                    )
8841                    .into()
8842                }),
8843            VariadicFunc::RegexpSplitToArray => {
8844                let flags = if ds.len() == 2 {
8845                    Datum::String("")
8846                } else {
8847                    ds[2]
8848                };
8849                regexp_split_to_array(ds[0], ds[1], flags, temp_storage)
8850            }
8851            VariadicFunc::RegexpReplace => regexp_replace_dynamic(&ds, temp_storage),
8852            VariadicFunc::StringToArray => {
8853                let null_string = if ds.len() == 2 { Datum::Null } else { ds[2] };
8854
8855                string_to_array(ds[0], ds[1], null_string, temp_storage)
8856            }
8857        }
8858    }
8859
8860    pub fn is_associative(&self) -> bool {
8861        match self {
8862            VariadicFunc::Coalesce
8863            | VariadicFunc::Greatest
8864            | VariadicFunc::Least
8865            | VariadicFunc::Concat
8866            | VariadicFunc::And
8867            | VariadicFunc::Or => true,
8868
8869            VariadicFunc::MakeTimestamp
8870            | VariadicFunc::PadLeading
8871            | VariadicFunc::ConcatWs
8872            | VariadicFunc::Substr
8873            | VariadicFunc::Replace
8874            | VariadicFunc::Translate
8875            | VariadicFunc::JsonbBuildArray
8876            | VariadicFunc::JsonbBuildObject
8877            | VariadicFunc::MapBuild { value_type: _ }
8878            | VariadicFunc::ArrayCreate { elem_type: _ }
8879            | VariadicFunc::ArrayToString { elem_type: _ }
8880            | VariadicFunc::ArrayIndex { offset: _ }
8881            | VariadicFunc::ListCreate { elem_type: _ }
8882            | VariadicFunc::RecordCreate { field_names: _ }
8883            | VariadicFunc::ListIndex
8884            | VariadicFunc::ListSliceLinear
8885            | VariadicFunc::SplitPart
8886            | VariadicFunc::RegexpMatch
8887            | VariadicFunc::HmacString
8888            | VariadicFunc::HmacBytes
8889            | VariadicFunc::ErrorIfNull
8890            | VariadicFunc::DateBinTimestamp
8891            | VariadicFunc::DateBinTimestampTz
8892            | VariadicFunc::DateDiffTimestamp
8893            | VariadicFunc::DateDiffTimestampTz
8894            | VariadicFunc::DateDiffDate
8895            | VariadicFunc::DateDiffTime
8896            | VariadicFunc::RangeCreate { .. }
8897            | VariadicFunc::MakeAclItem
8898            | VariadicFunc::MakeMzAclItem
8899            | VariadicFunc::ArrayPosition
8900            | VariadicFunc::ArrayFill { .. }
8901            | VariadicFunc::TimezoneTime
8902            | VariadicFunc::RegexpSplitToArray
8903            | VariadicFunc::StringToArray
8904            | VariadicFunc::RegexpReplace => false,
8905        }
8906    }
8907
8908    pub fn output_type(&self, input_types: Vec<ColumnType>) -> ColumnType {
8909        use VariadicFunc::*;
8910        let in_nullable = input_types.iter().any(|t| t.nullable);
8911        match self {
8912            Greatest | Least => input_types
8913                .into_iter()
8914                .reduce(|l, r| l.union(&r).unwrap())
8915                .unwrap(),
8916            Coalesce => {
8917                // Note that the parser doesn't allow empty argument lists for variadic functions
8918                // that use the standard function call syntax (ArrayCreate and co. are different
8919                // because of the special syntax for calling them).
8920                let nullable = input_types.iter().all(|typ| typ.nullable);
8921                input_types
8922                    .into_iter()
8923                    .reduce(|l, r| l.union(&r).unwrap())
8924                    .unwrap()
8925                    .nullable(nullable)
8926            }
8927            Concat | ConcatWs => ScalarType::String.nullable(in_nullable),
8928            MakeTimestamp => ScalarType::Timestamp { precision: None }.nullable(true),
8929            PadLeading => ScalarType::String.nullable(in_nullable),
8930            Substr => ScalarType::String.nullable(in_nullable),
8931            Replace => ScalarType::String.nullable(in_nullable),
8932            Translate => ScalarType::String.nullable(in_nullable),
8933            JsonbBuildArray | JsonbBuildObject => ScalarType::Jsonb.nullable(true),
8934            MapBuild { value_type } => ScalarType::Map {
8935                value_type: Box::new(value_type.clone()),
8936                custom_id: None,
8937            }
8938            .nullable(true),
8939            ArrayCreate { elem_type } => {
8940                debug_assert!(
8941                    input_types.iter().all(|t| t.scalar_type.base_eq(elem_type)),
8942                    "Args to ArrayCreate should have types that are compatible with the elem_type"
8943                );
8944                match elem_type {
8945                    ScalarType::Array(_) => elem_type.clone().nullable(false),
8946                    _ => ScalarType::Array(Box::new(elem_type.clone())).nullable(false),
8947                }
8948            }
8949            ArrayToString { .. } => ScalarType::String.nullable(in_nullable),
8950            ArrayIndex { .. } => input_types[0]
8951                .scalar_type
8952                .unwrap_array_element_type()
8953                .clone()
8954                .nullable(true),
8955            ListCreate { elem_type } => {
8956                // commented out to work around
8957                // https://github.com/MaterializeInc/database-issues/issues/2730
8958                // soft_assert!(
8959                //     input_types.iter().all(|t| t.scalar_type.base_eq(elem_type)),
8960                //     "{}", format!("Args to ListCreate should have types that are compatible with the elem_type.\nArgs:{:#?}\nelem_type:{:#?}", input_types, elem_type)
8961                // );
8962                ScalarType::List {
8963                    element_type: Box::new(elem_type.clone()),
8964                    custom_id: None,
8965                }
8966                .nullable(false)
8967            }
8968            ListIndex => input_types[0]
8969                .scalar_type
8970                .unwrap_list_nth_layer_type(input_types.len() - 1)
8971                .clone()
8972                .nullable(true),
8973            ListSliceLinear { .. } => input_types[0].scalar_type.clone().nullable(in_nullable),
8974            RecordCreate { field_names } => ScalarType::Record {
8975                fields: field_names
8976                    .clone()
8977                    .into_iter()
8978                    .zip_eq(input_types)
8979                    .collect(),
8980                custom_id: None,
8981            }
8982            .nullable(false),
8983            SplitPart => ScalarType::String.nullable(in_nullable),
8984            RegexpMatch => ScalarType::Array(Box::new(ScalarType::String)).nullable(true),
8985            HmacString | HmacBytes => ScalarType::Bytes.nullable(in_nullable),
8986            ErrorIfNull => input_types[0].scalar_type.clone().nullable(false),
8987            DateBinTimestamp => ScalarType::Timestamp { precision: None }.nullable(in_nullable),
8988            DateBinTimestampTz => ScalarType::TimestampTz { precision: None }.nullable(in_nullable),
8989            DateDiffTimestamp => ScalarType::Int64.nullable(in_nullable),
8990            DateDiffTimestampTz => ScalarType::Int64.nullable(in_nullable),
8991            DateDiffDate => ScalarType::Int64.nullable(in_nullable),
8992            DateDiffTime => ScalarType::Int64.nullable(in_nullable),
8993            And | Or => ScalarType::Bool.nullable(in_nullable),
8994            RangeCreate { elem_type } => ScalarType::Range {
8995                element_type: Box::new(elem_type.clone()),
8996            }
8997            .nullable(false),
8998            MakeAclItem => ScalarType::AclItem.nullable(true),
8999            MakeMzAclItem => ScalarType::MzAclItem.nullable(true),
9000            ArrayPosition => ScalarType::Int32.nullable(true),
9001            ArrayFill { elem_type } => {
9002                ScalarType::Array(Box::new(elem_type.clone())).nullable(false)
9003            }
9004            TimezoneTime => ScalarType::Time.nullable(in_nullable),
9005            RegexpSplitToArray => {
9006                ScalarType::Array(Box::new(ScalarType::String)).nullable(in_nullable)
9007            }
9008            RegexpReplace => ScalarType::String.nullable(in_nullable),
9009            StringToArray => ScalarType::Array(Box::new(ScalarType::String)).nullable(true),
9010        }
9011    }
9012
9013    /// Whether the function output is NULL if any of its inputs are NULL.
9014    ///
9015    /// NB: if any input is NULL the output will be returned as NULL without
9016    /// calling the function.
9017    pub fn propagates_nulls(&self) -> bool {
9018        // NOTE: The following is a list of the variadic functions
9019        // that **DO NOT** propagate nulls.
9020        !matches!(
9021            self,
9022            VariadicFunc::And
9023                | VariadicFunc::Or
9024                | VariadicFunc::Coalesce
9025                | VariadicFunc::Greatest
9026                | VariadicFunc::Least
9027                | VariadicFunc::Concat
9028                | VariadicFunc::ConcatWs
9029                | VariadicFunc::JsonbBuildArray
9030                | VariadicFunc::JsonbBuildObject
9031                | VariadicFunc::MapBuild { .. }
9032                | VariadicFunc::ListCreate { .. }
9033                | VariadicFunc::RecordCreate { .. }
9034                | VariadicFunc::ArrayCreate { .. }
9035                | VariadicFunc::ArrayToString { .. }
9036                | VariadicFunc::ErrorIfNull
9037                | VariadicFunc::RangeCreate { .. }
9038                | VariadicFunc::ArrayPosition
9039                | VariadicFunc::ArrayFill { .. }
9040                | VariadicFunc::StringToArray
9041        )
9042    }
9043
9044    /// Whether the function might return NULL even if none of its inputs are
9045    /// NULL.
9046    ///
9047    /// This is presently conservative, and may indicate that a function
9048    /// introduces nulls even when it does not.
9049    pub fn introduces_nulls(&self) -> bool {
9050        use VariadicFunc::*;
9051        match self {
9052            Concat
9053            | ConcatWs
9054            | PadLeading
9055            | Substr
9056            | Replace
9057            | Translate
9058            | JsonbBuildArray
9059            | JsonbBuildObject
9060            | MapBuild { .. }
9061            | ArrayCreate { .. }
9062            | ArrayToString { .. }
9063            | ListCreate { .. }
9064            | RecordCreate { .. }
9065            | ListSliceLinear
9066            | SplitPart
9067            | HmacString
9068            | HmacBytes
9069            | ErrorIfNull
9070            | DateBinTimestamp
9071            | DateBinTimestampTz
9072            | DateDiffTimestamp
9073            | DateDiffTimestampTz
9074            | DateDiffDate
9075            | DateDiffTime
9076            | RangeCreate { .. }
9077            | And
9078            | Or
9079            | MakeAclItem
9080            | MakeMzAclItem
9081            | ArrayPosition
9082            | ArrayFill { .. }
9083            | TimezoneTime
9084            | RegexpSplitToArray
9085            | RegexpReplace => false,
9086            Coalesce
9087            | Greatest
9088            | Least
9089            | MakeTimestamp
9090            | ArrayIndex { .. }
9091            | StringToArray
9092            | ListIndex
9093            | RegexpMatch => true,
9094        }
9095    }
9096
9097    pub fn switch_and_or(&self) -> Self {
9098        match self {
9099            VariadicFunc::And => VariadicFunc::Or,
9100            VariadicFunc::Or => VariadicFunc::And,
9101            _ => unreachable!(),
9102        }
9103    }
9104
9105    pub fn is_infix_op(&self) -> bool {
9106        use VariadicFunc::*;
9107        matches!(self, And | Or)
9108    }
9109
9110    /// Gives the unit (u) of OR or AND, such that `u AND/OR x == x`.
9111    /// Note that a 0-arg AND/OR evaluates to unit_of_and_or.
9112    pub fn unit_of_and_or(&self) -> MirScalarExpr {
9113        match self {
9114            VariadicFunc::And => MirScalarExpr::literal_true(),
9115            VariadicFunc::Or => MirScalarExpr::literal_false(),
9116            _ => unreachable!(),
9117        }
9118    }
9119
9120    /// Gives the zero (z) of OR or AND, such that `z AND/OR x == z`.
9121    pub fn zero_of_and_or(&self) -> MirScalarExpr {
9122        match self {
9123            VariadicFunc::And => MirScalarExpr::literal_false(),
9124            VariadicFunc::Or => MirScalarExpr::literal_true(),
9125            _ => unreachable!(),
9126        }
9127    }
9128
9129    /// Returns true if the function could introduce an error on non-error inputs.
9130    pub fn could_error(&self) -> bool {
9131        match self {
9132            VariadicFunc::And | VariadicFunc::Or => false,
9133            VariadicFunc::Coalesce => false,
9134            VariadicFunc::Greatest | VariadicFunc::Least => false,
9135            VariadicFunc::Concat | VariadicFunc::ConcatWs => false,
9136            VariadicFunc::Replace => false,
9137            VariadicFunc::Translate => false,
9138            VariadicFunc::ArrayIndex { .. } => false,
9139            VariadicFunc::ListCreate { .. } | VariadicFunc::RecordCreate { .. } => false,
9140            // All other cases are unknown
9141            _ => true,
9142        }
9143    }
9144
9145    /// Returns true if the function is monotone. (Non-strict; either increasing or decreasing.)
9146    /// Monotone functions map ranges to ranges: ie. given a range of possible inputs, we can
9147    /// determine the range of possible outputs just by mapping the endpoints.
9148    ///
9149    /// This describes the *pointwise* behaviour of the function:
9150    /// ie. if more than one argument is provided, this describes the behaviour of
9151    /// any specific argument as the others are held constant. (For example, `COALESCE(a, b)` is
9152    /// monotone in `a` because for any particular value of `b`, increasing `a` will never
9153    /// cause the result to decrease.)
9154    ///
9155    /// This property describes the behaviour of the function over ranges where the function is defined:
9156    /// ie. the arguments and the result are non-error datums.
9157    pub fn is_monotone(&self) -> bool {
9158        match self {
9159            VariadicFunc::Coalesce
9160            | VariadicFunc::Greatest
9161            | VariadicFunc::Least
9162            | VariadicFunc::And
9163            | VariadicFunc::Or => true,
9164            VariadicFunc::Concat
9165            | VariadicFunc::ConcatWs
9166            | VariadicFunc::MakeTimestamp
9167            | VariadicFunc::PadLeading
9168            | VariadicFunc::Substr
9169            | VariadicFunc::Replace
9170            | VariadicFunc::JsonbBuildArray
9171            | VariadicFunc::JsonbBuildObject
9172            | VariadicFunc::MapBuild { .. }
9173            | VariadicFunc::ArrayCreate { .. }
9174            | VariadicFunc::ArrayToString { .. }
9175            | VariadicFunc::ArrayIndex { .. }
9176            | VariadicFunc::ListCreate { .. }
9177            | VariadicFunc::RecordCreate { .. }
9178            | VariadicFunc::ListIndex
9179            | VariadicFunc::ListSliceLinear
9180            | VariadicFunc::SplitPart
9181            | VariadicFunc::RegexpMatch
9182            | VariadicFunc::HmacString
9183            | VariadicFunc::HmacBytes
9184            | VariadicFunc::ErrorIfNull
9185            | VariadicFunc::DateBinTimestamp
9186            | VariadicFunc::DateBinTimestampTz
9187            | VariadicFunc::RangeCreate { .. }
9188            | VariadicFunc::MakeAclItem
9189            | VariadicFunc::MakeMzAclItem
9190            | VariadicFunc::Translate
9191            | VariadicFunc::ArrayPosition
9192            | VariadicFunc::ArrayFill { .. }
9193            | VariadicFunc::DateDiffTimestamp
9194            | VariadicFunc::DateDiffTimestampTz
9195            | VariadicFunc::DateDiffDate
9196            | VariadicFunc::DateDiffTime
9197            | VariadicFunc::TimezoneTime
9198            | VariadicFunc::RegexpSplitToArray
9199            | VariadicFunc::StringToArray
9200            | VariadicFunc::RegexpReplace => false,
9201        }
9202    }
9203}
9204
9205impl fmt::Display for VariadicFunc {
9206    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9207        match self {
9208            VariadicFunc::Coalesce => f.write_str("coalesce"),
9209            VariadicFunc::Greatest => f.write_str("greatest"),
9210            VariadicFunc::Least => f.write_str("least"),
9211            VariadicFunc::Concat => f.write_str("concat"),
9212            VariadicFunc::ConcatWs => f.write_str("concat_ws"),
9213            VariadicFunc::MakeTimestamp => f.write_str("makets"),
9214            VariadicFunc::PadLeading => f.write_str("lpad"),
9215            VariadicFunc::Substr => f.write_str("substr"),
9216            VariadicFunc::Replace => f.write_str("replace"),
9217            VariadicFunc::Translate => f.write_str("translate"),
9218            VariadicFunc::JsonbBuildArray => f.write_str("jsonb_build_array"),
9219            VariadicFunc::JsonbBuildObject => f.write_str("jsonb_build_object"),
9220            VariadicFunc::MapBuild { .. } => f.write_str("map_build"),
9221            VariadicFunc::ArrayCreate { .. } => f.write_str("array_create"),
9222            VariadicFunc::ArrayToString { .. } => f.write_str("array_to_string"),
9223            VariadicFunc::ArrayIndex { .. } => f.write_str("array_index"),
9224            VariadicFunc::ListCreate { .. } => f.write_str("list_create"),
9225            VariadicFunc::RecordCreate { .. } => f.write_str("record_create"),
9226            VariadicFunc::ListIndex => f.write_str("list_index"),
9227            VariadicFunc::ListSliceLinear => f.write_str("list_slice_linear"),
9228            VariadicFunc::SplitPart => f.write_str("split_string"),
9229            VariadicFunc::RegexpMatch => f.write_str("regexp_match"),
9230            VariadicFunc::HmacString | VariadicFunc::HmacBytes => f.write_str("hmac"),
9231            VariadicFunc::ErrorIfNull => f.write_str("error_if_null"),
9232            VariadicFunc::DateBinTimestamp => f.write_str("timestamp_bin"),
9233            VariadicFunc::DateBinTimestampTz => f.write_str("timestamptz_bin"),
9234            VariadicFunc::DateDiffTimestamp
9235            | VariadicFunc::DateDiffTimestampTz
9236            | VariadicFunc::DateDiffDate
9237            | VariadicFunc::DateDiffTime => f.write_str("datediff"),
9238            VariadicFunc::And => f.write_str("AND"),
9239            VariadicFunc::Or => f.write_str("OR"),
9240            VariadicFunc::RangeCreate {
9241                elem_type: element_type,
9242            } => f.write_str(match element_type {
9243                ScalarType::Int32 => "int4range",
9244                ScalarType::Int64 => "int8range",
9245                ScalarType::Date => "daterange",
9246                ScalarType::Numeric { .. } => "numrange",
9247                ScalarType::Timestamp { .. } => "tsrange",
9248                ScalarType::TimestampTz { .. } => "tstzrange",
9249                _ => unreachable!(),
9250            }),
9251            VariadicFunc::MakeAclItem => f.write_str("makeaclitem"),
9252            VariadicFunc::MakeMzAclItem => f.write_str("make_mz_aclitem"),
9253            VariadicFunc::ArrayPosition => f.write_str("array_position"),
9254            VariadicFunc::ArrayFill { .. } => f.write_str("array_fill"),
9255            VariadicFunc::TimezoneTime => f.write_str("timezonet"),
9256            VariadicFunc::RegexpSplitToArray => f.write_str("regexp_split_to_array"),
9257            VariadicFunc::RegexpReplace => f.write_str("regexp_replace"),
9258            VariadicFunc::StringToArray => f.write_str("string_to_array"),
9259        }
9260    }
9261}
9262
9263/// An explicit [`Arbitrary`] implementation needed here because of a known
9264/// `proptest` issue.
9265///
9266/// Revert to the derive-macro impementation once the issue[^1] is fixed.
9267///
9268/// [^1]: <https://github.com/AltSysrq/proptest/issues/152>
9269impl Arbitrary for VariadicFunc {
9270    type Parameters = ();
9271
9272    type Strategy = Union<BoxedStrategy<Self>>;
9273
9274    fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
9275        Union::new(vec![
9276            Just(VariadicFunc::Coalesce).boxed(),
9277            Just(VariadicFunc::Greatest).boxed(),
9278            Just(VariadicFunc::Least).boxed(),
9279            Just(VariadicFunc::Concat).boxed(),
9280            Just(VariadicFunc::ConcatWs).boxed(),
9281            Just(VariadicFunc::MakeTimestamp).boxed(),
9282            Just(VariadicFunc::PadLeading).boxed(),
9283            Just(VariadicFunc::Substr).boxed(),
9284            Just(VariadicFunc::Replace).boxed(),
9285            Just(VariadicFunc::JsonbBuildArray).boxed(),
9286            Just(VariadicFunc::JsonbBuildObject).boxed(),
9287            ScalarType::arbitrary()
9288                .prop_map(|value_type| VariadicFunc::MapBuild { value_type })
9289                .boxed(),
9290            Just(VariadicFunc::MakeAclItem).boxed(),
9291            Just(VariadicFunc::MakeMzAclItem).boxed(),
9292            ScalarType::arbitrary()
9293                .prop_map(|elem_type| VariadicFunc::ArrayCreate { elem_type })
9294                .boxed(),
9295            ScalarType::arbitrary()
9296                .prop_map(|elem_type| VariadicFunc::ArrayToString { elem_type })
9297                .boxed(),
9298            i64::arbitrary()
9299                .prop_map(|offset| VariadicFunc::ArrayIndex { offset })
9300                .boxed(),
9301            ScalarType::arbitrary()
9302                .prop_map(|elem_type| VariadicFunc::ListCreate { elem_type })
9303                .boxed(),
9304            Vec::<ColumnName>::arbitrary()
9305                .prop_map(|field_names| VariadicFunc::RecordCreate { field_names })
9306                .boxed(),
9307            Just(VariadicFunc::ListIndex).boxed(),
9308            Just(VariadicFunc::ListSliceLinear).boxed(),
9309            Just(VariadicFunc::SplitPart).boxed(),
9310            Just(VariadicFunc::RegexpMatch).boxed(),
9311            Just(VariadicFunc::HmacString).boxed(),
9312            Just(VariadicFunc::HmacBytes).boxed(),
9313            Just(VariadicFunc::ErrorIfNull).boxed(),
9314            Just(VariadicFunc::DateBinTimestamp).boxed(),
9315            Just(VariadicFunc::DateBinTimestampTz).boxed(),
9316            Just(VariadicFunc::DateDiffTimestamp).boxed(),
9317            Just(VariadicFunc::DateDiffTimestampTz).boxed(),
9318            Just(VariadicFunc::DateDiffDate).boxed(),
9319            Just(VariadicFunc::DateDiffTime).boxed(),
9320            Just(VariadicFunc::And).boxed(),
9321            Just(VariadicFunc::Or).boxed(),
9322            mz_repr::arb_range_type()
9323                .prop_map(|elem_type| VariadicFunc::RangeCreate { elem_type })
9324                .boxed(),
9325            Just(VariadicFunc::ArrayPosition).boxed(),
9326            ScalarType::arbitrary()
9327                .prop_map(|elem_type| VariadicFunc::ArrayFill { elem_type })
9328                .boxed(),
9329        ])
9330    }
9331}
9332
9333impl RustType<ProtoVariadicFunc> for VariadicFunc {
9334    fn into_proto(&self) -> ProtoVariadicFunc {
9335        use crate::scalar::proto_variadic_func::Kind::*;
9336        use crate::scalar::proto_variadic_func::ProtoRecordCreate;
9337        let kind = match self {
9338            VariadicFunc::Coalesce => Coalesce(()),
9339            VariadicFunc::Greatest => Greatest(()),
9340            VariadicFunc::Least => Least(()),
9341            VariadicFunc::Concat => Concat(()),
9342            VariadicFunc::ConcatWs => ConcatWs(()),
9343            VariadicFunc::MakeTimestamp => MakeTimestamp(()),
9344            VariadicFunc::PadLeading => PadLeading(()),
9345            VariadicFunc::Substr => Substr(()),
9346            VariadicFunc::Replace => Replace(()),
9347            VariadicFunc::Translate => Translate(()),
9348            VariadicFunc::JsonbBuildArray => JsonbBuildArray(()),
9349            VariadicFunc::JsonbBuildObject => JsonbBuildObject(()),
9350            VariadicFunc::MapBuild { value_type } => MapBuild(value_type.into_proto()),
9351            VariadicFunc::ArrayCreate { elem_type } => ArrayCreate(elem_type.into_proto()),
9352            VariadicFunc::ArrayToString { elem_type } => ArrayToString(elem_type.into_proto()),
9353            VariadicFunc::ArrayIndex { offset } => ArrayIndex(offset.into_proto()),
9354            VariadicFunc::ListCreate { elem_type } => ListCreate(elem_type.into_proto()),
9355            VariadicFunc::RecordCreate { field_names } => RecordCreate(ProtoRecordCreate {
9356                field_names: field_names.into_proto(),
9357            }),
9358            VariadicFunc::ListIndex => ListIndex(()),
9359            VariadicFunc::ListSliceLinear => ListSliceLinear(()),
9360            VariadicFunc::SplitPart => SplitPart(()),
9361            VariadicFunc::RegexpMatch => RegexpMatch(()),
9362            VariadicFunc::HmacString => HmacString(()),
9363            VariadicFunc::HmacBytes => HmacBytes(()),
9364            VariadicFunc::ErrorIfNull => ErrorIfNull(()),
9365            VariadicFunc::DateBinTimestamp => DateBinTimestamp(()),
9366            VariadicFunc::DateBinTimestampTz => DateBinTimestampTz(()),
9367            VariadicFunc::DateDiffTimestamp => DateDiffTimestamp(()),
9368            VariadicFunc::DateDiffTimestampTz => DateDiffTimestampTz(()),
9369            VariadicFunc::DateDiffDate => DateDiffDate(()),
9370            VariadicFunc::DateDiffTime => DateDiffTime(()),
9371            VariadicFunc::And => And(()),
9372            VariadicFunc::Or => Or(()),
9373            VariadicFunc::RangeCreate { elem_type } => RangeCreate(elem_type.into_proto()),
9374            VariadicFunc::MakeAclItem => MakeAclItem(()),
9375            VariadicFunc::MakeMzAclItem => MakeMzAclItem(()),
9376            VariadicFunc::ArrayPosition => ArrayPosition(()),
9377            VariadicFunc::ArrayFill { elem_type } => ArrayFill(elem_type.into_proto()),
9378            VariadicFunc::TimezoneTime => TimezoneTime(()),
9379            VariadicFunc::RegexpSplitToArray => RegexpSplitToArray(()),
9380            VariadicFunc::RegexpReplace => RegexpReplace(()),
9381            VariadicFunc::StringToArray => StringToArray(()),
9382        };
9383        ProtoVariadicFunc { kind: Some(kind) }
9384    }
9385
9386    fn from_proto(proto: ProtoVariadicFunc) -> Result<Self, TryFromProtoError> {
9387        use crate::scalar::proto_variadic_func::Kind::*;
9388        use crate::scalar::proto_variadic_func::ProtoRecordCreate;
9389        if let Some(kind) = proto.kind {
9390            match kind {
9391                Coalesce(()) => Ok(VariadicFunc::Coalesce),
9392                Greatest(()) => Ok(VariadicFunc::Greatest),
9393                Least(()) => Ok(VariadicFunc::Least),
9394                Concat(()) => Ok(VariadicFunc::Concat),
9395                ConcatWs(()) => Ok(VariadicFunc::ConcatWs),
9396                MakeTimestamp(()) => Ok(VariadicFunc::MakeTimestamp),
9397                PadLeading(()) => Ok(VariadicFunc::PadLeading),
9398                Substr(()) => Ok(VariadicFunc::Substr),
9399                Replace(()) => Ok(VariadicFunc::Replace),
9400                Translate(()) => Ok(VariadicFunc::Translate),
9401                JsonbBuildArray(()) => Ok(VariadicFunc::JsonbBuildArray),
9402                JsonbBuildObject(()) => Ok(VariadicFunc::JsonbBuildObject),
9403                MapBuild(value_type) => Ok(VariadicFunc::MapBuild {
9404                    value_type: value_type.into_rust()?,
9405                }),
9406                ArrayCreate(elem_type) => Ok(VariadicFunc::ArrayCreate {
9407                    elem_type: elem_type.into_rust()?,
9408                }),
9409                ArrayToString(elem_type) => Ok(VariadicFunc::ArrayToString {
9410                    elem_type: elem_type.into_rust()?,
9411                }),
9412                ArrayIndex(offset) => Ok(VariadicFunc::ArrayIndex {
9413                    offset: offset.into_rust()?,
9414                }),
9415                ListCreate(elem_type) => Ok(VariadicFunc::ListCreate {
9416                    elem_type: elem_type.into_rust()?,
9417                }),
9418                RecordCreate(ProtoRecordCreate { field_names }) => Ok(VariadicFunc::RecordCreate {
9419                    field_names: field_names.into_rust()?,
9420                }),
9421                ListIndex(()) => Ok(VariadicFunc::ListIndex),
9422                ListSliceLinear(()) => Ok(VariadicFunc::ListSliceLinear),
9423                SplitPart(()) => Ok(VariadicFunc::SplitPart),
9424                RegexpMatch(()) => Ok(VariadicFunc::RegexpMatch),
9425                HmacString(()) => Ok(VariadicFunc::HmacString),
9426                HmacBytes(()) => Ok(VariadicFunc::HmacBytes),
9427                ErrorIfNull(()) => Ok(VariadicFunc::ErrorIfNull),
9428                DateBinTimestamp(()) => Ok(VariadicFunc::DateBinTimestamp),
9429                DateBinTimestampTz(()) => Ok(VariadicFunc::DateBinTimestampTz),
9430                DateDiffTimestamp(()) => Ok(VariadicFunc::DateDiffTimestamp),
9431                DateDiffTimestampTz(()) => Ok(VariadicFunc::DateDiffTimestampTz),
9432                DateDiffDate(()) => Ok(VariadicFunc::DateDiffDate),
9433                DateDiffTime(()) => Ok(VariadicFunc::DateDiffTime),
9434                And(()) => Ok(VariadicFunc::And),
9435                Or(()) => Ok(VariadicFunc::Or),
9436                RangeCreate(elem_type) => Ok(VariadicFunc::RangeCreate {
9437                    elem_type: elem_type.into_rust()?,
9438                }),
9439                MakeAclItem(()) => Ok(VariadicFunc::MakeAclItem),
9440                MakeMzAclItem(()) => Ok(VariadicFunc::MakeMzAclItem),
9441                ArrayPosition(()) => Ok(VariadicFunc::ArrayPosition),
9442                ArrayFill(elem_type) => Ok(VariadicFunc::ArrayFill {
9443                    elem_type: elem_type.into_rust()?,
9444                }),
9445                TimezoneTime(()) => Ok(VariadicFunc::TimezoneTime),
9446                RegexpSplitToArray(()) => Ok(VariadicFunc::RegexpSplitToArray),
9447                RegexpReplace(()) => Ok(VariadicFunc::RegexpReplace),
9448                StringToArray(()) => Ok(VariadicFunc::StringToArray),
9449            }
9450        } else {
9451            Err(TryFromProtoError::missing_field(
9452                "`ProtoVariadicFunc::kind`",
9453            ))
9454        }
9455    }
9456}
9457
9458#[cfg(test)]
9459mod test {
9460    use chrono::prelude::*;
9461    use mz_ore::assert_ok;
9462    use mz_proto::protobuf_roundtrip;
9463    use mz_repr::PropDatum;
9464    use proptest::prelude::*;
9465
9466    use super::*;
9467
9468    #[mz_ore::test]
9469    fn add_interval_months() {
9470        let dt = ym(2000, 1);
9471
9472        assert_eq!(add_timestamp_months(&*dt, 0).unwrap(), dt);
9473        assert_eq!(add_timestamp_months(&*dt, 1).unwrap(), ym(2000, 2));
9474        assert_eq!(add_timestamp_months(&*dt, 12).unwrap(), ym(2001, 1));
9475        assert_eq!(add_timestamp_months(&*dt, 13).unwrap(), ym(2001, 2));
9476        assert_eq!(add_timestamp_months(&*dt, 24).unwrap(), ym(2002, 1));
9477        assert_eq!(add_timestamp_months(&*dt, 30).unwrap(), ym(2002, 7));
9478
9479        // and negatives
9480        assert_eq!(add_timestamp_months(&*dt, -1).unwrap(), ym(1999, 12));
9481        assert_eq!(add_timestamp_months(&*dt, -12).unwrap(), ym(1999, 1));
9482        assert_eq!(add_timestamp_months(&*dt, -13).unwrap(), ym(1998, 12));
9483        assert_eq!(add_timestamp_months(&*dt, -24).unwrap(), ym(1998, 1));
9484        assert_eq!(add_timestamp_months(&*dt, -30).unwrap(), ym(1997, 7));
9485
9486        // and going over a year boundary by less than a year
9487        let dt = ym(1999, 12);
9488        assert_eq!(add_timestamp_months(&*dt, 1).unwrap(), ym(2000, 1));
9489        let end_of_month_dt = NaiveDate::from_ymd_opt(1999, 12, 31)
9490            .unwrap()
9491            .and_hms_opt(9, 9, 9)
9492            .unwrap();
9493        assert_eq!(
9494            // leap year
9495            add_timestamp_months(&end_of_month_dt, 2).unwrap(),
9496            NaiveDate::from_ymd_opt(2000, 2, 29)
9497                .unwrap()
9498                .and_hms_opt(9, 9, 9)
9499                .unwrap()
9500                .try_into()
9501                .unwrap(),
9502        );
9503        assert_eq!(
9504            // not leap year
9505            add_timestamp_months(&end_of_month_dt, 14).unwrap(),
9506            NaiveDate::from_ymd_opt(2001, 2, 28)
9507                .unwrap()
9508                .and_hms_opt(9, 9, 9)
9509                .unwrap()
9510                .try_into()
9511                .unwrap(),
9512        );
9513    }
9514
9515    fn ym(year: i32, month: u32) -> CheckedTimestamp<NaiveDateTime> {
9516        NaiveDate::from_ymd_opt(year, month, 1)
9517            .unwrap()
9518            .and_hms_opt(9, 9, 9)
9519            .unwrap()
9520            .try_into()
9521            .unwrap()
9522    }
9523
9524    proptest! {
9525        #![proptest_config(ProptestConfig::with_cases(4096))]
9526
9527        #[mz_ore::test]
9528        #[cfg_attr(miri, ignore)] // too slow
9529        fn unmaterializable_func_protobuf_roundtrip(expect in any::<UnmaterializableFunc>()) {
9530            let actual = protobuf_roundtrip::<_, ProtoUnmaterializableFunc>(&expect);
9531            assert_ok!(actual);
9532            assert_eq!(actual.unwrap(), expect);
9533        }
9534
9535        #[mz_ore::test]
9536        #[cfg_attr(miri, ignore)] // too slow
9537        fn unary_func_protobuf_roundtrip(expect in any::<UnaryFunc>()) {
9538            let actual = protobuf_roundtrip::<_, ProtoUnaryFunc>(&expect);
9539            assert_ok!(actual);
9540            assert_eq!(actual.unwrap(), expect);
9541        }
9542
9543        #[mz_ore::test]
9544        #[cfg_attr(miri, ignore)] // too slow
9545        fn binary_func_protobuf_roundtrip(expect in any::<BinaryFunc>()) {
9546            let actual = protobuf_roundtrip::<_, ProtoBinaryFunc>(&expect);
9547            assert_ok!(actual);
9548            assert_eq!(actual.unwrap(), expect);
9549        }
9550
9551        #[mz_ore::test]
9552        #[cfg_attr(miri, ignore)] // too slow
9553        fn variadic_func_protobuf_roundtrip(expect in any::<VariadicFunc>()) {
9554            let actual = protobuf_roundtrip::<_, ProtoVariadicFunc>(&expect);
9555            assert_ok!(actual);
9556            assert_eq!(actual.unwrap(), expect);
9557        }
9558    }
9559
9560    #[mz_ore::test]
9561    fn test_could_error() {
9562        for func in [
9563            UnaryFunc::IsNull(IsNull),
9564            UnaryFunc::CastVarCharToString(CastVarCharToString),
9565            UnaryFunc::Not(Not),
9566            UnaryFunc::IsLikeMatch(IsLikeMatch(like_pattern::compile("%hi%", false).unwrap())),
9567        ] {
9568            assert!(!func.could_error())
9569        }
9570    }
9571
9572    #[mz_ore::test]
9573    #[cfg_attr(miri, ignore)] // unsupported operation: can't call foreign function `decNumberFromInt32` on OS `linux`
9574    fn test_is_monotone() {
9575        use proptest::prelude::*;
9576
9577        /// Asserts that the function is either monotonically increasing or decreasing over
9578        /// the given sets of arguments.
9579        fn assert_monotone<'a, const N: usize>(
9580            expr: &MirScalarExpr,
9581            arena: &'a RowArena,
9582            datums: &[[Datum<'a>; N]],
9583        ) {
9584            // TODO: assertions for nulls, errors
9585            let Ok(results) = datums
9586                .iter()
9587                .map(|args| expr.eval(args.as_slice(), arena))
9588                .collect::<Result<Vec<_>, _>>()
9589            else {
9590                return;
9591            };
9592
9593            let forward = results.iter().tuple_windows().all(|(a, b)| a <= b);
9594            let reverse = results.iter().tuple_windows().all(|(a, b)| a >= b);
9595            assert!(
9596                forward || reverse,
9597                "expected {expr} to be monotone, but passing {datums:?} returned {results:?}"
9598            );
9599        }
9600
9601        fn proptest_unary<'a>(
9602            func: UnaryFunc,
9603            arena: &'a RowArena,
9604            arg: impl Strategy<Value = PropDatum>,
9605        ) {
9606            let is_monotone = func.is_monotone();
9607            let expr = MirScalarExpr::CallUnary {
9608                func,
9609                expr: Box::new(MirScalarExpr::Column(0)),
9610            };
9611            if is_monotone {
9612                proptest!(|(
9613                    mut arg in proptest::array::uniform3(arg),
9614                )| {
9615                    arg.sort();
9616                    let args: Vec<_> = arg.iter().map(|a| [Datum::from(a)]).collect();
9617                    assert_monotone(&expr, arena, &args);
9618                });
9619            }
9620        }
9621
9622        fn proptest_binary<'a>(
9623            func: BinaryFunc,
9624            arena: &'a RowArena,
9625            left: impl Strategy<Value = PropDatum>,
9626            right: impl Strategy<Value = PropDatum>,
9627        ) {
9628            let (left_monotone, right_monotone) = func.is_monotone();
9629            let expr = MirScalarExpr::CallBinary {
9630                func,
9631                expr1: Box::new(MirScalarExpr::Column(0)),
9632                expr2: Box::new(MirScalarExpr::Column(1)),
9633            };
9634            proptest!(|(
9635                mut left in proptest::array::uniform3(left),
9636                mut right in proptest::array::uniform3(right),
9637            )| {
9638                left.sort();
9639                right.sort();
9640                if left_monotone {
9641                    for r in &right {
9642                        let args: Vec<[_; 2]> = left
9643                            .iter()
9644                            .map(|l| [Datum::from(l), Datum::from(r)])
9645                            .collect();
9646                        assert_monotone(&expr, arena, &args);
9647                    }
9648                }
9649                if right_monotone {
9650                    for l in &left {
9651                        let args: Vec<[_; 2]> = right
9652                            .iter()
9653                            .map(|r| [Datum::from(l), Datum::from(r)])
9654                            .collect();
9655                        assert_monotone(&expr, arena, &args);
9656                    }
9657                }
9658            });
9659        }
9660
9661        let interesting_strs: Vec<_> = ScalarType::String.interesting_datums().collect();
9662        let str_datums = proptest::strategy::Union::new([
9663            proptest::string::string_regex("[A-Z]{0,10}")
9664                .expect("valid regex")
9665                .prop_map(|s| PropDatum::String(s.to_string()))
9666                .boxed(),
9667            (0..interesting_strs.len())
9668                .prop_map(move |i| {
9669                    let Datum::String(val) = interesting_strs[i] else {
9670                        unreachable!("interesting strings has non-strings")
9671                    };
9672                    PropDatum::String(val.to_string())
9673                })
9674                .boxed(),
9675        ]);
9676
9677        let interesting_i32s: Vec<Datum<'static>> =
9678            ScalarType::Int32.interesting_datums().collect();
9679        let i32_datums = proptest::strategy::Union::new([
9680            any::<i32>().prop_map(PropDatum::Int32).boxed(),
9681            (0..interesting_i32s.len())
9682                .prop_map(move |i| {
9683                    let Datum::Int32(val) = interesting_i32s[i] else {
9684                        unreachable!("interesting int32 has non-i32s")
9685                    };
9686                    PropDatum::Int32(val)
9687                })
9688                .boxed(),
9689            (-10i32..10).prop_map(PropDatum::Int32).boxed(),
9690        ]);
9691
9692        let arena = RowArena::new();
9693
9694        // It would be interesting to test all funcs here, but we currently need to hardcode
9695        // the generators for the argument types, which makes this tedious. Choose an interesting
9696        // subset for now.
9697        proptest_unary(
9698            UnaryFunc::CastInt32ToNumeric(CastInt32ToNumeric(None)),
9699            &arena,
9700            &i32_datums,
9701        );
9702        proptest_unary(
9703            UnaryFunc::CastInt32ToUint16(CastInt32ToUint16),
9704            &arena,
9705            &i32_datums,
9706        );
9707        proptest_unary(
9708            UnaryFunc::CastInt32ToString(CastInt32ToString),
9709            &arena,
9710            &i32_datums,
9711        );
9712        proptest_binary(BinaryFunc::AddInt32, &arena, &i32_datums, &i32_datums);
9713        proptest_binary(BinaryFunc::SubInt32, &arena, &i32_datums, &i32_datums);
9714        proptest_binary(BinaryFunc::MulInt32, &arena, &i32_datums, &i32_datums);
9715        proptest_binary(BinaryFunc::DivInt32, &arena, &i32_datums, &i32_datums);
9716        proptest_binary(BinaryFunc::TextConcat, &arena, &str_datums, &str_datums);
9717        proptest_binary(BinaryFunc::Left, &arena, &str_datums, &i32_datums);
9718    }
9719}