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