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