1use std::cell::RefCell;
14use std::collections::BTreeMap;
15use std::fmt;
16use std::sync::LazyLock;
17
18use itertools::Itertools;
19use mz_expr::func;
20use mz_expr::func::variadic;
21use mz_ore::collections::CollectionExt;
22use mz_ore::str::StrExt;
23use mz_pgrepr::oid;
24use mz_repr::role_id::RoleId;
25use mz_repr::{ColumnName, Datum, SqlRelationType, SqlScalarBaseType, SqlScalarType};
26
27use crate::ast::{SelectStatement, Statement};
28use crate::catalog::{CatalogType, TypeCategory, TypeReference};
29use crate::names::{self, ResolvedItemName};
30use crate::plan::error::PlanError;
31use crate::plan::hir::{
32 AggregateFunc, BinaryFunc, CoercibleScalarExpr, CoercibleScalarType, ColumnOrder,
33 HirRelationExpr, HirScalarExpr, ScalarWindowFunc, TableFunc, UnaryFunc, UnmaterializableFunc,
34 ValueWindowFunc, VariadicFunc,
35};
36use crate::plan::query::{self, ExprContext, QueryContext};
37use crate::plan::scope::Scope;
38use crate::plan::side_effecting_func::PG_CATALOG_SEF_BUILTINS;
39use crate::plan::transform_ast;
40use crate::plan::typeconv::{self, CastContext};
41use crate::session::vars::{self, ENABLE_TIME_AT_TIME_ZONE};
42
43#[derive(Clone, Copy, Debug)]
45pub enum FuncSpec<'a> {
46 Func(&'a ResolvedItemName),
48 Op(&'a str),
50}
51
52impl<'a> fmt::Display for FuncSpec<'a> {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 match self {
55 FuncSpec::Func(n) => n.fmt(f),
56 FuncSpec::Op(o) => o.fmt(f),
57 }
58 }
59}
60
61impl TypeCategory {
62 pub fn from_type(typ: &SqlScalarType) -> Self {
74 match typ {
76 SqlScalarType::Array(..) | SqlScalarType::Int2Vector => Self::Array,
77 SqlScalarType::Bool => Self::Boolean,
78 SqlScalarType::AclItem
79 | SqlScalarType::Bytes
80 | SqlScalarType::Jsonb
81 | SqlScalarType::Uuid
82 | SqlScalarType::MzAclItem => Self::UserDefined,
83 SqlScalarType::Date
84 | SqlScalarType::Time
85 | SqlScalarType::Timestamp { .. }
86 | SqlScalarType::TimestampTz { .. } => Self::DateTime,
87 SqlScalarType::Float32
88 | SqlScalarType::Float64
89 | SqlScalarType::Int16
90 | SqlScalarType::Int32
91 | SqlScalarType::Int64
92 | SqlScalarType::UInt16
93 | SqlScalarType::UInt32
94 | SqlScalarType::UInt64
95 | SqlScalarType::Oid
96 | SqlScalarType::RegClass
97 | SqlScalarType::RegProc
98 | SqlScalarType::RegType
99 | SqlScalarType::Numeric { .. } => Self::Numeric,
100 SqlScalarType::Interval => Self::Timespan,
101 SqlScalarType::List { .. } => Self::List,
102 SqlScalarType::PgLegacyChar
103 | SqlScalarType::PgLegacyName
104 | SqlScalarType::String
105 | SqlScalarType::Char { .. }
106 | SqlScalarType::VarChar { .. } => Self::String,
107 SqlScalarType::Record { custom_id, .. } => {
108 if custom_id.is_some() {
109 Self::Composite
110 } else {
111 Self::Pseudo
112 }
113 }
114 SqlScalarType::Map { .. } => Self::Pseudo,
115 SqlScalarType::MzTimestamp => Self::Numeric,
116 SqlScalarType::Range { .. } => Self::Range,
117 }
118 }
119
120 pub fn from_param(param: &ParamType) -> Self {
121 match param {
122 ParamType::Any
123 | ParamType::AnyElement
124 | ParamType::ArrayAny
125 | ParamType::ArrayAnyCompatible
126 | ParamType::AnyCompatible
127 | ParamType::ListAny
128 | ParamType::ListAnyCompatible
129 | ParamType::ListElementAnyCompatible
130 | ParamType::Internal
131 | ParamType::NonVecAny
132 | ParamType::NonVecAnyCompatible
133 | ParamType::MapAny
134 | ParamType::MapAnyCompatible
135 | ParamType::RecordAny => Self::Pseudo,
136 ParamType::RangeAnyCompatible | ParamType::RangeAny => Self::Range,
137 ParamType::Plain(t) => Self::from_type(t),
138 }
139 }
140
141 pub fn from_catalog_type<T>(catalog_type: &CatalogType<T>) -> Self
145 where
146 T: TypeReference,
147 {
148 match catalog_type {
150 CatalogType::Array { .. } | CatalogType::Int2Vector => Self::Array,
151 CatalogType::Bool => Self::Boolean,
152 CatalogType::AclItem
153 | CatalogType::Bytes
154 | CatalogType::Jsonb
155 | CatalogType::Uuid
156 | CatalogType::MzAclItem => Self::UserDefined,
157 CatalogType::Date
158 | CatalogType::Time
159 | CatalogType::Timestamp
160 | CatalogType::TimestampTz => Self::DateTime,
161 CatalogType::Float32
162 | CatalogType::Float64
163 | CatalogType::Int16
164 | CatalogType::Int32
165 | CatalogType::Int64
166 | CatalogType::UInt16
167 | CatalogType::UInt32
168 | CatalogType::UInt64
169 | CatalogType::Oid
170 | CatalogType::RegClass
171 | CatalogType::RegProc
172 | CatalogType::RegType
173 | CatalogType::Numeric { .. } => Self::Numeric,
174 CatalogType::Interval => Self::Timespan,
175 CatalogType::List { .. } => Self::List,
176 CatalogType::PgLegacyChar
177 | CatalogType::PgLegacyName
178 | CatalogType::String
179 | CatalogType::Char { .. }
180 | CatalogType::VarChar { .. } => Self::String,
181 CatalogType::Record { .. } => TypeCategory::Composite,
182 CatalogType::Map { .. } | CatalogType::Pseudo => Self::Pseudo,
183 CatalogType::MzTimestamp => Self::String,
184 CatalogType::Range { .. } => Self::Range,
185 }
186 }
187
188 pub fn preferred_type(&self) -> Option<SqlScalarType> {
196 match self {
197 Self::Array
198 | Self::BitString
199 | Self::Composite
200 | Self::Enum
201 | Self::Geometric
202 | Self::List
203 | Self::NetworkAddress
204 | Self::Pseudo
205 | Self::Range
206 | Self::Unknown
207 | Self::UserDefined => None,
208 Self::Boolean => Some(SqlScalarType::Bool),
209 Self::DateTime => Some(SqlScalarType::TimestampTz { precision: None }),
210 Self::Numeric => Some(SqlScalarType::Float64),
211 Self::String => Some(SqlScalarType::String),
212 Self::Timespan => Some(SqlScalarType::Interval),
213 }
214 }
215}
216
217pub struct Operation<R>(
220 pub Box<
221 dyn Fn(
222 &ExprContext,
223 Vec<CoercibleScalarExpr>,
224 &ParamList,
225 Vec<ColumnOrder>,
226 ) -> Result<R, PlanError>
227 + Send
228 + Sync,
229 >,
230);
231
232impl<R> fmt::Debug for Operation<R> {
233 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
234 f.debug_struct("Operation").finish()
235 }
236}
237
238impl Operation<HirScalarExpr> {
239 fn identity() -> Operation<HirScalarExpr> {
241 Operation::unary(|_ecx, e| Ok(e))
242 }
243}
244
245impl<R> Operation<R> {
246 fn new<F>(f: F) -> Operation<R>
247 where
248 F: Fn(
249 &ExprContext,
250 Vec<CoercibleScalarExpr>,
251 &ParamList,
252 Vec<ColumnOrder>,
253 ) -> Result<R, PlanError>
254 + Send
255 + Sync
256 + 'static,
257 {
258 Operation(Box::new(f))
259 }
260
261 fn nullary<F>(f: F) -> Operation<R>
263 where
264 F: Fn(&ExprContext) -> Result<R, PlanError> + Send + Sync + 'static,
265 {
266 Self::variadic(move |ecx, exprs| {
267 assert!(exprs.is_empty());
268 f(ecx)
269 })
270 }
271
272 fn unary<F>(f: F) -> Operation<R>
274 where
275 F: Fn(&ExprContext, HirScalarExpr) -> Result<R, PlanError> + Send + Sync + 'static,
276 {
277 Self::variadic(move |ecx, exprs| f(ecx, exprs.into_element()))
278 }
279
280 fn unary_ordered<F>(f: F) -> Operation<R>
282 where
283 F: Fn(&ExprContext, HirScalarExpr, Vec<ColumnOrder>) -> Result<R, PlanError>
284 + Send
285 + Sync
286 + 'static,
287 {
288 Self::new(move |ecx, cexprs, params, order_by| {
289 let exprs = coerce_args_to_types(ecx, cexprs, params)?;
290 f(ecx, exprs.into_element(), order_by)
291 })
292 }
293
294 fn binary<F>(f: F) -> Operation<R>
296 where
297 F: Fn(&ExprContext, HirScalarExpr, HirScalarExpr) -> Result<R, PlanError>
298 + Send
299 + Sync
300 + 'static,
301 {
302 Self::variadic(move |ecx, exprs| {
303 assert_eq!(exprs.len(), 2);
304 let mut exprs = exprs.into_iter();
305 let left = exprs.next().unwrap();
306 let right = exprs.next().unwrap();
307 f(ecx, left, right)
308 })
309 }
310
311 fn binary_ordered<F>(f: F) -> Operation<R>
316 where
317 F: Fn(&ExprContext, HirScalarExpr, HirScalarExpr, Vec<ColumnOrder>) -> Result<R, PlanError>
318 + Send
319 + Sync
320 + 'static,
321 {
322 Self::new(move |ecx, cexprs, params, order_by| {
323 let exprs = coerce_args_to_types(ecx, cexprs, params)?;
324 assert_eq!(exprs.len(), 2);
325 let mut exprs = exprs.into_iter();
326 let left = exprs.next().unwrap();
327 let right = exprs.next().unwrap();
328 f(ecx, left, right, order_by)
329 })
330 }
331
332 fn variadic<F>(f: F) -> Operation<R>
334 where
335 F: Fn(&ExprContext, Vec<HirScalarExpr>) -> Result<R, PlanError> + Send + Sync + 'static,
336 {
337 Self::new(move |ecx, cexprs, params, _order_by| {
338 let exprs = coerce_args_to_types(ecx, cexprs, params)?;
339 f(ecx, exprs)
340 })
341 }
342}
343
344pub fn sql_impl(
347 expr: &str,
348) -> impl Fn(&ExprContext, Vec<SqlScalarType>) -> Result<HirScalarExpr, PlanError> + use<> {
349 let expr = mz_sql_parser::parser::parse_expr(expr).unwrap_or_else(|e| {
350 panic!(
351 "static function definition failed to parse {}: {}",
352 expr.quoted(),
353 e,
354 )
355 });
356 move |ecx, types| {
357 let mut scx = ecx.qcx.scx.clone();
360 scx.param_types = RefCell::new(
361 types
362 .into_iter()
363 .enumerate()
364 .map(|(i, ty)| (i + 1, ty))
365 .collect(),
366 );
367 let qcx = QueryContext::root(&scx, ecx.qcx.lifetime);
368
369 let (mut expr, new_ids) = names::resolve(qcx.scx.catalog, expr.clone())?;
370 scx.sql_impl_resolved_ids
371 .lock()
372 .expect("planning is single-threaded")
373 .extend_from(&new_ids);
374 transform_ast::transform(&scx, &mut expr)?;
376
377 let ecx_name = format!(
378 "static function definition (or its outer context '{}')",
379 ecx.name
380 );
381 let ecx = ExprContext {
382 qcx: &qcx,
383 name: ecx_name.as_str(),
384 scope: &Scope::empty(),
385 relation_type: &SqlRelationType::empty(),
386 allow_aggregates: false,
393 allow_subqueries: ecx.allow_subqueries,
394 allow_parameters: true,
395 allow_windows: false,
396 };
397
398 query::plan_expr(&ecx, &expr)?.type_as_any(&ecx)
400 }
401}
402
403fn sql_impl_func(expr: &str) -> Operation<HirScalarExpr> {
417 let invoke = sql_impl(expr);
418 Operation::variadic(move |ecx, args| {
419 let types = args.iter().map(|arg| ecx.scalar_type(arg)).collect();
420 let mut out = invoke(ecx, types)?;
421 out.splice_parameters(&args, 0);
422 Ok(out)
423 })
424}
425
426fn sql_impl_table_func_inner(
439 sql: &'static str,
440 feature_flag: Option<&'static vars::FeatureFlag>,
441) -> Operation<TableFuncPlan> {
442 let query = match mz_sql_parser::parser::parse_statements(sql)
443 .expect("static function definition failed to parse")
444 .expect_element(|| "static function definition must have exactly one statement")
445 .ast
446 {
447 Statement::Select(SelectStatement { query, as_of: None }) => query,
448 _ => panic!("static function definition expected SELECT statement"),
449 };
450 let invoke = move |qcx: &QueryContext, types: Vec<SqlScalarType>| {
451 let mut scx = qcx.scx.clone();
454 scx.param_types = RefCell::new(
455 types
456 .into_iter()
457 .enumerate()
458 .map(|(i, ty)| (i + 1, ty))
459 .collect(),
460 );
461 let mut qcx = QueryContext::root(&scx, qcx.lifetime);
462
463 let query = query.clone();
464 let (mut query, new_ids) = names::resolve(qcx.scx.catalog, query)?;
465 scx.sql_impl_resolved_ids
466 .lock()
467 .expect("planning is single-threaded")
468 .extend_from(&new_ids);
469 transform_ast::transform(&scx, &mut query)?;
470
471 query::plan_nested_query(&mut qcx, &query)
472 };
473
474 Operation::variadic(move |ecx, args| {
475 if let Some(feature_flag) = feature_flag {
476 ecx.require_feature_flag(feature_flag)?;
477 }
478 let types = args.iter().map(|arg| ecx.scalar_type(arg)).collect();
479 let (mut expr, scope) = invoke(ecx.qcx, types)?;
480 expr.splice_parameters(&args, 0);
481 Ok(TableFuncPlan {
482 imp: TableFuncImpl::Expr(expr),
483 column_names: scope.column_names().cloned().collect(),
484 })
485 })
486}
487
488fn sql_impl_table_func(sql: &'static str) -> Operation<TableFuncPlan> {
493 sql_impl_table_func_inner(sql, None)
494}
495
496fn experimental_sql_impl_table_func(
497 feature: &'static vars::FeatureFlag,
498 sql: &'static str,
499) -> Operation<TableFuncPlan> {
500 sql_impl_table_func_inner(sql, Some(feature))
501}
502
503pub struct FuncImpl<R> {
505 pub oid: u32,
506 pub params: ParamList,
507 pub return_type: ReturnType,
508 pub op: Operation<R>,
509}
510
511#[derive(Debug)]
513pub struct FuncImplCatalogDetails {
514 pub oid: u32,
515 pub arg_typs: Vec<&'static str>,
516 pub variadic_typ: Option<&'static str>,
517 pub return_typ: Option<&'static str>,
518 pub return_is_set: bool,
519}
520
521impl<R> FuncImpl<R> {
522 pub fn details(&self) -> FuncImplCatalogDetails {
523 FuncImplCatalogDetails {
524 oid: self.oid,
525 arg_typs: self.params.arg_names(),
526 variadic_typ: self.params.variadic_name(),
527 return_typ: self.return_type.typ.as_ref().map(|t| t.name()),
528 return_is_set: self.return_type.is_set_of,
529 }
530 }
531}
532
533impl<R> fmt::Debug for FuncImpl<R> {
534 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
535 f.debug_struct("FuncImpl")
536 .field("oid", &self.oid)
537 .field("params", &self.params)
538 .field("ret", &self.return_type)
539 .field("op", &"<omitted>")
540 .finish()
541 }
542}
543
544impl From<UnmaterializableFunc> for Operation<HirScalarExpr> {
545 fn from(n: UnmaterializableFunc) -> Operation<HirScalarExpr> {
546 Operation::nullary(move |_ecx| Ok(HirScalarExpr::call_unmaterializable(n.clone())))
547 }
548}
549
550impl From<UnaryFunc> for Operation<HirScalarExpr> {
551 fn from(u: UnaryFunc) -> Operation<HirScalarExpr> {
552 Operation::unary(move |_ecx, e| Ok(e.call_unary(u.clone())))
553 }
554}
555
556impl From<BinaryFunc> for Operation<HirScalarExpr> {
557 fn from(b: BinaryFunc) -> Operation<HirScalarExpr> {
558 Operation::binary(move |_ecx, left, right| Ok(left.call_binary(right, b.clone())))
559 }
560}
561
562impl From<VariadicFunc> for Operation<HirScalarExpr> {
563 fn from(v: VariadicFunc) -> Operation<HirScalarExpr> {
564 Operation::variadic(move |_ecx, exprs| Ok(HirScalarExpr::call_variadic(v.clone(), exprs)))
565 }
566}
567
568impl From<AggregateFunc> for Operation<(HirScalarExpr, AggregateFunc)> {
569 fn from(a: AggregateFunc) -> Operation<(HirScalarExpr, AggregateFunc)> {
570 Operation::unary(move |_ecx, e| Ok((e, a.clone())))
571 }
572}
573
574impl From<ScalarWindowFunc> for Operation<ScalarWindowFunc> {
575 fn from(a: ScalarWindowFunc) -> Operation<ScalarWindowFunc> {
576 Operation::nullary(move |_ecx| Ok(a.clone()))
577 }
578}
579
580impl From<ValueWindowFunc> for Operation<(HirScalarExpr, ValueWindowFunc)> {
581 fn from(a: ValueWindowFunc) -> Operation<(HirScalarExpr, ValueWindowFunc)> {
582 Operation::unary(move |_ecx, e| Ok((e, a.clone())))
583 }
584}
585
586#[derive(Debug, Clone, Eq, PartialEq, Hash)]
587pub enum ParamList {
591 Exact(Vec<ParamType>),
592 Variadic {
593 leading: Vec<ParamType>,
594 trailing: ParamType,
595 },
596}
597
598impl ParamList {
599 fn matches_argtypes(&self, ecx: &ExprContext, typs: &[CoercibleScalarType]) -> bool {
601 if !self.validate_arg_len(typs.len()) {
602 return false;
603 }
604
605 for (i, typ) in typs.iter().enumerate() {
606 let param = &self[i];
607 if let CoercibleScalarType::Coerced(typ) = typ {
608 if !param.accepts_type(ecx, typ) {
615 return false;
616 }
617 }
618 }
619
620 PolymorphicSolution::new(ecx, typs, self).is_some()
623 }
624
625 fn validate_arg_len(&self, input_len: usize) -> bool {
627 match self {
628 Self::Exact(p) => p.len() == input_len,
629 Self::Variadic { leading, .. } => input_len > leading.len(),
630 }
631 }
632
633 fn exact_match(&self, types: &[&SqlScalarType]) -> bool {
636 types.iter().enumerate().all(|(i, t)| self[i] == **t)
637 }
638
639 fn arg_names(&self) -> Vec<&'static str> {
641 match self {
642 ParamList::Exact(p) => p.iter().map(|p| p.name()).collect::<Vec<_>>(),
643 ParamList::Variadic { leading, trailing } => leading
644 .iter()
645 .chain([trailing])
646 .map(|p| p.name())
647 .collect::<Vec<_>>(),
648 }
649 }
650
651 fn variadic_name(&self) -> Option<&'static str> {
653 match self {
654 ParamList::Exact(_) => None,
655 ParamList::Variadic { trailing, .. } => Some(trailing.name()),
656 }
657 }
658}
659
660impl std::ops::Index<usize> for ParamList {
661 type Output = ParamType;
662
663 fn index(&self, i: usize) -> &Self::Output {
664 match self {
665 Self::Exact(p) => &p[i],
666 Self::Variadic { leading, trailing } => leading.get(i).unwrap_or(trailing),
667 }
668 }
669}
670
671impl From<Vec<ParamType>> for ParamList {
673 fn from(p: Vec<ParamType>) -> ParamList {
674 ParamList::Exact(p)
675 }
676}
677
678#[derive(Debug, Clone, Eq, PartialEq, Hash)]
679pub enum ParamType {
692 Any,
695 AnyCompatible,
698 AnyElement,
701 ArrayAny,
704 ArrayAnyCompatible,
707 ListAny,
710 ListAnyCompatible,
713 ListElementAnyCompatible,
718 MapAny,
721 MapAnyCompatible,
724 NonVecAny,
728 NonVecAnyCompatible,
732 Plain(SqlScalarType),
735 RecordAny,
738 RangeAny,
741 RangeAnyCompatible,
748 Internal,
751}
752
753impl ParamType {
754 fn accepts_type(&self, ecx: &ExprContext, t: &SqlScalarType) -> bool {
756 use ParamType::*;
757 use SqlScalarType::*;
758
759 match self {
760 Any | AnyElement | AnyCompatible | ListElementAnyCompatible => true,
761 ArrayAny | ArrayAnyCompatible => matches!(t, Array(..) | Int2Vector),
762 ListAny | ListAnyCompatible => matches!(t, List { .. }),
763 MapAny | MapAnyCompatible => matches!(t, Map { .. }),
764 RangeAny | RangeAnyCompatible => matches!(t, Range { .. }),
765 NonVecAny | NonVecAnyCompatible => !t.is_vec(),
766 Internal => false,
767 Plain(to) => typeconv::can_cast(ecx, CastContext::Implicit, t, to),
768 RecordAny => matches!(t, Record { .. }),
769 }
770 }
771
772 fn is_preferred_by(&self, t: &SqlScalarType) -> bool {
775 if let Some(pt) = TypeCategory::from_type(t).preferred_type() {
776 *self == pt
777 } else {
778 false
779 }
780 }
781
782 fn is_near_match(&self, t: &SqlScalarType) -> bool {
786 match (self, t.near_match()) {
787 (ParamType::Plain(t), Some(near_match)) => t.structural_eq(near_match),
788 _ => false,
789 }
790 }
791
792 fn prefers_self(&self) -> bool {
794 if let Some(pt) = TypeCategory::from_param(self).preferred_type() {
795 *self == pt
796 } else {
797 false
798 }
799 }
800
801 fn is_polymorphic(&self) -> bool {
802 use ParamType::*;
803 match self {
804 AnyElement
805 | ArrayAny
806 | ArrayAnyCompatible
807 | AnyCompatible
808 | ListAny
809 | ListAnyCompatible
810 | ListElementAnyCompatible
811 | MapAny
812 | MapAnyCompatible
813 | NonVecAny
814 | NonVecAnyCompatible
815 | RecordAny
819 | RangeAny
820 | RangeAnyCompatible => true,
821 Any | Internal | Plain(_) => false,
822 }
823 }
824
825 fn name(&self) -> &'static str {
826 match self {
827 ParamType::Plain(t) => {
828 assert!(
829 !t.is_custom_type(),
830 "custom types cannot currently be used as \
831 parameters; use a polymorphic parameter that \
832 accepts the custom type instead"
833 );
834 let t: mz_pgrepr::Type = t.into();
835 t.catalog_name()
836 }
837 ParamType::Any => "any",
838 ParamType::AnyCompatible => "anycompatible",
839 ParamType::AnyElement => "anyelement",
840 ParamType::ArrayAny => "anyarray",
841 ParamType::ArrayAnyCompatible => "anycompatiblearray",
842 ParamType::Internal => "internal",
843 ParamType::ListAny => "list",
844 ParamType::ListAnyCompatible => "anycompatiblelist",
845 ParamType::ListElementAnyCompatible => "anycompatible",
848 ParamType::MapAny => "map",
849 ParamType::MapAnyCompatible => "anycompatiblemap",
850 ParamType::NonVecAny => "anynonarray",
851 ParamType::NonVecAnyCompatible => "anycompatiblenonarray",
852 ParamType::RecordAny => "record",
853 ParamType::RangeAny => "anyrange",
854 ParamType::RangeAnyCompatible => "anycompatiblerange",
855 }
856 }
857}
858
859impl PartialEq<SqlScalarType> for ParamType {
860 fn eq(&self, other: &SqlScalarType) -> bool {
861 match self {
862 ParamType::Plain(s) => s.base_eq(other),
863 _ => false,
865 }
866 }
867}
868
869impl PartialEq<ParamType> for SqlScalarType {
870 fn eq(&self, other: &ParamType) -> bool {
871 other == self
872 }
873}
874
875impl From<SqlScalarType> for ParamType {
876 fn from(s: SqlScalarType) -> ParamType {
877 ParamType::Plain(s)
878 }
879}
880
881impl From<SqlScalarBaseType> for ParamType {
882 fn from(s: SqlScalarBaseType) -> ParamType {
883 use SqlScalarBaseType::*;
884 let s = match s {
885 Array | List | Map | Record | Range => {
886 panic!("use polymorphic parameters rather than {:?}", s);
887 }
888 AclItem => SqlScalarType::AclItem,
889 Bool => SqlScalarType::Bool,
890 Int16 => SqlScalarType::Int16,
891 Int32 => SqlScalarType::Int32,
892 Int64 => SqlScalarType::Int64,
893 UInt16 => SqlScalarType::UInt16,
894 UInt32 => SqlScalarType::UInt32,
895 UInt64 => SqlScalarType::UInt64,
896 Float32 => SqlScalarType::Float32,
897 Float64 => SqlScalarType::Float64,
898 Numeric => SqlScalarType::Numeric { max_scale: None },
899 Date => SqlScalarType::Date,
900 Time => SqlScalarType::Time,
901 Timestamp => SqlScalarType::Timestamp { precision: None },
902 TimestampTz => SqlScalarType::TimestampTz { precision: None },
903 Interval => SqlScalarType::Interval,
904 Bytes => SqlScalarType::Bytes,
905 String => SqlScalarType::String,
906 Char => SqlScalarType::Char { length: None },
907 VarChar => SqlScalarType::VarChar { max_length: None },
908 PgLegacyChar => SqlScalarType::PgLegacyChar,
909 PgLegacyName => SqlScalarType::PgLegacyName,
910 Jsonb => SqlScalarType::Jsonb,
911 Uuid => SqlScalarType::Uuid,
912 Oid => SqlScalarType::Oid,
913 RegClass => SqlScalarType::RegClass,
914 RegProc => SqlScalarType::RegProc,
915 RegType => SqlScalarType::RegType,
916 Int2Vector => SqlScalarType::Int2Vector,
917 MzTimestamp => SqlScalarType::MzTimestamp,
918 MzAclItem => SqlScalarType::MzAclItem,
919 };
920 ParamType::Plain(s)
921 }
922}
923
924#[derive(Debug, Clone, Eq, PartialEq, Hash)]
925pub struct ReturnType {
926 pub typ: Option<ParamType>,
927 pub is_set_of: bool,
928}
929
930impl ReturnType {
931 fn scalar(typ: ParamType) -> ReturnType {
933 ReturnType {
934 typ: Some(typ),
935 is_set_of: false,
936 }
937 }
938
939 fn set_of(typ: ParamType) -> ReturnType {
942 ReturnType {
943 typ: Some(typ),
944 is_set_of: true,
945 }
946 }
947
948 fn none(is_set_of: bool) -> ReturnType {
950 ReturnType {
951 typ: None,
952 is_set_of,
953 }
954 }
955}
956
957impl From<ParamType> for ReturnType {
958 fn from(typ: ParamType) -> ReturnType {
959 ReturnType::scalar(typ)
960 }
961}
962
963impl From<SqlScalarBaseType> for ReturnType {
964 fn from(s: SqlScalarBaseType) -> ReturnType {
965 ParamType::from(s).into()
966 }
967}
968
969impl From<SqlScalarType> for ReturnType {
970 fn from(s: SqlScalarType) -> ReturnType {
971 ParamType::Plain(s).into()
972 }
973}
974
975#[derive(Clone, Debug)]
976pub struct Candidate<'a, R> {
978 fimpl: &'a FuncImpl<R>,
980 exact_matches: usize,
981 preferred_types: usize,
982 near_matches: usize,
983}
984
985pub fn select_impl<R>(
999 ecx: &ExprContext,
1000 spec: FuncSpec,
1001 impls: &[FuncImpl<R>],
1002 args: Vec<CoercibleScalarExpr>,
1003 order_by: Vec<ColumnOrder>,
1004) -> Result<R, PlanError>
1005where
1006 R: fmt::Debug,
1007{
1008 let name = spec.to_string();
1009 let ecx = &ecx.with_name(&name);
1010 let mut types: Vec<_> = args.iter().map(|e| ecx.scalar_type(e)).collect();
1011
1012 for ty in &mut types {
1018 ty.force_coerced_if_record();
1019 }
1020
1021 let impls: Vec<_> = impls
1026 .iter()
1027 .filter(|i| i.params.matches_argtypes(ecx, &types))
1028 .collect();
1029
1030 let f = find_match(ecx, &types, impls).map_err(|candidates| {
1031 let arg_types: Vec<_> = types
1032 .into_iter()
1033 .map(|ty| match ty {
1034 CoercibleScalarType::Coerced(ty) => ecx.humanize_sql_scalar_type(&ty, false),
1036 CoercibleScalarType::Record(_) => "record".to_string(),
1037 CoercibleScalarType::Uncoerced => "unknown".to_string(),
1038 })
1039 .collect();
1040
1041 if candidates == 0 {
1042 match spec {
1043 FuncSpec::Func(name) => PlanError::UnknownFunction {
1044 name: ecx
1045 .qcx
1046 .scx
1047 .humanize_resolved_name(name)
1048 .expect("resolved to object")
1049 .to_string(),
1050 arg_types,
1051 },
1052 FuncSpec::Op(name) => PlanError::UnknownOperator {
1053 name: name.to_string(),
1054 arg_types,
1055 },
1056 }
1057 } else {
1058 match spec {
1059 FuncSpec::Func(name) => PlanError::IndistinctFunction {
1060 name: ecx
1061 .qcx
1062 .scx
1063 .humanize_resolved_name(name)
1064 .expect("resolved to object")
1065 .to_string(),
1066 arg_types,
1067 },
1068 FuncSpec::Op(name) => PlanError::IndistinctOperator {
1069 name: name.to_string(),
1070 arg_types,
1071 },
1072 }
1073 }
1074 })?;
1075
1076 (f.op.0)(ecx, args, &f.params, order_by)
1077}
1078
1079fn find_match<'a, R: std::fmt::Debug>(
1085 ecx: &ExprContext,
1086 types: &[CoercibleScalarType],
1087 impls: Vec<&'a FuncImpl<R>>,
1088) -> Result<&'a FuncImpl<R>, usize> {
1089 let all_types_known = types.iter().all(|t| t.is_coerced());
1090
1091 if all_types_known {
1093 let known_types: Vec<_> = types.iter().filter_map(|t| t.as_coerced()).collect();
1094 let matching_impls: Vec<&FuncImpl<_>> = impls
1095 .iter()
1096 .filter(|i| i.params.exact_match(&known_types))
1097 .cloned()
1098 .collect();
1099
1100 if matching_impls.len() == 1 {
1101 return Ok(matching_impls[0]);
1102 }
1103 }
1104
1105 let mut candidates: Vec<Candidate<_>> = Vec::new();
1109 macro_rules! maybe_get_last_candidate {
1110 () => {
1111 if candidates.len() == 1 {
1112 return Ok(&candidates[0].fimpl);
1113 }
1114 };
1115 }
1116 let mut max_exact_matches = 0;
1117
1118 for fimpl in impls {
1119 let mut exact_matches = 0;
1120 let mut preferred_types = 0;
1121 let mut near_matches = 0;
1122
1123 for (i, arg_type) in types.iter().enumerate() {
1124 let param_type = &fimpl.params[i];
1125
1126 match arg_type {
1127 CoercibleScalarType::Coerced(arg_type) => {
1128 if param_type == arg_type {
1129 exact_matches += 1;
1130 }
1131 if param_type.is_preferred_by(arg_type) {
1132 preferred_types += 1;
1133 }
1134 if param_type.is_near_match(arg_type) {
1135 near_matches += 1;
1136 }
1137 }
1138 CoercibleScalarType::Record(_) | CoercibleScalarType::Uncoerced => {
1139 if param_type.prefers_self() {
1140 preferred_types += 1;
1141 }
1142 }
1143 }
1144 }
1145
1146 max_exact_matches = std::cmp::max(max_exact_matches, exact_matches);
1151 candidates.push(Candidate {
1152 fimpl,
1153 exact_matches,
1154 preferred_types,
1155 near_matches,
1156 });
1157 }
1158
1159 if candidates.is_empty() {
1160 return Err(0);
1161 }
1162
1163 maybe_get_last_candidate!();
1164
1165 candidates.retain(|c| c.exact_matches >= max_exact_matches);
1168
1169 maybe_get_last_candidate!();
1170
1171 let mut max_near_matches = 0;
1176 for c in &candidates {
1177 max_near_matches = std::cmp::max(max_near_matches, c.near_matches);
1178 }
1179 candidates.retain(|c| c.near_matches >= max_near_matches);
1180
1181 let mut max_preferred_types = 0;
1185 for c in &candidates {
1186 max_preferred_types = std::cmp::max(max_preferred_types, c.preferred_types);
1187 }
1188 candidates.retain(|c| c.preferred_types >= max_preferred_types);
1189
1190 maybe_get_last_candidate!();
1191
1192 if all_types_known {
1193 return Err(candidates.len());
1194 }
1195
1196 let mut found_known = false;
1197 let mut types_match = true;
1198 let mut common_type: Option<SqlScalarType> = None;
1199
1200 for (i, arg_type) in types.iter().enumerate() {
1201 let mut selected_category: Option<TypeCategory> = None;
1202 let mut categories_match = true;
1203
1204 match arg_type {
1205 CoercibleScalarType::Uncoerced | CoercibleScalarType::Record(_) => {
1209 for c in candidates.iter() {
1210 let this_category = TypeCategory::from_param(&c.fimpl.params[i]);
1211 if this_category == TypeCategory::String {
1216 selected_category = Some(TypeCategory::String);
1217 break;
1218 }
1219 match selected_category {
1220 Some(ref mut selected_category) => {
1221 categories_match =
1224 selected_category == &this_category && categories_match;
1225 }
1226 None => selected_category = Some(this_category.clone()),
1227 }
1228 }
1229
1230 if selected_category != Some(TypeCategory::String) && !categories_match {
1234 break;
1235 }
1236
1237 let selected_category = selected_category.unwrap();
1242
1243 let preferred_type = selected_category.preferred_type();
1244 let mut found_preferred_type_candidate = false;
1245 candidates.retain(|c| {
1246 if let Some(typ) = &preferred_type {
1247 found_preferred_type_candidate = c.fimpl.params[i].accepts_type(ecx, typ)
1248 || found_preferred_type_candidate;
1249 }
1250 selected_category == TypeCategory::from_param(&c.fimpl.params[i])
1251 });
1252
1253 if found_preferred_type_candidate {
1254 let preferred_type = preferred_type.unwrap();
1255 candidates.retain(|c| c.fimpl.params[i].accepts_type(ecx, &preferred_type));
1256 }
1257 }
1258 CoercibleScalarType::Coerced(typ) => {
1259 found_known = true;
1260 match common_type {
1263 Some(ref common_type) => types_match = common_type == typ && types_match,
1264 None => common_type = Some(typ.clone()),
1265 }
1266 }
1267 }
1268 }
1269
1270 maybe_get_last_candidate!();
1271
1272 if found_known && types_match {
1278 let common_type = common_type.unwrap();
1279 let common_typed: Vec<_> = types
1280 .iter()
1281 .map(|t| match t {
1282 CoercibleScalarType::Coerced(t) => CoercibleScalarType::Coerced(t.clone()),
1283 CoercibleScalarType::Uncoerced | CoercibleScalarType::Record(_) => {
1284 CoercibleScalarType::Coerced(common_type.clone())
1285 }
1286 })
1287 .collect();
1288
1289 candidates.retain(|c| c.fimpl.params.matches_argtypes(ecx, &common_typed));
1290
1291 maybe_get_last_candidate!();
1292 }
1293
1294 Err(candidates.len())
1295}
1296
1297#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
1298enum PolymorphicCompatClass {
1299 Any,
1303 BestCommonAny,
1319 BestCommonList,
1328 BestCommonMap,
1333 StructuralEq,
1343}
1344
1345impl TryFrom<&ParamType> for PolymorphicCompatClass {
1346 type Error = ();
1347 fn try_from(param: &ParamType) -> Result<PolymorphicCompatClass, Self::Error> {
1348 use ParamType::*;
1349
1350 Ok(match param {
1351 AnyElement | ArrayAny | ListAny | MapAny | NonVecAny | RangeAny => {
1352 PolymorphicCompatClass::Any
1353 }
1354 ArrayAnyCompatible | AnyCompatible | RangeAnyCompatible | NonVecAnyCompatible => {
1355 PolymorphicCompatClass::BestCommonAny
1356 }
1357 ListAnyCompatible | ListElementAnyCompatible => PolymorphicCompatClass::BestCommonList,
1358 MapAnyCompatible => PolymorphicCompatClass::BestCommonMap,
1359 RecordAny => PolymorphicCompatClass::StructuralEq,
1360 _ => return Err(()),
1361 })
1362 }
1363}
1364
1365impl PolymorphicCompatClass {
1366 fn compatible(&self, ecx: &ExprContext, from: &SqlScalarType, to: &SqlScalarType) -> bool {
1367 use PolymorphicCompatClass::*;
1368 match self {
1369 StructuralEq => from.structural_eq(to),
1370 Any => from.base_eq(to),
1371 _ => typeconv::can_cast(ecx, CastContext::Implicit, from, to),
1372 }
1373 }
1374}
1375
1376#[derive(Debug)]
1379pub(crate) struct PolymorphicSolution {
1380 compat: Option<PolymorphicCompatClass>,
1383 seen: Vec<CoercibleScalarType>,
1384 key: Option<SqlScalarType>,
1386}
1387
1388impl PolymorphicSolution {
1389 fn new(
1396 ecx: &ExprContext,
1397 args: &[CoercibleScalarType],
1398 params: &ParamList,
1399 ) -> Option<PolymorphicSolution> {
1400 let mut r = PolymorphicSolution {
1401 compat: None,
1402 seen: vec![],
1403 key: None,
1404 };
1405
1406 for (i, scalar_type) in args.iter().cloned().enumerate() {
1407 r.track_seen(¶ms[i], scalar_type);
1408 }
1409
1410 if !r.determine_key(ecx) { None } else { Some(r) }
1411 }
1412
1413 fn track_seen(&mut self, param: &ParamType, seen: CoercibleScalarType) {
1416 use ParamType::*;
1417
1418 self.seen.push(match param {
1419 AnyElement | AnyCompatible | ListAnyCompatible | MapAnyCompatible | NonVecAny
1421 | RecordAny => seen,
1422 MapAny => seen.map_coerced(|array| array.unwrap_map_value_type().clone()),
1423 ListAny => seen.map_coerced(|array| array.unwrap_list_element_type().clone()),
1424 ArrayAny | ArrayAnyCompatible => {
1425 seen.map_coerced(|array| array.unwrap_array_element_type().clone())
1426 }
1427 RangeAny | RangeAnyCompatible => {
1428 seen.map_coerced(|range| range.unwrap_range_element_type().clone())
1429 }
1430 ListElementAnyCompatible => seen.map_coerced(|el| SqlScalarType::List {
1431 custom_id: None,
1432 element_type: Box::new(el),
1433 }),
1434 o => {
1435 assert!(
1436 !o.is_polymorphic(),
1437 "polymorphic parameters must track types they \
1438 encounter to determine polymorphic solution"
1439 );
1440 return;
1441 }
1442 });
1443
1444 let compat_class = param
1445 .try_into()
1446 .expect("already returned for non-polymorphic params");
1447
1448 match &self.compat {
1449 None => self.compat = Some(compat_class),
1450 Some(c) => {
1451 assert_eq!(
1452 c, &compat_class,
1453 "do not know how to correlate polymorphic classes {:?} and {:?}",
1454 c, &compat_class,
1455 )
1456 }
1457 };
1458 }
1459
1460 fn determine_key(&mut self, ecx: &ExprContext) -> bool {
1464 self.key = if !self.seen.iter().any(|v| v.is_coerced()) {
1465 match &self.compat {
1466 None => None,
1468 Some(t) => match t {
1473 PolymorphicCompatClass::BestCommonAny => Some(SqlScalarType::String),
1474 PolymorphicCompatClass::BestCommonList => Some(SqlScalarType::List {
1475 custom_id: None,
1476 element_type: Box::new(SqlScalarType::String),
1477 }),
1478 PolymorphicCompatClass::BestCommonMap => Some(SqlScalarType::Map {
1479 value_type: Box::new(SqlScalarType::String),
1480 custom_id: None,
1481 }),
1482 PolymorphicCompatClass::StructuralEq | PolymorphicCompatClass::Any => None,
1484 },
1485 }
1486 } else {
1487 let compat = self.compat.as_ref().unwrap();
1490
1491 let r = match compat {
1492 PolymorphicCompatClass::Any => {
1493 let mut s = self
1494 .seen
1495 .iter()
1496 .filter_map(|f| f.as_coerced().cloned())
1497 .collect::<Vec<_>>();
1498 let (candiate, remaining) =
1499 s.split_first().expect("have at least one non-None element");
1500 if remaining.iter().all(|r| r.base_eq(candiate)) {
1501 s.remove(0)
1502 } else {
1503 return false;
1504 }
1505 }
1506 _ => match typeconv::guess_best_common_type(ecx, &self.seen) {
1507 Ok(r) => r,
1508 Err(_) => return false,
1509 },
1510 };
1511
1512 for t in self.seen.iter() {
1514 if let CoercibleScalarType::Coerced(t) = t {
1515 if !compat.compatible(ecx, t, &r) {
1516 return false;
1517 }
1518 }
1519 }
1520 Some(r)
1521 };
1522
1523 true
1524 }
1525
1526 fn target_for_param_type(&self, param: &ParamType) -> Option<SqlScalarType> {
1529 use ParamType::*;
1530 assert_eq!(
1531 self.compat,
1532 Some(
1533 param
1534 .try_into()
1535 .expect("target_for_param_type only supports polymorphic parameters")
1536 ),
1537 "cannot use polymorphic solution for different compatibility classes"
1538 );
1539
1540 assert!(
1541 !matches!(param, RecordAny),
1542 "RecordAny should not be cast to a target type"
1543 );
1544
1545 match param {
1546 AnyElement | AnyCompatible | ListAnyCompatible | MapAnyCompatible | NonVecAny => {
1547 self.key.clone()
1548 }
1549 ArrayAny | ArrayAnyCompatible => self
1550 .key
1551 .as_ref()
1552 .map(|key| SqlScalarType::Array(Box::new(key.clone()))),
1553 ListAny => self.key.as_ref().map(|key| SqlScalarType::List {
1554 element_type: Box::new(key.clone()),
1555 custom_id: None,
1556 }),
1557 MapAny => self.key.as_ref().map(|key| SqlScalarType::Map {
1558 value_type: Box::new(key.clone()),
1559 custom_id: None,
1560 }),
1561 RangeAny | RangeAnyCompatible => self.key.as_ref().map(|key| SqlScalarType::Range {
1562 element_type: Box::new(key.clone()),
1563 }),
1564 ListElementAnyCompatible => self
1565 .key
1566 .as_ref()
1567 .map(|key| key.unwrap_list_element_type().clone()),
1568 _ => unreachable!(
1569 "cannot use polymorphic solution to resolve target type for param {:?}",
1570 param,
1571 ),
1572 }
1573 }
1574}
1575
1576fn coerce_args_to_types(
1577 ecx: &ExprContext,
1578 args: Vec<CoercibleScalarExpr>,
1579 params: &ParamList,
1580) -> Result<Vec<HirScalarExpr>, PlanError> {
1581 use ParamType::*;
1582
1583 let mut scalar_types: Vec<_> = args.iter().map(|e| ecx.scalar_type(e)).collect();
1584
1585 for ty in &mut scalar_types {
1587 ty.force_coerced_if_record();
1588 }
1589
1590 let polymorphic_solution = PolymorphicSolution::new(ecx, &scalar_types, params)
1591 .expect("polymorphic solution previously determined to be valid");
1592
1593 let do_convert =
1594 |arg: CoercibleScalarExpr, ty: &SqlScalarType| arg.cast_to(ecx, CastContext::Implicit, ty);
1595
1596 let mut res_exprs = Vec::with_capacity(args.len());
1597 for (i, cexpr) in args.into_iter().enumerate() {
1598 let expr = match ¶ms[i] {
1599 Any => match cexpr {
1600 CoercibleScalarExpr::Parameter(n) => {
1601 sql_bail!("could not determine data type of parameter ${}", n)
1602 }
1603 _ => cexpr.type_as_any(ecx)?,
1604 },
1605 RecordAny => match cexpr {
1606 CoercibleScalarExpr::LiteralString(_) => {
1607 sql_bail!("input of anonymous composite types is not implemented");
1608 }
1609 _ => cexpr.type_as_any(ecx)?,
1613 },
1614 Plain(ty) => do_convert(cexpr, ty)?,
1615 Internal => return Err(PlanError::InternalFunctionCall),
1616 p => {
1617 let target = polymorphic_solution
1618 .target_for_param_type(p)
1619 .ok_or_else(|| {
1620 PlanError::UnsolvablePolymorphicFunctionInput
1629 })?;
1630 do_convert(cexpr, &target)?
1631 }
1632 };
1633 res_exprs.push(expr);
1634 }
1635
1636 Ok(res_exprs)
1637}
1638
1639macro_rules! params {
1641 ([$($p:expr),*], $v:ident...) => {
1642 ParamList::Variadic {
1643 leading: vec![$($p.into(),)*],
1644 trailing: $v.into(),
1645 }
1646 };
1647 ($v:ident...) => { ParamList::Variadic { leading: vec![], trailing: $v.into() } };
1648 ($($p:expr),*) => { ParamList::Exact(vec![$($p.into(),)*]) };
1649}
1650
1651macro_rules! impl_def {
1652 ($params:expr, $op:expr, $return_type:expr, $oid:expr) => {{
1662 FuncImpl {
1663 oid: $oid,
1664 params: $params.into(),
1665 op: $op.into(),
1666 return_type: $return_type.into(),
1667 }
1668 }};
1669}
1670
1671macro_rules! builtins {
1673 {
1674 $(
1675 $name:expr => $ty:ident {
1676 $($params:expr => $op:expr => $return_type:expr, $oid:expr;)+
1677 }
1678 ),+
1679 } => {{
1680
1681 let mut builtins = BTreeMap::new();
1682 $(
1683 let impls = vec![$(impl_def!($params, $op, $return_type, $oid)),+];
1684 let func = Func::$ty(impls);
1685 let expect_set_return = matches!(&func, Func::Table(_));
1686 for imp in func.func_impls() {
1687 assert_eq!(
1688 imp.return_is_set, expect_set_return,
1689 "wrong set return value for func with oid {}",
1690 imp.oid
1691 );
1692 }
1693 let old = builtins.insert($name, func);
1694 mz_ore::assert_none!(old, "duplicate entry in builtins list");
1695 )+
1696 builtins
1697 }};
1698}
1699
1700#[derive(Debug)]
1701pub struct TableFuncPlan {
1702 pub imp: TableFuncImpl,
1703 pub column_names: Vec<ColumnName>,
1704}
1705
1706#[derive(Debug)]
1739pub enum TableFuncImpl {
1740 CallTable {
1741 func: TableFunc,
1742 exprs: Vec<HirScalarExpr>,
1743 },
1744 Expr(HirRelationExpr),
1745}
1746
1747#[derive(Debug)]
1748pub enum Func {
1749 Scalar(Vec<FuncImpl<HirScalarExpr>>),
1750 Aggregate(Vec<FuncImpl<(HirScalarExpr, AggregateFunc)>>),
1751 Table(Vec<FuncImpl<TableFuncPlan>>),
1752 ScalarWindow(Vec<FuncImpl<ScalarWindowFunc>>),
1753 ValueWindow(Vec<FuncImpl<(HirScalarExpr, ValueWindowFunc)>>),
1754}
1755
1756impl Func {
1757 pub fn func_impls(&self) -> Vec<FuncImplCatalogDetails> {
1758 match self {
1759 Func::Scalar(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1760 Func::Aggregate(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1761 Func::Table(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1762 Func::ScalarWindow(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1763 Func::ValueWindow(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1764 }
1765 }
1766
1767 pub fn class(&self) -> &str {
1768 match self {
1769 Func::Scalar(..) => "scalar",
1770 Func::Aggregate(..) => "aggregate",
1771 Func::Table(..) => "table",
1772 Func::ScalarWindow(..) => "window",
1773 Func::ValueWindow(..) => "window",
1774 }
1775 }
1776}
1777
1778macro_rules! catalog_name_only {
1782 ($name:expr) => {
1783 panic!(
1784 "{} should be planned away before reaching function selection",
1785 $name
1786 )
1787 };
1788}
1789
1790macro_rules! privilege_fn {
1792 ( $fn_name:expr, $catalog_tbl:expr ) => {{
1793 let fn_name = $fn_name;
1794 let catalog_tbl = $catalog_tbl;
1795 let public_role = RoleId::Public;
1796 format!(
1797 "
1798 CASE
1799 -- We need to validate the privileges to return a proper error before anything
1800 -- else.
1801 WHEN NOT mz_internal.mz_validate_privileges($3)
1802 OR $1 IS NULL
1803 OR $2 IS NULL
1804 OR $3 IS NULL
1805 OR $1 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
1806 OR $2 NOT IN (SELECT oid FROM {catalog_tbl})
1807 THEN NULL
1808 ELSE COALESCE(
1809 (
1810 SELECT
1811 bool_or(
1812 mz_internal.mz_acl_item_contains_privilege(privilege, $3)
1813 )
1814 AS {fn_name}
1815 FROM
1816 (
1817 SELECT
1818 unnest(privileges)
1819 FROM
1820 {catalog_tbl}
1821 WHERE
1822 {catalog_tbl}.oid = $2
1823 )
1824 AS user_privs (privilege)
1825 LEFT JOIN mz_catalog.mz_roles ON
1826 mz_internal.mz_aclitem_grantee(privilege) = mz_roles.id
1827 WHERE
1828 mz_internal.mz_aclitem_grantee(privilege) = '{public_role}'
1829 OR pg_has_role($1, mz_roles.oid, 'USAGE')
1830 ),
1831 false
1832 )
1833 END
1834 ",
1835 )
1836 }};
1837}
1838
1839pub static PG_CATALOG_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
1841 use ParamType::*;
1842 use SqlScalarBaseType::*;
1843 let mut builtins = builtins! {
1844 "abs" => Scalar {
1857 params!(Int16) => UnaryFunc::AbsInt16(func::AbsInt16) => Int16, 1398;
1858 params!(Int32) => UnaryFunc::AbsInt32(func::AbsInt32) => Int32, 1397;
1859 params!(Int64) => UnaryFunc::AbsInt64(func::AbsInt64) => Int64, 1396;
1860 params!(Numeric) => UnaryFunc::AbsNumeric(func::AbsNumeric) => Numeric, 1705;
1861 params!(Float32) => UnaryFunc::AbsFloat32(func::AbsFloat32) => Float32, 1394;
1862 params!(Float64) => UnaryFunc::AbsFloat64(func::AbsFloat64) => Float64, 1395;
1863 },
1864 "aclexplode" => Table {
1865 params!(SqlScalarType::Array(Box::new(
1866 SqlScalarType::AclItem,
1867 ))) => Operation::unary(move |_ecx, aclitems| {
1868 Ok(TableFuncPlan {
1869 imp: TableFuncImpl::CallTable {
1870 func: TableFunc::AclExplode,
1871 exprs: vec![aclitems],
1872 },
1873 column_names: vec![
1874 "grantor".into(), "grantee".into(),
1875 "privilege_type".into(), "is_grantable".into(),
1876 ],
1877 })
1878 }) => ReturnType::set_of(RecordAny), 1689;
1879 },
1880 "array_cat" => Scalar {
1881 params!(ArrayAnyCompatible, ArrayAnyCompatible) => Operation::binary(|_ecx, lhs, rhs| {
1882 Ok(lhs.call_binary(rhs, func::ArrayArrayConcat))
1883 }) => ArrayAnyCompatible, 383;
1884 },
1885 "array_fill" => Scalar {
1886 params!(AnyElement, SqlScalarType::Array(Box::new(SqlScalarType::Int32)))
1887 => Operation::binary(|ecx, elem, dims| {
1888 let elem_type = ecx.scalar_type(&elem);
1889
1890 let elem_type = match elem_type.array_of_self_elem_type() {
1891 Ok(elem_type) => elem_type,
1892 Err(elem_type) => bail_unsupported!(
1893 format!("array_fill on {}", ecx.humanize_sql_scalar_type(&elem_type, false))
1896 ),
1897 };
1898
1899 Ok(HirScalarExpr::call_variadic(
1900 variadic::ArrayFill { elem_type },
1901 vec![elem, dims]
1902 ))
1903 }) => ArrayAny, 1193;
1904 params!(
1905 AnyElement,
1906 SqlScalarType::Array(Box::new(SqlScalarType::Int32)),
1907 SqlScalarType::Array(Box::new(SqlScalarType::Int32))
1908 ) => Operation::variadic(|ecx, exprs| {
1909 let elem_type = ecx.scalar_type(&exprs[0]);
1910
1911 let elem_type = match elem_type.array_of_self_elem_type() {
1912 Ok(elem_type) => elem_type,
1913 Err(elem_type) => bail_unsupported!(
1914 format!("array_fill on {}", ecx.humanize_sql_scalar_type(&elem_type, false))
1915 ),
1916 };
1917
1918 Ok(HirScalarExpr::call_variadic(variadic::ArrayFill { elem_type }, exprs))
1919 }) => ArrayAny, 1286;
1920 },
1921 "array_length" => Scalar {
1922 params![ArrayAny, Int64] => BinaryFunc::from(func::ArrayLength) => Int32, 2176;
1923 },
1924 "array_lower" => Scalar {
1925 params!(ArrayAny, Int64) => BinaryFunc::from(func::ArrayLower) => Int32, 2091;
1926 },
1927 "array_position" => Scalar {
1928 params!(ArrayAnyCompatible, AnyCompatible)
1929 => VariadicFunc::from(variadic::ArrayPosition) => Int32, 3277;
1930 params!(ArrayAnyCompatible, AnyCompatible, Int32)
1931 => VariadicFunc::from(variadic::ArrayPosition) => Int32, 3278;
1932 },
1933 "array_remove" => Scalar {
1934 params!(ArrayAnyCompatible, AnyCompatible)
1935 => BinaryFunc::from(func::ArrayRemove)
1936 => ArrayAnyCompatible, 3167;
1937 },
1938 "array_to_string" => Scalar {
1939 params!(ArrayAny, String) => Operation::variadic(array_to_string) => String, 395;
1940 params!(ArrayAny, String, String)
1941 => Operation::variadic(array_to_string) => String, 384;
1942 },
1943 "array_upper" => Scalar {
1944 params!(ArrayAny, Int64) => BinaryFunc::from(func::ArrayUpper) => Int32, 2092;
1945 },
1946 "ascii" => Scalar {
1947 params!(String) => UnaryFunc::Ascii(func::Ascii) => Int32, 1620;
1948 },
1949 "avg" => Scalar {
1950 params!(Int64) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Numeric, 2100;
1951 params!(Int32) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Numeric, 2101;
1952 params!(Int16) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Numeric, 2102;
1953 params!(UInt64) =>
1954 Operation::nullary(|_ecx| catalog_name_only!("avg"))
1955 => Numeric, oid::FUNC_AVG_UINT64_OID;
1956 params!(UInt32) =>
1957 Operation::nullary(|_ecx| catalog_name_only!("avg"))
1958 => Numeric, oid::FUNC_AVG_UINT32_OID;
1959 params!(UInt16) =>
1960 Operation::nullary(|_ecx| catalog_name_only!("avg"))
1961 => Numeric, oid::FUNC_AVG_UINT16_OID;
1962 params!(Float32) =>
1963 Operation::nullary(|_ecx| catalog_name_only!("avg"))
1964 => Float64, 2104;
1965 params!(Float64) =>
1966 Operation::nullary(|_ecx| catalog_name_only!("avg"))
1967 => Float64, 2105;
1968 params!(Interval) =>
1969 Operation::nullary(|_ecx| catalog_name_only!("avg"))
1970 => Interval, 2106;
1971 },
1972 "bit_count" => Scalar {
1973 params!(Bytes) => UnaryFunc::BitCountBytes(func::BitCountBytes) => Int64, 6163;
1974 },
1975 "bit_length" => Scalar {
1976 params!(Bytes) => UnaryFunc::BitLengthBytes(func::BitLengthBytes) => Int32, 1810;
1977 params!(String) => UnaryFunc::BitLengthString(func::BitLengthString) => Int32, 1811;
1978 },
1979 "btrim" => Scalar {
1980 params!(String) => UnaryFunc::TrimWhitespace(func::TrimWhitespace) => String, 885;
1981 params!(String, String) => BinaryFunc::from(func::Trim) => String, 884;
1982 },
1983 "cbrt" => Scalar {
1984 params!(Float64) => UnaryFunc::CbrtFloat64(func::CbrtFloat64) => Float64, 1345;
1985 },
1986 "ceil" => Scalar {
1987 params!(Float32) => UnaryFunc::CeilFloat32(func::CeilFloat32)
1988 => Float32, oid::FUNC_CEIL_F32_OID;
1989 params!(Float64) => UnaryFunc::CeilFloat64(func::CeilFloat64) => Float64, 2308;
1990 params!(Numeric) => UnaryFunc::CeilNumeric(func::CeilNumeric) => Numeric, 1711;
1991 },
1992 "ceiling" => Scalar {
1993 params!(Float32) => UnaryFunc::CeilFloat32(func::CeilFloat32)
1994 => Float32, oid::FUNC_CEILING_F32_OID;
1995 params!(Float64) => UnaryFunc::CeilFloat64(func::CeilFloat64) => Float64, 2320;
1996 params!(Numeric) => UnaryFunc::CeilNumeric(func::CeilNumeric) => Numeric, 2167;
1997 },
1998 "char_length" => Scalar {
1999 params!(String) => UnaryFunc::CharLength(func::CharLength) => Int32, 1381;
2000 },
2001 "col_description" => Scalar {
2003 params!(Oid, Int32) => sql_impl_func(
2004 "(SELECT description
2005 FROM pg_description
2006 WHERE objoid = $1 AND classoid = 'pg_class'::regclass AND objsubid = $2)"
2007 ) => String, 1216;
2008 },
2009 "concat" => Scalar {
2010 params!(Any...) => Operation::variadic(|ecx, cexprs| {
2011 if cexprs.is_empty() {
2012 sql_bail!("No function matches the given name and argument types. \
2013 You might need to add explicit type casts.")
2014 }
2015 let mut exprs = vec![];
2016 for expr in cexprs {
2017 exprs.push(match ecx.scalar_type(&expr) {
2018 SqlScalarType::Bool => expr.call_unary(
2021 UnaryFunc::CastBoolToStringNonstandard(
2022 func::CastBoolToStringNonstandard,
2023 ),
2024 ),
2025 SqlScalarType::Char { length } => {
2027 expr.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
2028 }
2029 _ => typeconv::to_string(ecx, expr)
2030 });
2031 }
2032 Ok(HirScalarExpr::call_variadic(variadic::Concat, exprs))
2033 }) => String, 3058;
2034 },
2035 "concat_ws" => Scalar {
2036 params!([String], Any...) => Operation::variadic(|ecx, cexprs| {
2037 if cexprs.len() < 2 {
2038 sql_bail!("No function matches the given name and argument types. \
2039 You might need to add explicit type casts.")
2040 }
2041 let mut exprs = vec![];
2042 for expr in cexprs {
2043 exprs.push(match ecx.scalar_type(&expr) {
2044 SqlScalarType::Bool => expr.call_unary(
2047 UnaryFunc::CastBoolToStringNonstandard(
2048 func::CastBoolToStringNonstandard,
2049 ),
2050 ),
2051 SqlScalarType::Char { length } => {
2053 expr.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
2054 }
2055 _ => typeconv::to_string(ecx, expr)
2056 });
2057 }
2058 Ok(HirScalarExpr::call_variadic(variadic::ConcatWs, exprs))
2059 }) => String, 3059;
2060 },
2061 "convert_from" => Scalar {
2062 params!(Bytes, String) => BinaryFunc::from(func::ConvertFrom) => String, 1714;
2063 },
2064 "cos" => Scalar {
2065 params!(Float64) => UnaryFunc::Cos(func::Cos) => Float64, 1605;
2066 },
2067 "acos" => Scalar {
2068 params!(Float64) => UnaryFunc::Acos(func::Acos) => Float64, 1601;
2069 },
2070 "cosh" => Scalar {
2071 params!(Float64) => UnaryFunc::Cosh(func::Cosh) => Float64, 2463;
2072 },
2073 "acosh" => Scalar {
2074 params!(Float64) => UnaryFunc::Acosh(func::Acosh) => Float64, 2466;
2075 },
2076 "cot" => Scalar {
2077 params!(Float64) => UnaryFunc::Cot(func::Cot) => Float64, 1607;
2078 },
2079 "current_schema" => Scalar {
2080 params!() => UnmaterializableFunc::CurrentSchema => String, 1402;
2084 },
2085 "current_schemas" => Scalar {
2086 params!(Bool) => Operation::unary(|_ecx, e| {
2087 Ok(HirScalarExpr::if_then_else(
2088 e,
2089 HirScalarExpr::call_unmaterializable(
2090 UnmaterializableFunc::CurrentSchemasWithSystem,
2091 ),
2092 HirScalarExpr::call_unmaterializable(
2093 UnmaterializableFunc::CurrentSchemasWithoutSystem,
2094 ),
2095 ))
2096 }) => SqlScalarType::Array(Box::new(SqlScalarType::String)), 1403;
2100 },
2101 "current_database" => Scalar {
2102 params!() => UnmaterializableFunc::CurrentDatabase => String, 861;
2103 },
2104 "current_catalog" => Scalar {
2105 params!() => UnmaterializableFunc::CurrentDatabase => String, oid::FUNC_CURRENT_CATALOG;
2106 },
2107 "current_setting" => Scalar {
2108 params!(String) => Operation::unary(|_ecx, name| {
2109 current_settings(name, HirScalarExpr::literal_false())
2110 }) => SqlScalarType::String, 2077;
2111 params!(String, Bool) => Operation::binary(|_ecx, name, missing_ok| {
2112 current_settings(name, missing_ok)
2113 }) => SqlScalarType::String, 3294;
2114 },
2115 "current_timestamp" => Scalar {
2116 params!() => UnmaterializableFunc::CurrentTimestamp
2117 => TimestampTz, oid::FUNC_CURRENT_TIMESTAMP_OID;
2118 },
2119 "current_user" => Scalar {
2120 params!() => UnmaterializableFunc::CurrentUser => String, 745;
2121 },
2122 "current_role" => Scalar {
2123 params!() => UnmaterializableFunc::CurrentUser => String, oid::FUNC_CURRENT_ROLE;
2124 },
2125 "user" => Scalar {
2126 params!() => UnmaterializableFunc::CurrentUser => String, oid::FUNC_USER;
2127 },
2128 "session_user" => Scalar {
2129 params!() => UnmaterializableFunc::SessionUser => String, 746;
2130 },
2131 "chr" => Scalar {
2132 params!(Int32) => UnaryFunc::Chr(func::Chr) => String, 1621;
2133 },
2134 "date" => Scalar {
2135 params!(String) => UnaryFunc::CastStringToDate(func::CastStringToDate)
2136 => Date, oid::FUNC_DATE_FROM_TEXT;
2137 params!(Timestamp) => UnaryFunc::CastTimestampToDate(func::CastTimestampToDate)
2138 => Date, 2029;
2139 params!(TimestampTz) => UnaryFunc::CastTimestampTzToDate(func::CastTimestampTzToDate)
2140 => Date, 1178;
2141 },
2142 "date_bin" => Scalar {
2143 params!(Interval, Timestamp) => Operation::binary(|ecx, stride, source| {
2144 ecx.require_feature_flag(&vars::ENABLE_BINARY_DATE_BIN)?;
2145 Ok(stride.call_binary(source, func::DateBinTimestamp))
2146 }) => Timestamp, oid::FUNC_MZ_DATE_BIN_UNIX_EPOCH_TS_OID;
2147 params!(Interval, TimestampTz) => Operation::binary(|ecx, stride, source| {
2148 ecx.require_feature_flag(&vars::ENABLE_BINARY_DATE_BIN)?;
2149 Ok(stride.call_binary(source, func::DateBinTimestampTz))
2150 }) => TimestampTz, oid::FUNC_MZ_DATE_BIN_UNIX_EPOCH_TSTZ_OID;
2151 params!(Interval, Timestamp, Timestamp)
2152 => VariadicFunc::from(variadic::DateBinTimestamp) => Timestamp, 6177;
2153 params!(Interval, TimestampTz, TimestampTz)
2154 => VariadicFunc::from(variadic::DateBinTimestampTz) => TimestampTz, 6178;
2155 },
2156 "extract" => Scalar {
2157 params!(String, Interval)
2158 => BinaryFunc::from(func::DatePartIntervalNumeric) => Numeric, 6204;
2159 params!(String, Time)
2160 => BinaryFunc::from(func::DatePartTimeNumeric) => Numeric, 6200;
2161 params!(String, Timestamp)
2162 => BinaryFunc::from(func::DatePartTimestampTimestampNumeric)
2163 => Numeric, 6202;
2164 params!(String, TimestampTz)
2165 => BinaryFunc::from(func::DatePartTimestampTimestampTzNumeric)
2166 => Numeric, 6203;
2167 params!(String, Date) => BinaryFunc::from(func::ExtractDateUnits) => Numeric, 6199;
2168 },
2169 "date_part" => Scalar {
2170 params!(String, Interval)
2171 => BinaryFunc::from(func::DatePartIntervalF64) => Float64, 1172;
2172 params!(String, Time)
2173 => BinaryFunc::from(func::DatePartTimeF64) => Float64, 1385;
2174 params!(String, Timestamp)
2175 => BinaryFunc::from(func::DatePartTimestampTimestampF64)
2176 => Float64, 2021;
2177 params!(String, TimestampTz)
2178 => BinaryFunc::from(func::DatePartTimestampTimestampTzF64)
2179 => Float64, 1171;
2180 },
2181 "date_trunc" => Scalar {
2182 params!(String, Timestamp)
2183 => BinaryFunc::from(func::DateTruncUnitsTimestamp) => Timestamp, 2020;
2184 params!(String, TimestampTz)
2185 => BinaryFunc::from(func::DateTruncUnitsTimestampTz)
2186 => TimestampTz, 1217;
2187 params!(String, Interval)
2188 => BinaryFunc::from(func::DateTruncInterval) => Interval, 1218;
2189 },
2190 "daterange" => Scalar {
2191 params!(Date, Date) => Operation::variadic(|_ecx, mut exprs| {
2192 exprs.push(HirScalarExpr::literal(
2193 Datum::String("[)"), SqlScalarType::String,
2194 ));
2195 Ok(HirScalarExpr::call_variadic(
2196 variadic::RangeCreate { elem_type: SqlScalarType::Date },
2197 exprs,
2198 ))
2199 }) => SqlScalarType::Range {
2200 element_type: Box::new(SqlScalarType::Date),
2201 }, 3941;
2202 params!(Date, Date, String) => Operation::variadic(|_ecx, exprs| {
2203 Ok(HirScalarExpr::call_variadic(
2204 variadic::RangeCreate { elem_type: SqlScalarType::Date },
2205 exprs,
2206 ))
2207 }) => SqlScalarType::Range {
2208 element_type: Box::new(SqlScalarType::Date),
2209 }, 3942;
2210 },
2211 "degrees" => Scalar {
2212 params!(Float64) => UnaryFunc::Degrees(func::Degrees) => Float64, 1608;
2213 },
2214 "digest" => Scalar {
2215 params!(String, String) => BinaryFunc::from(func::DigestString)
2216 => Bytes, oid::FUNC_PG_DIGEST_STRING;
2217 params!(Bytes, String) => BinaryFunc::from(func::DigestBytes)
2218 => Bytes, oid::FUNC_PG_DIGEST_BYTES;
2219 },
2220 "exp" => Scalar {
2221 params!(Float64) => UnaryFunc::Exp(func::Exp) => Float64, 1347;
2222 params!(Numeric) => UnaryFunc::ExpNumeric(func::ExpNumeric) => Numeric, 1732;
2223 },
2224 "floor" => Scalar {
2225 params!(Float32) => UnaryFunc::FloorFloat32(func::FloorFloat32)
2226 => Float32, oid::FUNC_FLOOR_F32_OID;
2227 params!(Float64) => UnaryFunc::FloorFloat64(func::FloorFloat64) => Float64, 2309;
2228 params!(Numeric) => UnaryFunc::FloorNumeric(func::FloorNumeric) => Numeric, 1712;
2229 },
2230 "format_type" => Scalar {
2231 params!(Oid, Int32) => sql_impl_func(
2232 "CASE
2233 WHEN $1 IS NULL THEN NULL
2234 -- timestamp and timestamptz have the typmod in
2235 -- a nonstandard location that requires special
2236 -- handling.
2237 WHEN $1 = 1114 AND $2 >= 0 THEN 'timestamp(' || $2 || ') without time zone'
2238 WHEN $1 = 1184 AND $2 >= 0 THEN 'timestamp(' || $2 || ') with time zone'
2239 ELSE coalesce(
2240 (SELECT pg_catalog.concat(
2241 coalesce(mz_internal.mz_type_name($1), name),
2242 mz_internal.mz_render_typmod($1, $2))
2243 FROM mz_catalog.mz_types WHERE oid = $1),
2244 '???')
2245 END"
2246 ) => String, 1081;
2247 },
2248 "get_bit" => Scalar {
2249 params!(Bytes, Int32) => BinaryFunc::from(func::GetBit) => Int32, 723;
2250 },
2251 "get_byte" => Scalar {
2252 params!(Bytes, Int32) => BinaryFunc::from(func::GetByte) => Int32, 721;
2253 },
2254 "pg_get_ruledef" => Scalar {
2255 params!(Oid) => sql_impl_func("NULL::pg_catalog.text") => String, 1573;
2256 params!(Oid, Bool) => sql_impl_func("NULL::pg_catalog.text") => String, 2504;
2257 },
2258 "has_schema_privilege" => Scalar {
2259 params!(String, String, String) => sql_impl_func(
2260 "has_schema_privilege(\
2261 mz_internal.mz_role_oid($1), \
2262 mz_internal.mz_schema_oid($2), $3)",
2263 ) => Bool, 2268;
2264 params!(String, Oid, String) => sql_impl_func(
2265 "has_schema_privilege(\
2266 mz_internal.mz_role_oid($1), $2, $3)",
2267 ) => Bool, 2269;
2268 params!(Oid, String, String) => sql_impl_func(
2269 "has_schema_privilege(\
2270 $1, mz_internal.mz_schema_oid($2), $3)",
2271 ) => Bool, 2270;
2272 params!(Oid, Oid, String) => sql_impl_func(
2273 &privilege_fn!(
2274 "has_schema_privilege", "mz_schemas"
2275 ),
2276 ) => Bool, 2271;
2277 params!(String, String) => sql_impl_func(
2278 "has_schema_privilege(current_user, $1, $2)",
2279 ) => Bool, 2272;
2280 params!(Oid, String) => sql_impl_func(
2281 "has_schema_privilege(current_user, $1, $2)",
2282 ) => Bool, 2273;
2283 },
2284 "has_database_privilege" => Scalar {
2285 params!(String, String, String) => sql_impl_func(
2286 "has_database_privilege(\
2287 mz_internal.mz_role_oid($1), \
2288 mz_internal.mz_database_oid($2), $3)",
2289 ) => Bool, 2250;
2290 params!(String, Oid, String) => sql_impl_func(
2291 "has_database_privilege(\
2292 mz_internal.mz_role_oid($1), $2, $3)",
2293 ) => Bool, 2251;
2294 params!(Oid, String, String) => sql_impl_func(
2295 "has_database_privilege(\
2296 $1, mz_internal.mz_database_oid($2), $3)",
2297 ) => Bool, 2252;
2298 params!(Oid, Oid, String) => sql_impl_func(
2299 &privilege_fn!(
2300 "has_database_privilege", "mz_databases"
2301 ),
2302 ) => Bool, 2253;
2303 params!(String, String) => sql_impl_func(
2304 "has_database_privilege(current_user, $1, $2)",
2305 ) => Bool, 2254;
2306 params!(Oid, String) => sql_impl_func(
2307 "has_database_privilege(current_user, $1, $2)",
2308 ) => Bool, 2255;
2309 },
2310 "has_table_privilege" => Scalar {
2311 params!(String, String, String) => sql_impl_func(
2312 "has_table_privilege(\
2313 mz_internal.mz_role_oid($1), \
2314 $2::regclass::oid, $3)",
2315 ) => Bool, 1922;
2316 params!(String, Oid, String) => sql_impl_func(
2317 "has_table_privilege(\
2318 mz_internal.mz_role_oid($1), $2, $3)",
2319 ) => Bool, 1923;
2320 params!(Oid, String, String) => sql_impl_func(
2321 "has_table_privilege(\
2322 $1, $2::regclass::oid, $3)",
2323 ) => Bool, 1924;
2324 params!(Oid, Oid, String) => sql_impl_func(
2325 &privilege_fn!(
2326 "has_table_privilege", "mz_relations"
2327 ),
2328 ) => Bool, 1925;
2329 params!(String, String) => sql_impl_func(
2330 "has_table_privilege(current_user, $1, $2)",
2331 ) => Bool, 1926;
2332 params!(Oid, String) => sql_impl_func(
2333 "has_table_privilege(current_user, $1, $2)",
2334 ) => Bool, 1927;
2335 },
2336 "hmac" => Scalar {
2337 params!(String, String, String) => VariadicFunc::from(variadic::HmacString)
2338 => Bytes, oid::FUNC_PG_HMAC_STRING;
2339 params!(Bytes, Bytes, String) => VariadicFunc::from(variadic::HmacBytes)
2340 => Bytes, oid::FUNC_PG_HMAC_BYTES;
2341 },
2342 "initcap" => Scalar {
2343 params!(String) => UnaryFunc::Initcap(func::Initcap) => String, 872;
2344 },
2345 "int4range" => Scalar {
2346 params!(Int32, Int32) => Operation::variadic(|_ecx, mut exprs| {
2347 exprs.push(HirScalarExpr::literal(
2348 Datum::String("[)"), SqlScalarType::String,
2349 ));
2350 Ok(HirScalarExpr::call_variadic(
2351 variadic::RangeCreate { elem_type: SqlScalarType::Int32 },
2352 exprs,
2353 ))
2354 }) => SqlScalarType::Range {
2355 element_type: Box::new(SqlScalarType::Int32),
2356 }, 3840;
2357 params!(Int32, Int32, String) => Operation::variadic(|_ecx, exprs| {
2358 Ok(HirScalarExpr::call_variadic(
2359 variadic::RangeCreate { elem_type: SqlScalarType::Int32 },
2360 exprs,
2361 ))
2362 }) => SqlScalarType::Range {
2363 element_type: Box::new(SqlScalarType::Int32),
2364 }, 3841;
2365 },
2366 "int8range" => Scalar {
2367 params!(Int64, Int64) => Operation::variadic(|_ecx, mut exprs| {
2368 exprs.push(HirScalarExpr::literal(
2369 Datum::String("[)"), SqlScalarType::String,
2370 ));
2371 Ok(HirScalarExpr::call_variadic(
2372 variadic::RangeCreate { elem_type: SqlScalarType::Int64 },
2373 exprs,
2374 ))
2375 }) => SqlScalarType::Range {
2376 element_type: Box::new(SqlScalarType::Int64),
2377 }, 3945;
2378 params!(Int64, Int64, String) => Operation::variadic(|_ecx, exprs| {
2379 Ok(HirScalarExpr::call_variadic(
2380 variadic::RangeCreate { elem_type: SqlScalarType::Int64 },
2381 exprs,
2382 ))
2383 }) => SqlScalarType::Range {
2384 element_type: Box::new(SqlScalarType::Int64),
2385 }, 3946;
2386 },
2387 "isempty" => Scalar {
2388 params!(RangeAny) => UnaryFunc::RangeEmpty(func::RangeEmpty) => Bool, 3850;
2389 },
2390 "jsonb_array_length" => Scalar {
2391 params!(Jsonb) => UnaryFunc::JsonbArrayLength(func::JsonbArrayLength) => Int32, 3207;
2392 },
2393 "jsonb_build_array" => Scalar {
2394 params!() => VariadicFunc::from(variadic::JsonbBuildArray) => Jsonb, 3272;
2395 params!(Any...) => Operation::variadic(|ecx, exprs| {
2396 Ok(HirScalarExpr::call_variadic(
2397 variadic::JsonbBuildArray,
2398 exprs.into_iter().map(|e| typeconv::to_jsonb(ecx, e)).collect(),
2399 ))
2400 }) => Jsonb, 3271;
2401 },
2402 "jsonb_build_object" => Scalar {
2403 params!() => VariadicFunc::from(variadic::JsonbBuildObject) => Jsonb, 3274;
2404 params!(Any...) => Operation::variadic(|ecx, exprs| {
2405 if exprs.len() % 2 != 0 {
2406 sql_bail!("argument list must have even number of elements")
2407 }
2408 Ok(HirScalarExpr::call_variadic(
2409 variadic::JsonbBuildObject,
2410 exprs.into_iter().tuples().map(|(key, val)| {
2411 let key = typeconv::to_string(ecx, key);
2412 let val = typeconv::to_jsonb(ecx, val);
2413 vec![key, val]
2414 }).flatten().collect()))
2415 }) => Jsonb, 3273;
2416 },
2417 "jsonb_pretty" => Scalar {
2418 params!(Jsonb) => UnaryFunc::JsonbPretty(func::JsonbPretty) => String, 3306;
2419 },
2420 "jsonb_strip_nulls" => Scalar {
2421 params!(Jsonb) => UnaryFunc::JsonbStripNulls(func::JsonbStripNulls) => Jsonb, 3262;
2422 },
2423 "jsonb_typeof" => Scalar {
2424 params!(Jsonb) => UnaryFunc::JsonbTypeof(func::JsonbTypeof) => String, 3210;
2425 },
2426 "justify_days" => Scalar {
2427 params!(Interval) => UnaryFunc::JustifyDays(func::JustifyDays) => Interval, 1295;
2428 },
2429 "justify_hours" => Scalar {
2430 params!(Interval) => UnaryFunc::JustifyHours(func::JustifyHours) => Interval, 1175;
2431 },
2432 "justify_interval" => Scalar {
2433 params!(Interval) => UnaryFunc::JustifyInterval(func::JustifyInterval)
2434 => Interval, 2711;
2435 },
2436 "left" => Scalar {
2437 params!(String, Int32) => BinaryFunc::from(func::Left) => String, 3060;
2438 },
2439 "length" => Scalar {
2440 params!(Bytes) => UnaryFunc::ByteLengthBytes(func::ByteLengthBytes) => Int32, 2010;
2441 params!(String) => UnaryFunc::CharLength(func::CharLength) => Int32, 1317;
2443 params!(Bytes, String) => BinaryFunc::from(func::EncodedBytesCharLength) => Int32, 1713;
2444 },
2445 "like_escape" => Scalar {
2446 params!(String, String) => BinaryFunc::from(func::LikeEscape) => String, 1637;
2447 },
2448 "ln" => Scalar {
2449 params!(Float64) => UnaryFunc::Ln(func::Ln) => Float64, 1341;
2450 params!(Numeric) => UnaryFunc::LnNumeric(func::LnNumeric) => Numeric, 1734;
2451 },
2452 "log10" => Scalar {
2453 params!(Float64) => UnaryFunc::Log10(func::Log10) => Float64, 1194;
2454 params!(Numeric) => UnaryFunc::Log10Numeric(func::Log10Numeric) => Numeric, 1481;
2455 },
2456 "log" => Scalar {
2457 params!(Float64) => UnaryFunc::Log10(func::Log10) => Float64, 1340;
2458 params!(Numeric) => UnaryFunc::Log10Numeric(func::Log10Numeric) => Numeric, 1741;
2459 params!(Numeric, Numeric) => BinaryFunc::from(func::LogBaseNumeric) => Numeric, 1736;
2460 },
2461 "lower" => Scalar {
2462 params!(String) => UnaryFunc::Lower(func::Lower) => String, 870;
2463 params!(RangeAny) => UnaryFunc::RangeLower(func::RangeLower) => AnyElement, 3848;
2464 },
2465 "lower_inc" => Scalar {
2466 params!(RangeAny) => UnaryFunc::RangeLowerInc(func::RangeLowerInc) => Bool, 3851;
2467 },
2468 "lower_inf" => Scalar {
2469 params!(RangeAny) => UnaryFunc::RangeLowerInf(func::RangeLowerInf) => Bool, 3853;
2470 },
2471 "lpad" => Scalar {
2472 params!(String, Int32) => VariadicFunc::from(variadic::PadLeading) => String, 879;
2473 params!(String, Int32, String) => VariadicFunc::from(variadic::PadLeading)
2474 => String, 873;
2475 },
2476 "ltrim" => Scalar {
2477 params!(String) => UnaryFunc::TrimLeadingWhitespace(
2478 func::TrimLeadingWhitespace,
2479 ) => String, 881;
2480 params!(String, String) => BinaryFunc::from(func::TrimLeading) => String, 875;
2481 },
2482 "makeaclitem" => Scalar {
2483 params!(Oid, Oid, String, Bool)
2484 => VariadicFunc::from(variadic::MakeAclItem) => AclItem, 1365;
2485 },
2486 "make_timestamp" => Scalar {
2487 params!(Int64, Int64, Int64, Int64, Int64, Float64)
2488 => VariadicFunc::from(variadic::MakeTimestamp) => Timestamp, 3461;
2489 },
2490 "md5" => Scalar {
2491 params!(String) => Operation::unary(move |_ecx, input| {
2492 let algorithm = HirScalarExpr::literal(Datum::String("md5"), SqlScalarType::String);
2493 let encoding = HirScalarExpr::literal(Datum::String("hex"), SqlScalarType::String);
2494 Ok(input
2495 .call_binary(algorithm, func::DigestString)
2496 .call_binary(encoding, func::Encode))
2497 }) => String, 2311;
2498 params!(Bytes) => Operation::unary(move |_ecx, input| {
2499 let algorithm = HirScalarExpr::literal(
2500 Datum::String("md5"), SqlScalarType::String,
2501 );
2502 let encoding = HirScalarExpr::literal(
2503 Datum::String("hex"), SqlScalarType::String,
2504 );
2505 Ok(input
2506 .call_binary(algorithm, func::DigestBytes)
2507 .call_binary(encoding, func::Encode))
2508 }) => String, 2321;
2509 },
2510 "mod" => Scalar {
2511 params!(Numeric, Numeric) =>
2512 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2513 => Numeric, 1728;
2514 params!(Int16, Int16) =>
2515 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2516 => Int16, 940;
2517 params!(Int32, Int32) =>
2518 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2519 => Int32, 941;
2520 params!(Int64, Int64) =>
2521 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2522 => Int64, 947;
2523 params!(UInt16, UInt16) =>
2524 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2525 => UInt16, oid::FUNC_MOD_UINT16_OID;
2526 params!(UInt32, UInt32) =>
2527 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2528 => UInt32, oid::FUNC_MOD_UINT32_OID;
2529 params!(UInt64, UInt64) =>
2530 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2531 => UInt64, oid::FUNC_MOD_UINT64_OID;
2532 },
2533 "normalize" => Scalar {
2534 params!(String, String) => BinaryFunc::Normalize(func::Normalize)
2536 => String, oid::FUNC_NORMALIZE_OID;
2537 },
2538 "now" => Scalar {
2539 params!() => UnmaterializableFunc::CurrentTimestamp => TimestampTz, 1299;
2540 },
2541 "numrange" => Scalar {
2542 params!(Numeric, Numeric) => Operation::variadic(|_ecx, mut exprs| {
2543 exprs.push(HirScalarExpr::literal(
2544 Datum::String("[)"), SqlScalarType::String,
2545 ));
2546 Ok(HirScalarExpr::call_variadic(
2547 variadic::RangeCreate {
2548 elem_type: SqlScalarType::Numeric { max_scale: None },
2549 },
2550 exprs,
2551 ))
2552 }) => SqlScalarType::Range {
2553 element_type: Box::new(SqlScalarType::Numeric { max_scale: None }),
2554 }, 3844;
2555 params!(Numeric, Numeric, String) => Operation::variadic(|_ecx, exprs| {
2556 Ok(HirScalarExpr::call_variadic(
2557 variadic::RangeCreate {
2558 elem_type: SqlScalarType::Numeric { max_scale: None },
2559 },
2560 exprs,
2561 ))
2562 }) => SqlScalarType::Range {
2563 element_type: Box::new(SqlScalarType::Numeric { max_scale: None }),
2564 }, 3845;
2565 },
2566 "octet_length" => Scalar {
2567 params!(Bytes) => UnaryFunc::ByteLengthBytes(func::ByteLengthBytes) => Int32, 720;
2568 params!(String) => UnaryFunc::ByteLengthString(func::ByteLengthString) => Int32, 1374;
2569 params!(Char) => Operation::unary(|ecx, e| {
2570 let length = ecx.scalar_type(&e).unwrap_char_length();
2571 Ok(e.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
2572 .call_unary(UnaryFunc::ByteLengthString(func::ByteLengthString))
2573 )
2574 }) => Int32, 1375;
2575 },
2576 "obj_description" => Scalar {
2580 params!(Oid, String) => sql_impl_func(&format!(
2581 "(SELECT description FROM pg_description
2582 WHERE objoid = $1
2583 AND classoid = (
2584 SELECT oid FROM pg_class WHERE relname = $2 AND relnamespace = {})
2585 AND objsubid = 0)",
2586 oid::SCHEMA_PG_CATALOG_OID
2587 )) => String, 1215;
2588 },
2589 "pg_column_size" => Scalar {
2590 params!(Any) => UnaryFunc::PgColumnSize(func::PgColumnSize) => Int32, 1269;
2591 },
2592 "pg_size_pretty" => Scalar {
2593 params!(Numeric) => UnaryFunc::PgSizePretty(func::PgSizePretty) => String, 3166;
2594 },
2595 "mz_row_size" => Scalar {
2596 params!(Any) => Operation::unary(|ecx, e| {
2597 let s = ecx.scalar_type(&e);
2598 if !matches!(s, SqlScalarType::Record{..}) {
2599 sql_bail!("mz_row_size requires a record type");
2600 }
2601 Ok(e.call_unary(UnaryFunc::MzRowSize(func::MzRowSize)))
2602 }) => Int32, oid::FUNC_MZ_ROW_SIZE;
2603 },
2604 "parse_ident" => Scalar {
2605 params!(String) => Operation::unary(|_ecx, ident| {
2606 Ok(ident.call_binary(HirScalarExpr::literal_true(), func::ParseIdent))
2607 }) => SqlScalarType::Array(Box::new(SqlScalarType::String)),
2608 oid::FUNC_PARSE_IDENT_DEFAULT_STRICT;
2609 params!(String, Bool) => BinaryFunc::from(func::ParseIdent)
2610 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 1268;
2611 },
2612 "pg_encoding_to_char" => Scalar {
2613 params!(Int64) => sql_impl_func(
2616 "CASE WHEN $1 = 6 THEN 'UTF8' ELSE NULL END",
2617 ) => String, 1597;
2618 },
2619 "pg_backend_pid" => Scalar {
2620 params!() => UnmaterializableFunc::PgBackendPid => Int32, 2026;
2621 },
2622 "pg_get_constraintdef" => Scalar {
2628 params!(Oid) => Operation::unary(|_ecx, _oid|
2629 Ok(HirScalarExpr::literal_null(SqlScalarType::String))) => String, 1387;
2630 params!(Oid, Bool) => Operation::binary(|_ecx, _oid, _pretty|
2631 Ok(HirScalarExpr::literal_null(SqlScalarType::String))) => String, 2508;
2632 },
2633 "pg_get_indexdef" => Scalar {
2638 params!(Oid) => sql_impl_func(
2639 "(SELECT 'CREATE INDEX ' || i.name
2640 || ' ON ' || r.name
2641 || ' USING arrangement (' || (
2642 SELECT pg_catalog.string_agg(
2643 cols.col_exp, ',' ORDER BY cols.index_position)
2644 FROM (
2645 SELECT c.name AS col_exp, ic.index_position
2646 FROM mz_catalog.mz_index_columns AS ic
2647 JOIN mz_catalog.mz_indexes AS i2
2648 ON ic.index_id = i2.id
2649 JOIN mz_catalog.mz_columns AS c
2650 ON i2.on_id = c.id
2651 AND ic.on_position = c.position
2652 WHERE ic.index_id = i.id
2653 AND ic.on_expression IS NULL
2654 UNION
2655 SELECT ic.on_expression AS col_exp,
2656 ic.index_position
2657 FROM mz_catalog.mz_index_columns AS ic
2658 WHERE ic.index_id = i.id
2659 AND ic.on_expression IS NOT NULL
2660 ) AS cols
2661 ) || ')'
2662 FROM mz_catalog.mz_indexes AS i
2663 JOIN mz_catalog.mz_relations AS r
2664 ON i.on_id = r.id
2665 WHERE i.oid = $1)"
2666 ) => String, 1643;
2667 params!(Oid, Int32, Bool) => sql_impl_func(
2670 "(SELECT CASE
2671 WHEN $2 = 0
2672 THEN pg_catalog.pg_get_indexdef($1)
2673 ELSE (
2674 SELECT c.name
2675 FROM mz_catalog.mz_indexes AS i
2676 JOIN mz_catalog.mz_index_columns AS ic
2677 ON i.id = ic.index_id
2678 JOIN mz_catalog.mz_columns AS c
2679 ON i.on_id = c.id
2680 AND ic.on_position = c.position
2681 WHERE i.oid = $1
2682 AND ic.on_expression IS NULL
2683 AND ic.index_position = $2
2684 UNION
2685 SELECT ic.on_expression
2686 FROM mz_catalog.mz_indexes AS i
2687 JOIN mz_catalog.mz_index_columns AS ic
2688 ON i.id = ic.index_id
2689 WHERE i.oid = $1
2690 AND ic.on_expression IS NOT NULL
2691 AND ic.index_position = $2)
2692 END)"
2693 ) => String, 2507;
2694 },
2695 "pg_get_viewdef" => Scalar {
2698 params!(String) => sql_impl_func(
2699 "(SELECT definition FROM mz_catalog.mz_views WHERE name = $1)"
2700 ) => String, 1640;
2701 params!(Oid) => sql_impl_func(
2702 "(SELECT definition FROM mz_catalog.mz_views WHERE oid = $1)"
2703 ) => String, 1641;
2704 params!(String, Bool) => sql_impl_func(
2705 "(SELECT definition FROM mz_catalog.mz_views WHERE name = $1)"
2706 ) => String, 2505;
2707 params!(Oid, Bool) => sql_impl_func(
2708 "(SELECT definition FROM mz_catalog.mz_views WHERE oid = $1)"
2709 ) => String, 2506;
2710 params!(Oid, Int32) => sql_impl_func(
2711 "(SELECT definition FROM mz_catalog.mz_views WHERE oid = $1)"
2712 ) => String, 3159;
2713 },
2714 "pg_get_expr" => Scalar {
2722 params!(String, Oid) => Operation::binary(|_ecx, l, _r| Ok(l)) => String, 1716;
2723 params!(String, Oid, Bool) => Operation::variadic(
2724 move |_ecx, mut args| Ok(args.remove(0)),
2725 ) => String, 2509;
2726 },
2727 "pg_get_userbyid" => Scalar {
2728 params!(Oid) => sql_impl_func(
2729 "CASE \
2730 WHEN $1 IS NULL THEN NULL \
2731 ELSE COALESCE(\
2732 (SELECT name FROM mz_catalog.mz_roles WHERE oid = $1),\
2733 'unknown (OID=' || $1 || ')'\
2734 ) \
2735 END"
2736 ) => String, 1642;
2737 },
2738 "pg_has_role" => Scalar {
2745 params!(String, String, String) => sql_impl_func(
2746 "pg_has_role(\
2747 mz_internal.mz_role_oid($1), \
2748 mz_internal.mz_role_oid($2), $3)",
2749 ) => Bool, 2705;
2750 params!(String, Oid, String) => sql_impl_func(
2751 "pg_has_role(\
2752 mz_internal.mz_role_oid($1), $2, $3)",
2753 ) => Bool, 2706;
2754 params!(Oid, String, String) => sql_impl_func(
2755 "pg_has_role(\
2756 $1, mz_internal.mz_role_oid($2), $3)",
2757 ) => Bool, 2707;
2758 params!(Oid, Oid, String) => sql_impl_func(
2759 "CASE
2760 -- We need to validate the privilege to return a proper error before anything
2761 -- else.
2762 WHEN NOT mz_internal.mz_validate_role_privilege($3)
2763 OR $1 IS NULL
2764 OR $2 IS NULL
2765 OR $3 IS NULL
2766 THEN NULL
2767 WHEN $1 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
2768 OR $2 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
2769 THEN false
2770 ELSE $2::text IN (SELECT UNNEST(mz_internal.mz_role_oid_memberships() -> $1::text))
2771 END",
2772 ) => Bool, 2708;
2773 params!(String, String) => sql_impl_func(
2774 "pg_has_role(current_user, $1, $2)",
2775 ) => Bool, 2709;
2776 params!(Oid, String) => sql_impl_func(
2777 "pg_has_role(current_user, $1, $2)",
2778 ) => Bool, 2710;
2779 },
2780 "pg_is_in_recovery" => Scalar {
2783 params!() => Operation::nullary(|_ecx| {
2784 Ok(HirScalarExpr::literal_false())
2785 }) => Bool, 3810;
2786 },
2787 "pg_postmaster_start_time" => Scalar {
2788 params!() => UnmaterializableFunc::PgPostmasterStartTime => TimestampTz, 2560;
2789 },
2790 "pg_relation_size" => Scalar {
2791 params!(RegClass, String) => sql_impl_func(
2792 "CASE WHEN $1 IS NULL OR $2 IS NULL \
2793 THEN NULL ELSE -1::pg_catalog.int8 END",
2794 ) => Int64, 2332;
2795 params!(RegClass) => sql_impl_func(
2796 "CASE WHEN $1 IS NULL \
2797 THEN NULL ELSE -1::pg_catalog.int8 END",
2798 ) => Int64, 2325;
2799 },
2800 "pg_stat_get_numscans" => Scalar {
2801 params!(Oid) => sql_impl_func(
2802 "CASE WHEN $1 IS NULL \
2803 THEN NULL ELSE -1::pg_catalog.int8 END",
2804 ) => Int64, 1928;
2805 },
2806 "pg_table_is_visible" => Scalar {
2807 params!(Oid) => sql_impl_func(
2808 "(SELECT s.name = ANY(pg_catalog.current_schemas(true))
2809 FROM mz_catalog.mz_objects o JOIN mz_catalog.mz_schemas s ON o.schema_id = s.id
2810 WHERE o.oid = $1)"
2811 ) => Bool, 2079;
2812 },
2813 "pg_type_is_visible" => Scalar {
2814 params!(Oid) => sql_impl_func(
2815 "(SELECT s.name = ANY(pg_catalog.current_schemas(true))
2816 FROM mz_catalog.mz_types t JOIN mz_catalog.mz_schemas s ON t.schema_id = s.id
2817 WHERE t.oid = $1)"
2818 ) => Bool, 2080;
2819 },
2820 "pg_function_is_visible" => Scalar {
2821 params!(Oid) => sql_impl_func(
2822 "(SELECT s.name = ANY(pg_catalog.current_schemas(true))
2823 FROM mz_catalog.mz_functions f
2824 JOIN mz_catalog.mz_schemas s
2825 ON f.schema_id = s.id
2826 WHERE f.oid = $1)"
2827 ) => Bool, 2081;
2828 },
2829 "pg_tablespace_location" => Scalar {
2833 params!(Oid) => Operation::unary(|_ecx, _e| {
2834 Ok(HirScalarExpr::literal_null(SqlScalarType::String))
2835 }) => String, 3778;
2836 },
2837 "pg_typeof" => Scalar {
2838 params!(Any) => Operation::new(|ecx, exprs, params, _order_by| {
2839 let name = match ecx.scalar_type(&exprs[0]) {
2841 CoercibleScalarType::Uncoerced => "unknown".to_string(),
2842 CoercibleScalarType::Record(_) => "record".to_string(),
2843 CoercibleScalarType::Coerced(ty) => ecx.humanize_sql_scalar_type(&ty, true),
2844 };
2845
2846 coerce_args_to_types(ecx, exprs, params)?;
2850
2851 Ok(HirScalarExpr::literal(Datum::String(&name), SqlScalarType::String))
2856 }) => String, 1619;
2857 },
2858 "position" => Scalar {
2859 params!(String, String) => BinaryFunc::from(func::Position) => Int32, 849;
2860 },
2861 "pow" => Scalar {
2862 params!(Float64, Float64) =>
2863 Operation::nullary(|_ecx| catalog_name_only!("pow"))
2864 => Float64, 1346;
2865 },
2866 "power" => Scalar {
2867 params!(Float64, Float64) => BinaryFunc::from(func::Power) => Float64, 1368;
2868 params!(Numeric, Numeric) => BinaryFunc::from(func::PowerNumeric) => Numeric, 2169;
2869 },
2870 "quote_ident" => Scalar {
2871 params!(String) => UnaryFunc::QuoteIdent(func::QuoteIdent) => String, 1282;
2872 },
2873 "radians" => Scalar {
2874 params!(Float64) => UnaryFunc::Radians(func::Radians) => Float64, 1609;
2875 },
2876 "repeat" => Scalar {
2877 params!(String, Int32) => BinaryFunc::RepeatString(func::RepeatString) => String, 1622;
2878 },
2879 "regexp_match" => Scalar {
2880 params!(String, String) => VariadicFunc::from(variadic::RegexpMatch)
2881 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 3396;
2882 params!(String, String, String) => VariadicFunc::from(variadic::RegexpMatch)
2883 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 3397;
2884 },
2885 "replace" => Scalar {
2886 params!(String, String, String) => VariadicFunc::from(variadic::Replace)
2887 => String, 2087;
2888 },
2889 "right" => Scalar {
2890 params!(String, Int32) => BinaryFunc::from(func::Right) => String, 3061;
2891 },
2892 "round" => Scalar {
2893 params!(Float32) => UnaryFunc::RoundFloat32(func::RoundFloat32)
2894 => Float32, oid::FUNC_ROUND_F32_OID;
2895 params!(Float64) => UnaryFunc::RoundFloat64(func::RoundFloat64) => Float64, 1342;
2896 params!(Numeric) => UnaryFunc::RoundNumeric(func::RoundNumeric) => Numeric, 1708;
2897 params!(Numeric, Int32) => BinaryFunc::from(func::RoundNumericBinary) => Numeric, 1707;
2898 },
2899 "rtrim" => Scalar {
2900 params!(String) => UnaryFunc::TrimTrailingWhitespace(
2901 func::TrimTrailingWhitespace,
2902 ) => String, 882;
2903 params!(String, String) => BinaryFunc::from(func::TrimTrailing) => String, 876;
2904 },
2905 "sha224" => Scalar {
2906 params!(Bytes) => digest("sha224") => Bytes, 3419;
2907 },
2908 "sha256" => Scalar {
2909 params!(Bytes) => digest("sha256") => Bytes, 3420;
2910 },
2911 "sha384" => Scalar {
2912 params!(Bytes) => digest("sha384") => Bytes, 3421;
2913 },
2914 "sha512" => Scalar {
2915 params!(Bytes) => digest("sha512") => Bytes, 3422;
2916 },
2917 "sin" => Scalar {
2918 params!(Float64) => UnaryFunc::Sin(func::Sin) => Float64, 1604;
2919 },
2920 "asin" => Scalar {
2921 params!(Float64) => UnaryFunc::Asin(func::Asin) => Float64, 1600;
2922 },
2923 "sinh" => Scalar {
2924 params!(Float64) => UnaryFunc::Sinh(func::Sinh) => Float64, 2462;
2925 },
2926 "asinh" => Scalar {
2927 params!(Float64) => UnaryFunc::Asinh(func::Asinh) => Float64, 2465;
2928 },
2929 "strpos" => Scalar {
2930 params!(String, String) => BinaryFunc::from(func::Strpos) => Int32, 868;
2931 },
2932 "split_part" => Scalar {
2933 params!(String, String, Int32) => VariadicFunc::from(variadic::SplitPart)
2934 => String, 2088;
2935 },
2936 "stddev" => Scalar {
2937 params!(Float32) =>
2938 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2939 => Float64, 2157;
2940 params!(Float64) =>
2941 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2942 => Float64, 2158;
2943 params!(Int16) =>
2944 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2945 => Numeric, 2156;
2946 params!(Int32) =>
2947 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2948 => Numeric, 2155;
2949 params!(Int64) =>
2950 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2951 => Numeric, 2154;
2952 params!(UInt16) =>
2953 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2954 => Numeric, oid::FUNC_STDDEV_UINT16_OID;
2955 params!(UInt32) =>
2956 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2957 => Numeric, oid::FUNC_STDDEV_UINT32_OID;
2958 params!(UInt64) =>
2959 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2960 => Numeric, oid::FUNC_STDDEV_UINT64_OID;
2961 },
2962 "stddev_pop" => Scalar {
2963 params!(Float32) =>
2964 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2965 => Float64, 2727;
2966 params!(Float64) =>
2967 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2968 => Float64, 2728;
2969 params!(Int16) =>
2970 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2971 => Numeric, 2726;
2972 params!(Int32) =>
2973 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2974 => Numeric, 2725;
2975 params!(Int64) =>
2976 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2977 => Numeric, 2724;
2978 params!(UInt16) =>
2979 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2980 => Numeric, oid::FUNC_STDDEV_POP_UINT16_OID;
2981 params!(UInt32) =>
2982 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2983 => Numeric, oid::FUNC_STDDEV_POP_UINT32_OID;
2984 params!(UInt64) =>
2985 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2986 => Numeric, oid::FUNC_STDDEV_POP_UINT64_OID;
2987 },
2988 "stddev_samp" => Scalar {
2989 params!(Float32) =>
2990 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
2991 => Float64, 2715;
2992 params!(Float64) =>
2993 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
2994 => Float64, 2716;
2995 params!(Int16) =>
2996 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
2997 => Numeric, 2714;
2998 params!(Int32) =>
2999 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
3000 => Numeric, 2713;
3001 params!(Int64) =>
3002 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
3003 => Numeric, 2712;
3004 params!(UInt16) =>
3005 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
3006 => Numeric, oid::FUNC_STDDEV_SAMP_UINT16_OID;
3007 params!(UInt32) =>
3008 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
3009 => Numeric, oid::FUNC_STDDEV_SAMP_UINT32_OID;
3010 params!(UInt64) =>
3011 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
3012 => Numeric, oid::FUNC_STDDEV_SAMP_UINT64_OID;
3013 },
3014 "substr" => Scalar {
3015 params!(String, Int32) => VariadicFunc::from(variadic::Substr) => String, 883;
3016 params!(String, Int32, Int32) => VariadicFunc::from(variadic::Substr) => String, 877;
3017 },
3018 "substring" => Scalar {
3019 params!(String, Int32) => VariadicFunc::from(variadic::Substr) => String, 937;
3020 params!(String, Int32, Int32) => VariadicFunc::from(variadic::Substr) => String, 936;
3021 },
3022 "sqrt" => Scalar {
3023 params!(Float64) => UnaryFunc::SqrtFloat64(func::SqrtFloat64) => Float64, 1344;
3024 params!(Numeric) => UnaryFunc::SqrtNumeric(func::SqrtNumeric) => Numeric, 1730;
3025 },
3026 "tan" => Scalar {
3027 params!(Float64) => UnaryFunc::Tan(func::Tan) => Float64, 1606;
3028 },
3029 "atan" => Scalar {
3030 params!(Float64) => UnaryFunc::Atan(func::Atan) => Float64, 1602;
3031 },
3032 "tanh" => Scalar {
3033 params!(Float64) => UnaryFunc::Tanh(func::Tanh) => Float64, 2464;
3034 },
3035 "atanh" => Scalar {
3036 params!(Float64) => UnaryFunc::Atanh(func::Atanh) => Float64, 2467;
3037 },
3038 "age" => Scalar {
3039 params!(Timestamp, Timestamp) => BinaryFunc::from(func::AgeTimestamp) => Interval, 2058;
3040 params!(TimestampTz, TimestampTz)
3041 => BinaryFunc::from(func::AgeTimestampTz) => Interval, 1199;
3042 },
3043 "timezone" => Scalar {
3044 params!(String, Timestamp)
3045 => BinaryFunc::TimezoneTimestampBinary(
3046 func::TimezoneTimestampBinary,
3047 ) => TimestampTz, 2069;
3048 params!(String, TimestampTz)
3049 => BinaryFunc::TimezoneTimestampTzBinary(
3050 func::TimezoneTimestampTzBinary,
3051 ) => Timestamp, 1159;
3052 params!(String, Time) => Operation::binary(|ecx, lhs, rhs| {
3054 ecx.require_feature_flag(&ENABLE_TIME_AT_TIME_ZONE)?;
3068 Ok(HirScalarExpr::call_variadic(
3069 variadic::TimezoneTimeVariadic,
3070 vec![
3071 lhs,
3072 rhs,
3073 HirScalarExpr::call_unmaterializable(
3074 UnmaterializableFunc::CurrentTimestamp,
3075 ),
3076 ],
3077 ))
3078 }) => Time, 2037;
3079 params!(Interval, Timestamp)
3080 => BinaryFunc::from(func::TimezoneIntervalTimestampBinary)
3081 => TimestampTz, 2070;
3082 params!(Interval, TimestampTz)
3083 => BinaryFunc::from(func::TimezoneIntervalTimestampTzBinary)
3084 => Timestamp, 1026;
3085 params!(Interval, Time)
3087 => BinaryFunc::from(func::TimezoneIntervalTimeBinary) => Time, 2038;
3088 },
3089 "to_char" => Scalar {
3090 params!(Timestamp, String)
3091 => BinaryFunc::from(func::ToCharTimestampFormat) => String, 2049;
3092 params!(TimestampTz, String)
3093 => BinaryFunc::from(func::ToCharTimestampTzFormat) => String, 1770;
3094 },
3095 "to_jsonb" => Scalar {
3106 params!(Any) => Operation::unary(|ecx, e| {
3107 let e = match ecx.scalar_type(&e) {
3109 SqlScalarType::Char { length } => {
3110 e.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
3111 }
3112 _ => e,
3113 };
3114 Ok(typeconv::to_jsonb(ecx, e))
3115 }) => Jsonb, 3787;
3116 },
3117 "to_timestamp" => Scalar {
3118 params!(Float64) => UnaryFunc::ToTimestamp(func::ToTimestamp) => TimestampTz, 1158;
3119 },
3120 "translate" => Scalar {
3121 params!(String, String, String) => VariadicFunc::from(variadic::Translate)
3122 => String, 878;
3123 },
3124 "trunc" => Scalar {
3125 params!(Float32) => UnaryFunc::TruncFloat32(func::TruncFloat32)
3126 => Float32, oid::FUNC_TRUNC_F32_OID;
3127 params!(Float64) => UnaryFunc::TruncFloat64(func::TruncFloat64) => Float64, 1343;
3128 params!(Numeric) => UnaryFunc::TruncNumeric(func::TruncNumeric) => Numeric, 1710;
3129 },
3130 "tsrange" => Scalar {
3131 params!(Timestamp, Timestamp) => Operation::variadic(|_ecx, mut exprs| {
3132 exprs.push(HirScalarExpr::literal(
3133 Datum::String("[)"), SqlScalarType::String,
3134 ));
3135 Ok(HirScalarExpr::call_variadic(
3136 variadic::RangeCreate {
3137 elem_type: SqlScalarType::Timestamp { precision: None },
3138 },
3139 exprs,
3140 ))
3141 }) => SqlScalarType::Range {
3142 element_type: Box::new(SqlScalarType::Timestamp { precision: None }),
3143 }, 3933;
3144 params!(Timestamp, Timestamp, String) => Operation::variadic(|_ecx, exprs| {
3145 Ok(HirScalarExpr::call_variadic(
3146 variadic::RangeCreate {
3147 elem_type: SqlScalarType::Timestamp { precision: None },
3148 },
3149 exprs,
3150 ))
3151 }) => SqlScalarType::Range {
3152 element_type: Box::new(SqlScalarType::Timestamp { precision: None }),
3153 }, 3934;
3154 },
3155 "tstzrange" => Scalar {
3156 params!(TimestampTz, TimestampTz) => Operation::variadic(|_ecx, mut exprs| {
3157 exprs.push(HirScalarExpr::literal(
3158 Datum::String("[)"), SqlScalarType::String,
3159 ));
3160 Ok(HirScalarExpr::call_variadic(
3161 variadic::RangeCreate {
3162 elem_type: SqlScalarType::TimestampTz { precision: None },
3163 },
3164 exprs,
3165 ))
3166 }) => SqlScalarType::Range {
3167 element_type: Box::new(SqlScalarType::TimestampTz { precision: None }),
3168 }, 3937;
3169 params!(TimestampTz, TimestampTz, String) => Operation::variadic(|_ecx, exprs| {
3170 Ok(HirScalarExpr::call_variadic(
3171 variadic::RangeCreate {
3172 elem_type: SqlScalarType::TimestampTz { precision: None },
3173 },
3174 exprs,
3175 ))
3176 }) => SqlScalarType::Range {
3177 element_type: Box::new(SqlScalarType::TimestampTz { precision: None }),
3178 }, 3938;
3179 },
3180 "upper" => Scalar {
3181 params!(String) => UnaryFunc::Upper(func::Upper) => String, 871;
3182 params!(RangeAny) => UnaryFunc::RangeUpper(func::RangeUpper) => AnyElement, 3849;
3183 },
3184 "upper_inc" => Scalar {
3185 params!(RangeAny) => UnaryFunc::RangeUpperInc(func::RangeUpperInc) => Bool, 3852;
3186 },
3187 "upper_inf" => Scalar {
3188 params!(RangeAny) => UnaryFunc::RangeUpperInf(func::RangeUpperInf) => Bool, 3854;
3189 },
3190 "uuid_generate_v5" => Scalar {
3191 params!(Uuid, String) => BinaryFunc::from(func::UuidGenerateV5)
3192 => Uuid, oid::FUNC_PG_UUID_GENERATE_V5;
3193 },
3194 "variance" => Scalar {
3195 params!(Float32) =>
3196 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3197 => Float64, 2151;
3198 params!(Float64) =>
3199 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3200 => Float64, 2152;
3201 params!(Int16) =>
3202 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3203 => Numeric, 2150;
3204 params!(Int32) =>
3205 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3206 => Numeric, 2149;
3207 params!(Int64) =>
3208 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3209 => Numeric, 2148;
3210 params!(UInt16) =>
3211 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3212 => Numeric, oid::FUNC_VARIANCE_UINT16_OID;
3213 params!(UInt32) =>
3214 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3215 => Numeric, oid::FUNC_VARIANCE_UINT32_OID;
3216 params!(UInt64) =>
3217 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3218 => Numeric, oid::FUNC_VARIANCE_UINT64_OID;
3219 },
3220 "var_pop" => Scalar {
3221 params!(Float32) =>
3222 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3223 => Float64, 2721;
3224 params!(Float64) =>
3225 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3226 => Float64, 2722;
3227 params!(Int16) =>
3228 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3229 => Numeric, 2720;
3230 params!(Int32) =>
3231 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3232 => Numeric, 2719;
3233 params!(Int64) =>
3234 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3235 => Numeric, 2718;
3236 params!(UInt16) =>
3237 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3238 => Numeric, oid::FUNC_VAR_POP_UINT16_OID;
3239 params!(UInt32) =>
3240 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3241 => Numeric, oid::FUNC_VAR_POP_UINT32_OID;
3242 params!(UInt64) =>
3243 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3244 => Numeric, oid::FUNC_VAR_POP_UINT64_OID;
3245 },
3246 "var_samp" => Scalar {
3247 params!(Float32) =>
3248 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3249 => Float64, 2644;
3250 params!(Float64) =>
3251 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3252 => Float64, 2645;
3253 params!(Int16) =>
3254 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3255 => Numeric, 2643;
3256 params!(Int32) =>
3257 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3258 => Numeric, 2642;
3259 params!(Int64) =>
3260 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3261 => Numeric, 2641;
3262 params!(UInt16) =>
3263 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3264 => Numeric, oid::FUNC_VAR_SAMP_UINT16_OID;
3265 params!(UInt32) =>
3266 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3267 => Numeric, oid::FUNC_VAR_SAMP_UINT32_OID;
3268 params!(UInt64) =>
3269 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3270 => Numeric, oid::FUNC_VAR_SAMP_UINT64_OID;
3271 },
3272 "version" => Scalar {
3273 params!() => UnmaterializableFunc::Version => String, 89;
3274 },
3275
3276 "aclitemin" => Scalar {
3278 params!(String) => Operation::variadic(|_ecx, _exprs| {
3279 bail_unsupported!("aclitemin")
3280 }) => AclItem, 1031;
3281 },
3282 "any_in" => Scalar {
3283 params!(String) => Operation::variadic(|_ecx, _exprs| {
3284 bail_unsupported!("any_in")
3285 }) => Any, 2294;
3286 },
3287 "anyarray_in" => Scalar {
3288 params!(String) => Operation::variadic(|_ecx, _exprs| {
3289 bail_unsupported!("anyarray_in")
3290 }) => ArrayAny, 2296;
3291 },
3292 "anycompatible_in" => Scalar {
3293 params!(String) => Operation::variadic(|_ecx, _exprs| {
3294 bail_unsupported!("anycompatible_in")
3295 }) => AnyCompatible, 5086;
3296 },
3297 "anycompatiblearray_in" => Scalar {
3298 params!(String) => Operation::variadic(|_ecx, _exprs| {
3299 bail_unsupported!("anycompatiblearray_in")
3300 }) => ArrayAnyCompatible, 5088;
3301 },
3302 "anycompatiblenonarray_in" => Scalar {
3303 params!(String) => Operation::variadic(|_ecx, _exprs| {
3304 bail_unsupported!("anycompatiblenonarray_in")
3305 }) => NonVecAnyCompatible, 5092;
3306 },
3307 "anycompatiblerange_in" => Scalar {
3308 params!(String, Oid, Int32) =>
3309 Operation::variadic(|_ecx, _exprs| {
3310 bail_unsupported!("anycompatiblerange_in")
3311 }) => RangeAnyCompatible, 5094;
3312 },
3313 "anyelement_in" => Scalar {
3314 params!(String) => Operation::variadic(|_ecx, _exprs| {
3315 bail_unsupported!("anyelement_in")
3316 }) => AnyElement, 2312;
3317 },
3318 "anynonarray_in" => Scalar {
3319 params!(String) => Operation::variadic(|_ecx, _exprs| {
3320 bail_unsupported!("anynonarray_in")
3321 }) => NonVecAny, 2777;
3322 },
3323 "anyrange_in" => Scalar {
3324 params!(String, Oid, Int32) =>
3325 Operation::variadic(|_ecx, _exprs| {
3326 bail_unsupported!("anyrange_in")
3327 }) => RangeAny, 3832;
3328 },
3329 "array_in" => Scalar {
3330 params!(String, Oid, Int32) =>
3331 Operation::variadic(|_ecx, _exprs| {
3332 bail_unsupported!("array_in")
3333 }) => ArrayAny, 750;
3334 },
3335 "boolin" => Scalar {
3336 params!(String) => Operation::variadic(|_ecx, _exprs| {
3337 bail_unsupported!("boolin")
3338 }) => Bool, 1242;
3339 },
3340 "bpcharin" => Scalar {
3341 params!(String, Oid, Int32) =>
3342 Operation::variadic(|_ecx, _exprs| {
3343 bail_unsupported!("bpcharin")
3344 }) => Char, 1044;
3345 },
3346 "byteain" => Scalar {
3347 params!(String) => Operation::variadic(|_ecx, _exprs| {
3348 bail_unsupported!("byteain")
3349 }) => Bytes, 1244;
3350 },
3351 "charin" => Scalar {
3352 params!(String) => Operation::variadic(|_ecx, _exprs| {
3353 bail_unsupported!("charin")
3354 }) => PgLegacyChar, 1245;
3355 },
3356 "date_in" => Scalar {
3357 params!(String) => Operation::variadic(|_ecx, _exprs| {
3358 bail_unsupported!("date_in")
3359 }) => Date, 1084;
3360 },
3361 "float4in" => Scalar {
3362 params!(String) => Operation::variadic(|_ecx, _exprs| {
3363 bail_unsupported!("float4in")
3364 }) => Float32, 200;
3365 },
3366 "float8in" => Scalar {
3367 params!(String) => Operation::variadic(|_ecx, _exprs| {
3368 bail_unsupported!("float8in")
3369 }) => Float64, 214;
3370 },
3371 "int2in" => Scalar {
3372 params!(String) => Operation::variadic(|_ecx, _exprs| {
3373 bail_unsupported!("int2in")
3374 }) => Int16, 38;
3375 },
3376 "int2vectorin" => Scalar {
3377 params!(String) => Operation::variadic(|_ecx, _exprs| {
3378 bail_unsupported!("int2vectorin")
3379 }) => Int2Vector, 40;
3380 },
3381 "int4in" => Scalar {
3382 params!(String) => Operation::variadic(|_ecx, _exprs| {
3383 bail_unsupported!("int4in")
3384 }) => Int32, 42;
3385 },
3386 "int8in" => Scalar {
3387 params!(String) => Operation::variadic(|_ecx, _exprs| {
3388 bail_unsupported!("int8in")
3389 }) => Int64, 460;
3390 },
3391 "internal_in" => Scalar {
3392 params!(String) => Operation::variadic(|_ecx, _exprs| {
3393 bail_unsupported!("internal_in")
3394 }) => Internal, 2304;
3395 },
3396 "interval_in" => Scalar {
3397 params!(String, Oid, Int32) =>
3398 Operation::variadic(|_ecx, _exprs| {
3399 bail_unsupported!("interval_in")
3400 }) => Interval, 1160;
3401 },
3402 "jsonb_in" => Scalar {
3403 params!(String) => Operation::variadic(|_ecx, _exprs| {
3404 bail_unsupported!("jsonb_in")
3405 }) => Jsonb, 3806;
3406 },
3407 "namein" => Scalar {
3408 params!(String) => Operation::variadic(|_ecx, _exprs| {
3409 bail_unsupported!("namein")
3410 }) => PgLegacyName, 34;
3411 },
3412 "numeric_in" => Scalar {
3413 params!(String, Oid, Int32) =>
3414 Operation::variadic(|_ecx, _exprs| {
3415 bail_unsupported!("numeric_in")
3416 }) => Numeric, 1701;
3417 },
3418 "oidin" => Scalar {
3419 params!(String) => Operation::variadic(|_ecx, _exprs| {
3420 bail_unsupported!("oidin")
3421 }) => Oid, 1798;
3422 },
3423 "range_in" => Scalar {
3424 params!(String, Oid, Int32) =>
3425 Operation::variadic(|_ecx, _exprs| {
3426 bail_unsupported!("range_in")
3427 }) => RangeAny, 3834;
3428 },
3429 "record_in" => Scalar {
3430 params!(String, Oid, Int32) =>
3431 Operation::variadic(|_ecx, _exprs| {
3432 bail_unsupported!("record_in")
3433 }) => RecordAny, 2290;
3434 },
3435 "regclassin" => Scalar {
3436 params!(String) => Operation::variadic(|_ecx, _exprs| {
3437 bail_unsupported!("regclassin")
3438 }) => RegClass, 2218;
3439 },
3440 "regprocin" => Scalar {
3441 params!(String) => Operation::variadic(|_ecx, _exprs| {
3442 bail_unsupported!("regprocin")
3443 }) => RegProc, 44;
3444 },
3445 "regtypein" => Scalar {
3446 params!(String) => Operation::variadic(|_ecx, _exprs| {
3447 bail_unsupported!("regtypein")
3448 }) => RegType, 2220;
3449 },
3450 "textin" => Scalar {
3451 params!(String) => Operation::variadic(|_ecx, _exprs| {
3452 bail_unsupported!("textin")
3453 }) => String, 46;
3454 },
3455 "time_in" => Scalar {
3456 params!(String, Oid, Int32) =>
3457 Operation::variadic(|_ecx, _exprs| {
3458 bail_unsupported!("time_in")
3459 }) => Time, 1143;
3460 },
3461 "timestamp_in" => Scalar {
3462 params!(String, Oid, Int32) =>
3463 Operation::variadic(|_ecx, _exprs| {
3464 bail_unsupported!("timestamp_in")
3465 }) => Timestamp, 1312;
3466 },
3467 "timestamptz_in" => Scalar {
3468 params!(String, Oid, Int32) =>
3469 Operation::variadic(|_ecx, _exprs| {
3470 bail_unsupported!("timestamptz_in")
3471 }) => TimestampTz, 1150;
3472 },
3473 "varcharin" => Scalar {
3474 params!(String, Oid, Int32) =>
3475 Operation::variadic(|_ecx, _exprs| {
3476 bail_unsupported!("varcharin")
3477 }) => VarChar, 1046;
3478 },
3479 "uuid_in" => Scalar {
3480 params!(String) => Operation::variadic(|_ecx, _exprs| {
3481 bail_unsupported!("uuid_in")
3482 }) => Uuid, 2952;
3483 },
3484 "boolrecv" => Scalar {
3485 params!(Internal) =>
3486 Operation::nullary(|_ecx| catalog_name_only!("boolrecv"))
3487 => Bool, 2436;
3488 },
3489 "textrecv" => Scalar {
3490 params!(Internal) =>
3491 Operation::nullary(|_ecx| catalog_name_only!("textrecv"))
3492 => String, 2414;
3493 },
3494 "anyarray_recv" => Scalar {
3495 params!(Internal) =>
3496 Operation::nullary(|_ecx| {
3497 catalog_name_only!("anyarray_recv")
3498 }) => ArrayAny, 2502;
3499 },
3500 "bytearecv" => Scalar {
3501 params!(Internal) =>
3502 Operation::nullary(|_ecx| catalog_name_only!("bytearecv"))
3503 => Bytes, 2412;
3504 },
3505 "bpcharrecv" => Scalar {
3506 params!(Internal) =>
3507 Operation::nullary(|_ecx| {
3508 catalog_name_only!("bpcharrecv")
3509 }) => Char, 2430;
3510 },
3511 "charrecv" => Scalar {
3512 params!(Internal) =>
3513 Operation::nullary(|_ecx| catalog_name_only!("charrecv"))
3514 => PgLegacyChar, 2434;
3515 },
3516 "date_recv" => Scalar {
3517 params!(Internal) =>
3518 Operation::nullary(|_ecx| catalog_name_only!("date_recv"))
3519 => Date, 2468;
3520 },
3521 "float4recv" => Scalar {
3522 params!(Internal) =>
3523 Operation::nullary(|_ecx| {
3524 catalog_name_only!("float4recv")
3525 }) => Float32, 2424;
3526 },
3527 "float8recv" => Scalar {
3528 params!(Internal) =>
3529 Operation::nullary(|_ecx| {
3530 catalog_name_only!("float8recv")
3531 }) => Float64, 2426;
3532 },
3533 "int4recv" => Scalar {
3534 params!(Internal) =>
3535 Operation::nullary(|_ecx| catalog_name_only!("int4recv"))
3536 => Int32, 2406;
3537 },
3538 "int8recv" => Scalar {
3539 params!(Internal) =>
3540 Operation::nullary(|_ecx| catalog_name_only!("int8recv"))
3541 => Int64, 2408;
3542 },
3543 "interval_recv" => Scalar {
3544 params!(Internal) =>
3545 Operation::nullary(|_ecx| {
3546 catalog_name_only!("interval_recv")
3547 }) => Interval, 2478;
3548 },
3549 "jsonb_recv" => Scalar {
3550 params!(Internal) =>
3551 Operation::nullary(|_ecx| {
3552 catalog_name_only!("jsonb_recv")
3553 }) => Jsonb, 3805;
3554 },
3555 "namerecv" => Scalar {
3556 params!(Internal) =>
3557 Operation::nullary(|_ecx| catalog_name_only!("namerecv"))
3558 => PgLegacyName, 2422;
3559 },
3560 "numeric_recv" => Scalar {
3561 params!(Internal) =>
3562 Operation::nullary(|_ecx| {
3563 catalog_name_only!("numeric_recv")
3564 }) => Numeric, 2460;
3565 },
3566 "oidrecv" => Scalar {
3567 params!(Internal) =>
3568 Operation::nullary(|_ecx| catalog_name_only!("oidrecv"))
3569 => Oid, 2418;
3570 },
3571 "record_recv" => Scalar {
3572 params!(Internal) =>
3573 Operation::nullary(|_ecx| {
3574 catalog_name_only!("recordrerecord_recvcv")
3575 }) => RecordAny, 2402;
3576 },
3577 "regclassrecv" => Scalar {
3578 params!(Internal) =>
3579 Operation::nullary(|_ecx| {
3580 catalog_name_only!("regclassrecv")
3581 }) => RegClass, 2452;
3582 },
3583 "regprocrecv" => Scalar {
3584 params!(Internal) =>
3585 Operation::nullary(|_ecx| {
3586 catalog_name_only!("regprocrecv")
3587 }) => RegProc, 2444;
3588 },
3589 "regtyperecv" => Scalar {
3590 params!(Internal) =>
3591 Operation::nullary(|_ecx| {
3592 catalog_name_only!("regtyperecv")
3593 }) => RegType, 2454;
3594 },
3595 "int2recv" => Scalar {
3596 params!(Internal) =>
3597 Operation::nullary(|_ecx| catalog_name_only!("int2recv"))
3598 => Int16, 2404;
3599 },
3600 "time_recv" => Scalar {
3601 params!(Internal) =>
3602 Operation::nullary(|_ecx| catalog_name_only!("time_recv"))
3603 => Time, 2470;
3604 },
3605 "timestamp_recv" => Scalar {
3606 params!(Internal) =>
3607 Operation::nullary(|_ecx| {
3608 catalog_name_only!("timestamp_recv")
3609 }) => Timestamp, 2474;
3610 },
3611 "timestamptz_recv" => Scalar {
3612 params!(Internal) =>
3613 Operation::nullary(|_ecx| {
3614 catalog_name_only!("timestamptz_recv")
3615 }) => TimestampTz, 2476;
3616 },
3617 "uuid_recv" => Scalar {
3618 params!(Internal) =>
3619 Operation::nullary(|_ecx| catalog_name_only!("uuid_recv"))
3620 => Uuid, 2961;
3621 },
3622 "varcharrecv" => Scalar {
3623 params!(Internal) =>
3624 Operation::nullary(|_ecx| {
3625 catalog_name_only!("varcharrecv")
3626 }) => VarChar, 2432;
3627 },
3628 "int2vectorrecv" => Scalar {
3629 params!(Internal) =>
3630 Operation::nullary(|_ecx| {
3631 catalog_name_only!("int2vectorrecv")
3632 }) => Int2Vector, 2410;
3633 },
3634 "anycompatiblearray_recv" => Scalar {
3635 params!(Internal) =>
3636 Operation::nullary(|_ecx| {
3637 catalog_name_only!("anycompatiblearray_recv")
3638 }) => ArrayAnyCompatible, 5090;
3639 },
3640 "array_recv" => Scalar {
3641 params!(Internal) =>
3642 Operation::nullary(|_ecx| {
3643 catalog_name_only!("array_recv")
3644 }) => ArrayAny, 2400;
3645 },
3646 "range_recv" => Scalar {
3647 params!(Internal) =>
3648 Operation::nullary(|_ecx| {
3649 catalog_name_only!("range_recv")
3650 }) => RangeAny, 3836;
3651 },
3652
3653
3654 "array_agg" => Aggregate {
3656 params!(NonVecAny) => Operation::unary_ordered(|ecx, e, order_by| {
3657 let elem_type = ecx.scalar_type(&e);
3658
3659 let elem_type = match elem_type.array_of_self_elem_type() {
3660 Ok(elem_type) => elem_type,
3661 Err(elem_type) => bail_unsupported!(
3662 format!("array_agg on {}", ecx.humanize_sql_scalar_type(&elem_type, false))
3663 ),
3664 };
3665
3666 let e_arr = HirScalarExpr::call_variadic(
3669 variadic::ArrayCreate { elem_type },
3670 vec![e],
3671 );
3672 Ok((e_arr, AggregateFunc::ArrayConcat { order_by }))
3673 }) => ArrayAny, 2335;
3674 params!(ArrayAny) => Operation::unary(|_ecx, _e| {
3675 bail_unsupported!("array_agg on arrays")
3676 }) => ArrayAny, 4053;
3677 },
3678 "bool_and" => Aggregate {
3679 params!(Bool) =>
3680 Operation::nullary(|_ecx| catalog_name_only!("bool_and"))
3681 => Bool, 2517;
3682 },
3683 "bool_or" => Aggregate {
3684 params!(Bool) => Operation::nullary(|_ecx| catalog_name_only!("bool_or")) => Bool, 2518;
3685 },
3686 "count" => Aggregate {
3687 params!() => Operation::nullary(|_ecx| {
3688 Ok((HirScalarExpr::literal_true(), AggregateFunc::Count))
3692 }) => Int64, 2803;
3693 params!(Any) => AggregateFunc::Count => Int64, 2147;
3694 },
3695 "max" => Aggregate {
3696 params!(Bool) => AggregateFunc::MaxBool => Bool, oid::FUNC_MAX_BOOL_OID;
3697 params!(Int16) => AggregateFunc::MaxInt16 => Int16, 2117;
3698 params!(Int32) => AggregateFunc::MaxInt32 => Int32, 2116;
3699 params!(Int64) => AggregateFunc::MaxInt64 => Int64, 2115;
3700 params!(UInt16) => AggregateFunc::MaxUInt16 => UInt16, oid::FUNC_MAX_UINT16_OID;
3701 params!(UInt32) => AggregateFunc::MaxUInt32 => UInt32, oid::FUNC_MAX_UINT32_OID;
3702 params!(UInt64) => AggregateFunc::MaxUInt64 => UInt64, oid::FUNC_MAX_UINT64_OID;
3703 params!(MzTimestamp) => AggregateFunc::MaxMzTimestamp
3704 => MzTimestamp, oid::FUNC_MAX_MZ_TIMESTAMP_OID;
3705 params!(Float32) => AggregateFunc::MaxFloat32 => Float32, 2119;
3706 params!(Float64) => AggregateFunc::MaxFloat64 => Float64, 2120;
3707 params!(String) => AggregateFunc::MaxString => String, 2129;
3708 params!(Char) => AggregateFunc::MaxString => Char, 2244;
3710 params!(Date) => AggregateFunc::MaxDate => Date, 2122;
3711 params!(Timestamp) => AggregateFunc::MaxTimestamp => Timestamp, 2126;
3712 params!(TimestampTz) => AggregateFunc::MaxTimestampTz => TimestampTz, 2127;
3713 params!(Numeric) => AggregateFunc::MaxNumeric => Numeric, oid::FUNC_MAX_NUMERIC_OID;
3714 params!(Interval) => AggregateFunc::MaxInterval => Interval, 2128;
3715 params!(Time) => AggregateFunc::MaxTime => Time, 2123;
3716 },
3717 "min" => Aggregate {
3718 params!(Bool) => AggregateFunc::MinBool => Bool, oid::FUNC_MIN_BOOL_OID;
3719 params!(Int16) => AggregateFunc::MinInt16 => Int16, 2133;
3720 params!(Int32) => AggregateFunc::MinInt32 => Int32, 2132;
3721 params!(Int64) => AggregateFunc::MinInt64 => Int64, 2131;
3722 params!(UInt16) => AggregateFunc::MinUInt16 => UInt16, oid::FUNC_MIN_UINT16_OID;
3723 params!(UInt32) => AggregateFunc::MinUInt32 => UInt32, oid::FUNC_MIN_UINT32_OID;
3724 params!(UInt64) => AggregateFunc::MinUInt64 => UInt64, oid::FUNC_MIN_UINT64_OID;
3725 params!(MzTimestamp) => AggregateFunc::MinMzTimestamp
3726 => MzTimestamp, oid::FUNC_MIN_MZ_TIMESTAMP_OID;
3727 params!(Float32) => AggregateFunc::MinFloat32 => Float32, 2135;
3728 params!(Float64) => AggregateFunc::MinFloat64 => Float64, 2136;
3729 params!(String) => AggregateFunc::MinString => String, 2145;
3730 params!(Char) => AggregateFunc::MinString => Char, 2245;
3732 params!(Date) => AggregateFunc::MinDate => Date, 2138;
3733 params!(Timestamp) => AggregateFunc::MinTimestamp => Timestamp, 2142;
3734 params!(TimestampTz) => AggregateFunc::MinTimestampTz => TimestampTz, 2143;
3735 params!(Numeric) => AggregateFunc::MinNumeric => Numeric, oid::FUNC_MIN_NUMERIC_OID;
3736 params!(Interval) => AggregateFunc::MinInterval => Interval, 2144;
3737 params!(Time) => AggregateFunc::MinTime => Time, 2139;
3738 },
3739 "jsonb_agg" => Aggregate {
3740 params!(Any) => Operation::unary_ordered(|ecx, e, order_by| {
3741 let e = match ecx.scalar_type(&e) {
3743 SqlScalarType::Char { length } => {
3744 e.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
3745 }
3746 _ => e,
3747 };
3748 let json_null = HirScalarExpr::literal(Datum::JsonNull, SqlScalarType::Jsonb);
3754 let e = HirScalarExpr::call_variadic(
3755 variadic::Coalesce,
3756 vec![typeconv::to_jsonb(ecx, e), json_null],
3757 );
3758 Ok((e, AggregateFunc::JsonbAgg { order_by }))
3759 }) => Jsonb, 3267;
3760 },
3761 "jsonb_object_agg" => Aggregate {
3762 params!(Any, Any) => Operation::binary_ordered(|ecx, key, val, order_by| {
3763 let key = match ecx.scalar_type(&key) {
3765 SqlScalarType::Char { length } => {
3766 key.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
3767 }
3768 _ => key,
3769 };
3770 let val = match ecx.scalar_type(&val) {
3771 SqlScalarType::Char { length } => {
3772 val.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
3773 }
3774 _ => val,
3775 };
3776
3777 let json_null = HirScalarExpr::literal(Datum::JsonNull, SqlScalarType::Jsonb);
3778 let key = typeconv::to_string(ecx, key);
3779 let val = HirScalarExpr::call_variadic(
3786 variadic::Coalesce,
3787 vec![typeconv::to_jsonb(ecx, val), json_null],
3788 );
3789 let e = HirScalarExpr::call_variadic(
3790 variadic::RecordCreate {
3791 field_names: vec![ColumnName::from("key"), ColumnName::from("val")],
3792 },
3793 vec![key, val],
3794 );
3795 Ok((e, AggregateFunc::JsonbObjectAgg { order_by }))
3796 }) => Jsonb, 3270;
3797 },
3798 "string_agg" => Aggregate {
3799 params!(String, String) => Operation::binary_ordered(|_ecx, value, sep, order_by| {
3800 let e = HirScalarExpr::call_variadic(
3801 variadic::RecordCreate {
3802 field_names: vec![ColumnName::from("value"), ColumnName::from("sep")],
3803 },
3804 vec![value, sep],
3805 );
3806 Ok((e, AggregateFunc::StringAgg { order_by }))
3807 }) => String, 3538;
3808 params!(Bytes, Bytes) =>
3809 Operation::binary(|_ecx, _l, _r| {
3810 bail_unsupported!("string_agg on BYTEA")
3811 }) => Bytes, 3545;
3812 },
3813 "string_to_array" => Scalar {
3814 params!(String, String) => VariadicFunc::from(variadic::StringToArray)
3815 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 376;
3816 params!(String, String, String) => VariadicFunc::from(variadic::StringToArray)
3817 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 394;
3818 },
3819 "sum" => Aggregate {
3820 params!(Int16) => AggregateFunc::SumInt16 => Int64, 2109;
3821 params!(Int32) => AggregateFunc::SumInt32 => Int64, 2108;
3822 params!(Int64) => AggregateFunc::SumInt64 => Numeric, 2107;
3823 params!(UInt16) => AggregateFunc::SumUInt16 => UInt64, oid::FUNC_SUM_UINT16_OID;
3824 params!(UInt32) => AggregateFunc::SumUInt32 => UInt64, oid::FUNC_SUM_UINT32_OID;
3825 params!(UInt64) => AggregateFunc::SumUInt64 => Numeric, oid::FUNC_SUM_UINT64_OID;
3826 params!(Float32) => AggregateFunc::SumFloat32 => Float32, 2110;
3827 params!(Float64) => AggregateFunc::SumFloat64 => Float64, 2111;
3828 params!(Numeric) => AggregateFunc::SumNumeric => Numeric, 2114;
3829 params!(Interval) => Operation::unary(|_ecx, _e| {
3830 bail_unsupported!("sum(interval)");
3835 }) => Interval, 2113;
3836 },
3837
3838 "row_number" => ScalarWindow {
3840 params!() => ScalarWindowFunc::RowNumber => Int64, 3100;
3841 },
3842 "rank" => ScalarWindow {
3843 params!() => ScalarWindowFunc::Rank => Int64, 3101;
3844 },
3845 "dense_rank" => ScalarWindow {
3846 params!() => ScalarWindowFunc::DenseRank => Int64, 3102;
3847 },
3848 "lag" => ValueWindow {
3849 params!(AnyElement) => Operation::unary(|ecx, e| {
3851 let typ = ecx.scalar_type(&e);
3852 let e = HirScalarExpr::call_variadic(
3853 variadic::RecordCreate {
3854 field_names: vec![
3855 ColumnName::from("expr"),
3856 ColumnName::from("offset"),
3857 ColumnName::from("default"),
3858 ],
3859 },
3860 vec![
3861 e,
3862 HirScalarExpr::literal(Datum::Int32(1), SqlScalarType::Int32),
3863 HirScalarExpr::literal_null(typ),
3864 ],
3865 );
3866 Ok((e, ValueWindowFunc::Lag))
3867 }) => AnyElement, 3106;
3868 params!(AnyElement, Int32) => Operation::binary(|ecx, e, offset| {
3869 let typ = ecx.scalar_type(&e);
3870 let e = HirScalarExpr::call_variadic(
3871 variadic::RecordCreate {
3872 field_names: vec![
3873 ColumnName::from("expr"),
3874 ColumnName::from("offset"),
3875 ColumnName::from("default"),
3876 ],
3877 },
3878 vec![e, offset, HirScalarExpr::literal_null(typ)],
3879 );
3880 Ok((e, ValueWindowFunc::Lag))
3881 }) => AnyElement, 3107;
3882 params!(AnyCompatible, Int32, AnyCompatible) => Operation::variadic(|_ecx, exprs| {
3883 let e = HirScalarExpr::call_variadic(
3884 variadic::RecordCreate {
3885 field_names: vec![
3886 ColumnName::from("expr"),
3887 ColumnName::from("offset"),
3888 ColumnName::from("default"),
3889 ],
3890 },
3891 exprs,
3892 );
3893 Ok((e, ValueWindowFunc::Lag))
3894 }) => AnyCompatible, 3108;
3895 },
3896 "lead" => ValueWindow {
3897 params!(AnyElement) => Operation::unary(|ecx, e| {
3899 let typ = ecx.scalar_type(&e);
3900 let e = HirScalarExpr::call_variadic(
3901 variadic::RecordCreate {
3902 field_names: vec![
3903 ColumnName::from("expr"),
3904 ColumnName::from("offset"),
3905 ColumnName::from("default"),
3906 ],
3907 },
3908 vec![
3909 e,
3910 HirScalarExpr::literal(Datum::Int32(1), SqlScalarType::Int32),
3911 HirScalarExpr::literal_null(typ),
3912 ],
3913 );
3914 Ok((e, ValueWindowFunc::Lead))
3915 }) => AnyElement, 3109;
3916 params!(AnyElement, Int32) => Operation::binary(|ecx, e, offset| {
3917 let typ = ecx.scalar_type(&e);
3918 let e = HirScalarExpr::call_variadic(
3919 variadic::RecordCreate {
3920 field_names: vec![
3921 ColumnName::from("expr"),
3922 ColumnName::from("offset"),
3923 ColumnName::from("default"),
3924 ],
3925 },
3926 vec![e, offset, HirScalarExpr::literal_null(typ)],
3927 );
3928 Ok((e, ValueWindowFunc::Lead))
3929 }) => AnyElement, 3110;
3930 params!(AnyCompatible, Int32, AnyCompatible) => Operation::variadic(|_ecx, exprs| {
3931 let e = HirScalarExpr::call_variadic(
3932 variadic::RecordCreate {
3933 field_names: vec![
3934 ColumnName::from("expr"),
3935 ColumnName::from("offset"),
3936 ColumnName::from("default"),
3937 ],
3938 },
3939 exprs,
3940 );
3941 Ok((e, ValueWindowFunc::Lead))
3942 }) => AnyCompatible, 3111;
3943 },
3944 "first_value" => ValueWindow {
3945 params!(AnyElement) => ValueWindowFunc::FirstValue => AnyElement, 3112;
3946 },
3947 "last_value" => ValueWindow {
3948 params!(AnyElement) => ValueWindowFunc::LastValue => AnyElement, 3113;
3949 },
3950
3951 "generate_series" => Table {
3953 params!(Int32, Int32, Int32) => Operation::variadic(move |_ecx, exprs| {
3954 Ok(TableFuncPlan {
3955 imp: TableFuncImpl::CallTable {
3956 func: TableFunc::GenerateSeriesInt32,
3957 exprs,
3958 },
3959 column_names: vec!["generate_series".into()],
3960 })
3961 }) => ReturnType::set_of(Int32.into()), 1066;
3962 params!(Int32, Int32) => Operation::binary(move |_ecx, start, stop| {
3963 Ok(TableFuncPlan {
3964 imp: TableFuncImpl::CallTable {
3965 func: TableFunc::GenerateSeriesInt32,
3966 exprs: vec![
3967 start, stop,
3968 HirScalarExpr::literal(Datum::Int32(1), SqlScalarType::Int32),
3969 ],
3970 },
3971 column_names: vec!["generate_series".into()],
3972 })
3973 }) => ReturnType::set_of(Int32.into()), 1067;
3974 params!(Int64, Int64, Int64) => Operation::variadic(move |_ecx, exprs| {
3975 Ok(TableFuncPlan {
3976 imp: TableFuncImpl::CallTable {
3977 func: TableFunc::GenerateSeriesInt64,
3978 exprs,
3979 },
3980 column_names: vec!["generate_series".into()],
3981 })
3982 }) => ReturnType::set_of(Int64.into()), 1068;
3983 params!(Int64, Int64) => Operation::binary(move |_ecx, start, stop| {
3984 Ok(TableFuncPlan {
3985 imp: TableFuncImpl::CallTable {
3986 func: TableFunc::GenerateSeriesInt64,
3987 exprs: vec![
3988 start, stop,
3989 HirScalarExpr::literal(Datum::Int64(1), SqlScalarType::Int64),
3990 ],
3991 },
3992 column_names: vec!["generate_series".into()],
3993 })
3994 }) => ReturnType::set_of(Int64.into()), 1069;
3995 params!(Timestamp, Timestamp, Interval) => Operation::variadic(move |_ecx, exprs| {
3996 Ok(TableFuncPlan {
3997 imp: TableFuncImpl::CallTable {
3998 func: TableFunc::GenerateSeriesTimestamp,
3999 exprs,
4000 },
4001 column_names: vec!["generate_series".into()],
4002 })
4003 }) => ReturnType::set_of(Timestamp.into()), 938;
4004 params!(TimestampTz, TimestampTz, Interval) => Operation::variadic(move |_ecx, exprs| {
4005 Ok(TableFuncPlan {
4006 imp: TableFuncImpl::CallTable {
4007 func: TableFunc::GenerateSeriesTimestampTz,
4008 exprs,
4009 },
4010 column_names: vec!["generate_series".into()],
4011 })
4012 }) => ReturnType::set_of(TimestampTz.into()), 939;
4013 },
4014
4015 "generate_subscripts" => Table {
4016 params!(ArrayAny, Int32) => Operation::variadic(move |_ecx, exprs| {
4017 Ok(TableFuncPlan {
4018 imp: TableFuncImpl::CallTable {
4019 func: TableFunc::GenerateSubscriptsArray,
4020 exprs,
4021 },
4022 column_names: vec!["generate_subscripts".into()],
4023 })
4024 }) => ReturnType::set_of(Int32.into()), 1192;
4025 },
4026
4027 "jsonb_array_elements" => Table {
4028 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
4029 Ok(TableFuncPlan {
4030 imp: TableFuncImpl::CallTable {
4031 func: TableFunc::JsonbArrayElements,
4032 exprs: vec![jsonb],
4033 },
4034 column_names: vec!["value".into()],
4035 })
4036 }) => ReturnType::set_of(Jsonb.into()), 3219;
4037 },
4038 "jsonb_array_elements_text" => Table {
4039 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
4040 Ok(TableFuncPlan {
4041 imp: TableFuncImpl::CallTable {
4042 func: TableFunc::JsonbArrayElementsStringify,
4043 exprs: vec![jsonb],
4044 },
4045 column_names: vec!["value".into()],
4046 })
4047 }) => ReturnType::set_of(String.into()), 3465;
4048 },
4049 "jsonb_each" => Table {
4050 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
4051 Ok(TableFuncPlan {
4052 imp: TableFuncImpl::CallTable {
4053 func: TableFunc::JsonbEach,
4054 exprs: vec![jsonb],
4055 },
4056 column_names: vec!["key".into(), "value".into()],
4057 })
4058 }) => ReturnType::set_of(RecordAny), 3208;
4059 },
4060 "jsonb_each_text" => Table {
4061 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
4062 Ok(TableFuncPlan {
4063 imp: TableFuncImpl::CallTable {
4064 func: TableFunc::JsonbEachStringify,
4065 exprs: vec![jsonb],
4066 },
4067 column_names: vec!["key".into(), "value".into()],
4068 })
4069 }) => ReturnType::set_of(RecordAny), 3932;
4070 },
4071 "jsonb_object_keys" => Table {
4072 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
4073 Ok(TableFuncPlan {
4074 imp: TableFuncImpl::CallTable {
4075 func: TableFunc::JsonbObjectKeys,
4076 exprs: vec![jsonb],
4077 },
4078 column_names: vec!["jsonb_object_keys".into()],
4079 })
4080 }) => ReturnType::set_of(String.into()), 3931;
4081 },
4082 "date_bin_hopping" => Table {
4086 params!(Interval, Interval, Timestamp)
4088 => experimental_sql_impl_table_func(
4089 &vars::ENABLE_DATE_BIN_HOPPING, "
4090 SELECT *
4091 FROM pg_catalog.generate_series(
4092 pg_catalog.date_bin($1, $3 + $1, '1970-01-01') - $2, $3, $1
4093 ) AS dbh(date_bin_hopping)
4094 ") => ReturnType::set_of(Timestamp.into()),
4095 oid::FUNC_MZ_DATE_BIN_HOPPING_UNIX_EPOCH_TS_OID;
4096 params!(Interval, Interval, TimestampTz)
4098 => experimental_sql_impl_table_func(
4099 &vars::ENABLE_DATE_BIN_HOPPING, "
4100 SELECT *
4101 FROM pg_catalog.generate_series(
4102 pg_catalog.date_bin($1, $3 + $1, '1970-01-01') - $2, $3, $1
4103 ) AS dbh(date_bin_hopping)
4104 ") => ReturnType::set_of(TimestampTz.into()),
4105 oid::FUNC_MZ_DATE_BIN_HOPPING_UNIX_EPOCH_TSTZ_OID;
4106 params!(Interval, Interval, Timestamp, Timestamp)
4108 => experimental_sql_impl_table_func(
4109 &vars::ENABLE_DATE_BIN_HOPPING, "
4110 SELECT *
4111 FROM pg_catalog.generate_series(
4112 pg_catalog.date_bin($1, $3 + $1, $4) - $2, $3, $1
4113 ) AS dbh(date_bin_hopping)
4114 ") => ReturnType::set_of(Timestamp.into()),
4115 oid::FUNC_MZ_DATE_BIN_HOPPING_TS_OID;
4116 params!(Interval, Interval, TimestampTz, TimestampTz)
4118 => experimental_sql_impl_table_func(
4119 &vars::ENABLE_DATE_BIN_HOPPING, "
4120 SELECT *
4121 FROM pg_catalog.generate_series(
4122 pg_catalog.date_bin($1, $3 + $1, $4) - $2, $3, $1
4123 ) AS dbh(date_bin_hopping)
4124 ") => ReturnType::set_of(TimestampTz.into()),
4125 oid::FUNC_MZ_DATE_BIN_HOPPING_TSTZ_OID;
4126 },
4127 "encode" => Scalar {
4128 params!(Bytes, String) => BinaryFunc::from(func::Encode) => String, 1946;
4129 },
4130 "decode" => Scalar {
4131 params!(String, String) => BinaryFunc::from(func::Decode) => Bytes, 1947;
4132 },
4133 "regexp_split_to_array" => Scalar {
4134 params!(String, String) => VariadicFunc::from(variadic::RegexpSplitToArray)
4135 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 2767;
4136 params!(String, String, String) => VariadicFunc::from(variadic::RegexpSplitToArray)
4137 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 2768;
4138 },
4139 "regexp_split_to_table" => Table {
4140 params!(String, String) => sql_impl_table_func("
4141 SELECT unnest(regexp_split_to_array($1, $2))
4142 ") => ReturnType::set_of(String.into()), 2765;
4143 params!(String, String, String) => sql_impl_table_func("
4144 SELECT unnest(regexp_split_to_array($1, $2, $3))
4145 ") => ReturnType::set_of(String.into()), 2766;
4146 },
4147 "regexp_replace" => Scalar {
4148 params!(String, String, String)
4149 => VariadicFunc::from(variadic::RegexpReplace) => String, 2284;
4150 params!(String, String, String, String)
4151 => VariadicFunc::from(variadic::RegexpReplace) => String, 2285;
4152 },
4156 "regexp_matches" => Table {
4157 params!(String, String) => Operation::variadic(move |_ecx, exprs| {
4158 let column_names = vec!["regexp_matches".into()];
4159 Ok(TableFuncPlan {
4160 imp: TableFuncImpl::CallTable {
4161 func: TableFunc::RegexpMatches,
4162 exprs: vec![exprs[0].clone(), exprs[1].clone()],
4163 },
4164 column_names,
4165 })
4166 }) => ReturnType::set_of(
4167 SqlScalarType::Array(Box::new(SqlScalarType::String)).into(),
4168 ), 2763;
4169 params!(String, String, String) => Operation::variadic(move |_ecx, exprs| {
4170 let column_names = vec!["regexp_matches".into()];
4171 Ok(TableFuncPlan {
4172 imp: TableFuncImpl::CallTable {
4173 func: TableFunc::RegexpMatches,
4174 exprs: vec![exprs[0].clone(), exprs[1].clone(), exprs[2].clone()],
4175 },
4176 column_names,
4177 })
4178 }) => ReturnType::set_of(
4179 SqlScalarType::Array(Box::new(SqlScalarType::String)).into(),
4180 ), 2764;
4181 },
4182 "reverse" => Scalar {
4183 params!(String) => UnaryFunc::Reverse(func::Reverse) => String, 3062;
4184 }
4185 };
4186
4187 for sef_builtin in PG_CATALOG_SEF_BUILTINS.values() {
4191 builtins.insert(
4192 sef_builtin.name,
4193 Func::Scalar(vec![FuncImpl {
4194 oid: sef_builtin.oid,
4195 params: ParamList::Exact(
4196 sef_builtin
4197 .param_types
4198 .iter()
4199 .map(|t| ParamType::from(t.clone()))
4200 .collect(),
4201 ),
4202 return_type: ReturnType::scalar(ParamType::from(
4203 sef_builtin.return_type.scalar_type.clone(),
4204 )),
4205 op: Operation::variadic(|_ecx, _e| {
4206 bail_unsupported!(format!("{} in this position", sef_builtin.name))
4207 }),
4208 }]),
4209 );
4210 }
4211
4212 builtins
4213});
4214
4215pub static INFORMATION_SCHEMA_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> =
4216 LazyLock::new(|| {
4217 use ParamType::*;
4218 builtins! {
4219 "_pg_expandarray" => Table {
4220 params!(ArrayAny) => sql_impl_table_func("
4224 SELECT
4225 $1[s] AS x,
4226 s - pg_catalog.array_lower($1, 1) + 1 AS n
4227 FROM pg_catalog.generate_series(
4228 pg_catalog.array_lower($1, 1),
4229 pg_catalog.array_upper($1, 1),
4230 1) as g(s)
4231 ") => ReturnType::set_of(RecordAny), oid::FUNC_PG_EXPAND_ARRAY;
4232 }
4233 }
4234 });
4235
4236pub static MZ_CATALOG_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
4237 use ParamType::*;
4238 use SqlScalarBaseType::*;
4239 builtins! {
4240 "constant_time_eq" => Scalar {
4241 params!(Bytes, Bytes) => BinaryFunc::from(func::ConstantTimeEqBytes)
4242 => Bool, oid::FUNC_CONSTANT_TIME_EQ_BYTES_OID;
4243 params!(String, String) => BinaryFunc::from(func::ConstantTimeEqString)
4244 => Bool, oid::FUNC_CONSTANT_TIME_EQ_STRING_OID;
4245 },
4246 "avg_internal_v1" => Scalar {
4254 params!(Int64) =>
4255 Operation::nullary(|_ecx| {
4256 catalog_name_only!("avg_internal_v1")
4257 }) => Numeric,
4258 oid::FUNC_AVG_INTERNAL_V1_INT64_OID;
4259 params!(Int32) =>
4260 Operation::nullary(|_ecx| {
4261 catalog_name_only!("avg_internal_v1")
4262 }) => Numeric,
4263 oid::FUNC_AVG_INTERNAL_V1_INT32_OID;
4264 params!(Int16) =>
4265 Operation::nullary(|_ecx| {
4266 catalog_name_only!("avg_internal_v1")
4267 }) => Numeric,
4268 oid::FUNC_AVG_INTERNAL_V1_INT16_OID;
4269 params!(UInt64) =>
4270 Operation::nullary(|_ecx| {
4271 catalog_name_only!("avg_internal_v1")
4272 }) => Numeric,
4273 oid::FUNC_AVG_INTERNAL_V1_UINT64_OID;
4274 params!(UInt32) =>
4275 Operation::nullary(|_ecx| {
4276 catalog_name_only!("avg_internal_v1")
4277 }) => Numeric,
4278 oid::FUNC_AVG_INTERNAL_V1_UINT32_OID;
4279 params!(UInt16) =>
4280 Operation::nullary(|_ecx| {
4281 catalog_name_only!("avg_internal_v1")
4282 }) => Numeric,
4283 oid::FUNC_AVG_INTERNAL_V1_UINT16_OID;
4284 params!(Float32) =>
4285 Operation::nullary(|_ecx| {
4286 catalog_name_only!("avg_internal_v1")
4287 }) => Float64,
4288 oid::FUNC_AVG_INTERNAL_V1_FLOAT32_OID;
4289 params!(Float64) =>
4290 Operation::nullary(|_ecx| {
4291 catalog_name_only!("avg_internal_v1")
4292 }) => Float64,
4293 oid::FUNC_AVG_INTERNAL_V1_FLOAT64_OID;
4294 params!(Interval) =>
4295 Operation::nullary(|_ecx| {
4296 catalog_name_only!("avg_internal_v1")
4297 }) => Interval,
4298 oid::FUNC_AVG_INTERNAL_V1_INTERVAL_OID;
4299 },
4300 "csv_extract" => Table {
4301 params!(Int64, String) => Operation::binary(move |_ecx, ncols, input| {
4302 const MAX_EXTRACT_COLUMNS: i64 = 8192;
4303 const TOO_MANY_EXTRACT_COLUMNS: i64 = MAX_EXTRACT_COLUMNS + 1;
4304
4305 let ncols = match ncols.into_literal_int64() {
4306 None | Some(i64::MIN..=0) => {
4307 sql_bail!(
4308 "csv_extract number of columns \
4309 must be a positive integer literal"
4310 );
4311 },
4312 Some(ncols @ 1..=MAX_EXTRACT_COLUMNS) => ncols,
4313 Some(ncols @ TOO_MANY_EXTRACT_COLUMNS..) => {
4314 return Err(PlanError::TooManyColumns {
4315 max_num_columns: usize::try_from(MAX_EXTRACT_COLUMNS)
4316 .unwrap_or(usize::MAX),
4317 req_num_columns: usize::try_from(ncols)
4318 .unwrap_or(usize::MAX),
4319 });
4320 },
4321 };
4322 let ncols = usize::try_from(ncols).expect("known to be greater than zero");
4323
4324 let column_names = (1..=ncols).map(|i| format!("column{}", i).into()).collect();
4325 Ok(TableFuncPlan {
4326 imp: TableFuncImpl::CallTable {
4327 func: TableFunc::CsvExtract(ncols),
4328 exprs: vec![input],
4329 },
4330 column_names,
4331 })
4332 }) => ReturnType::set_of(RecordAny), oid::FUNC_CSV_EXTRACT_OID;
4333 },
4334 "concat_agg" => Aggregate {
4335 params!(Any) => Operation::unary(|_ecx, _e| {
4336 bail_unsupported!("concat_agg")
4337 }) => String, oid::FUNC_CONCAT_AGG_OID;
4338 },
4339 "crc32" => Scalar {
4340 params!(String) => UnaryFunc::Crc32String(func::Crc32String)
4341 => UInt32, oid::FUNC_CRC32_STRING_OID;
4342 params!(Bytes) => UnaryFunc::Crc32Bytes(func::Crc32Bytes)
4343 => UInt32, oid::FUNC_CRC32_BYTES_OID;
4344 },
4345 "datediff" => Scalar {
4346 params!(String, Timestamp, Timestamp)
4347 => VariadicFunc::from(variadic::DateDiffTimestamp)
4348 => Int64, oid::FUNC_DATEDIFF_TIMESTAMP;
4349 params!(String, TimestampTz, TimestampTz)
4350 => VariadicFunc::from(variadic::DateDiffTimestampTz)
4351 => Int64, oid::FUNC_DATEDIFF_TIMESTAMPTZ;
4352 params!(String, Date, Date) => VariadicFunc::from(variadic::DateDiffDate)
4353 => Int64, oid::FUNC_DATEDIFF_DATE;
4354 params!(String, Time, Time) => VariadicFunc::from(variadic::DateDiffTime)
4355 => Int64, oid::FUNC_DATEDIFF_TIME;
4356 },
4357 "has_cluster_privilege" => Scalar {
4360 params!(String, String, String) => sql_impl_func(
4361 "has_cluster_privilege(mz_internal.mz_role_oid($1), $2, $3)",
4362 ) => Bool, oid::FUNC_HAS_CLUSTER_PRIVILEGE_TEXT_TEXT_TEXT_OID;
4363 params!(Oid, String, String) => sql_impl_func(&format!("
4364 CASE
4365 -- We must first check $2 to avoid a potentially
4366 -- null error message (an error itself).
4367 WHEN $2 IS NULL
4368 THEN NULL
4369 -- Validate the cluster name to return a proper error.
4370 WHEN NOT EXISTS (
4371 SELECT name FROM mz_clusters WHERE name = $2)
4372 THEN mz_unsafe.mz_error_if_null(
4373 NULL::boolean,
4374 'error cluster \"' || $2 || '\" does not exist')
4375 -- Validate the privileges and other arguments.
4376 WHEN NOT mz_internal.mz_validate_privileges($3)
4377 OR $1 IS NULL
4378 OR $3 IS NULL
4379 OR $1 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
4380 THEN NULL
4381 ELSE COALESCE(
4382 (
4383 SELECT
4384 bool_or(
4385 mz_internal.mz_acl_item_contains_privilege(privilege, $3)
4386 )
4387 AS has_cluster_privilege
4388 FROM
4389 (
4390 SELECT
4391 unnest(privileges)
4392 FROM
4393 mz_clusters
4394 WHERE
4395 mz_clusters.name = $2
4396 )
4397 AS user_privs (privilege)
4398 LEFT JOIN mz_catalog.mz_roles ON
4399 mz_internal.mz_aclitem_grantee(privilege) = mz_roles.id
4400 WHERE
4401 mz_internal.mz_aclitem_grantee(privilege) = '{}'
4402 OR pg_has_role($1, mz_roles.oid, 'USAGE')
4403 ),
4404 false
4405 )
4406 END
4407 ", RoleId::Public))
4408 => Bool, oid::FUNC_HAS_CLUSTER_PRIVILEGE_OID_TEXT_TEXT_OID;
4409 params!(String, String) => sql_impl_func(
4410 "has_cluster_privilege(current_user, $1, $2)",
4411 ) => Bool, oid::FUNC_HAS_CLUSTER_PRIVILEGE_TEXT_TEXT_OID;
4412 },
4413 "has_connection_privilege" => Scalar {
4414 params!(String, String, String) => sql_impl_func(
4415 "has_connection_privilege(\
4416 mz_internal.mz_role_oid($1), \
4417 mz_internal.mz_connection_oid($2), $3)",
4418 ) => Bool,
4419 oid::FUNC_HAS_CONNECTION_PRIVILEGE_TEXT_TEXT_TEXT_OID;
4420 params!(String, Oid, String) => sql_impl_func(
4421 "has_connection_privilege(mz_internal.mz_role_oid($1), $2, $3)",
4422 ) => Bool,
4423 oid::FUNC_HAS_CONNECTION_PRIVILEGE_TEXT_OID_TEXT_OID;
4424 params!(Oid, String, String) => sql_impl_func(
4425 "has_connection_privilege($1, mz_internal.mz_connection_oid($2), $3)",
4426 ) => Bool,
4427 oid::FUNC_HAS_CONNECTION_PRIVILEGE_OID_TEXT_TEXT_OID;
4428 params!(Oid, Oid, String) => sql_impl_func(
4429 &privilege_fn!("has_connection_privilege", "mz_connections"),
4430 ) => Bool,
4431 oid::FUNC_HAS_CONNECTION_PRIVILEGE_OID_OID_TEXT_OID;
4432 params!(String, String) => sql_impl_func(
4433 "has_connection_privilege(current_user, $1, $2)",
4434 ) => Bool,
4435 oid::FUNC_HAS_CONNECTION_PRIVILEGE_TEXT_TEXT_OID;
4436 params!(Oid, String) => sql_impl_func(
4437 "has_connection_privilege(current_user, $1, $2)",
4438 ) => Bool,
4439 oid::FUNC_HAS_CONNECTION_PRIVILEGE_OID_TEXT_OID;
4440 },
4441 "has_role" => Scalar {
4442 params!(String, String, String)
4443 => sql_impl_func("pg_has_role($1, $2, $3)")
4444 => Bool, oid::FUNC_HAS_ROLE_TEXT_TEXT_TEXT_OID;
4445 params!(String, Oid, String)
4446 => sql_impl_func("pg_has_role($1, $2, $3)")
4447 => Bool, oid::FUNC_HAS_ROLE_TEXT_OID_TEXT_OID;
4448 params!(Oid, String, String)
4449 => sql_impl_func("pg_has_role($1, $2, $3)")
4450 => Bool, oid::FUNC_HAS_ROLE_OID_TEXT_TEXT_OID;
4451 params!(Oid, Oid, String)
4452 => sql_impl_func("pg_has_role($1, $2, $3)")
4453 => Bool, oid::FUNC_HAS_ROLE_OID_OID_TEXT_OID;
4454 params!(String, String)
4455 => sql_impl_func("pg_has_role($1, $2)")
4456 => Bool, oid::FUNC_HAS_ROLE_TEXT_TEXT_OID;
4457 params!(Oid, String)
4458 => sql_impl_func("pg_has_role($1, $2)")
4459 => Bool, oid::FUNC_HAS_ROLE_OID_TEXT_OID;
4460 },
4461 "has_secret_privilege" => Scalar {
4462 params!(String, String, String) => sql_impl_func(
4463 "has_secret_privilege(\
4464 mz_internal.mz_role_oid($1), \
4465 mz_internal.mz_secret_oid($2), $3)",
4466 ) => Bool,
4467 oid::FUNC_HAS_SECRET_PRIVILEGE_TEXT_TEXT_TEXT_OID;
4468 params!(String, Oid, String) => sql_impl_func(
4469 "has_secret_privilege(mz_internal.mz_role_oid($1), $2, $3)",
4470 ) => Bool,
4471 oid::FUNC_HAS_SECRET_PRIVILEGE_TEXT_OID_TEXT_OID;
4472 params!(Oid, String, String) => sql_impl_func(
4473 "has_secret_privilege($1, mz_internal.mz_secret_oid($2), $3)",
4474 ) => Bool,
4475 oid::FUNC_HAS_SECRET_PRIVILEGE_OID_TEXT_TEXT_OID;
4476 params!(Oid, Oid, String) => sql_impl_func(
4477 &privilege_fn!("has_secret_privilege", "mz_secrets"),
4478 ) => Bool,
4479 oid::FUNC_HAS_SECRET_PRIVILEGE_OID_OID_TEXT_OID;
4480 params!(String, String) => sql_impl_func(
4481 "has_secret_privilege(current_user, $1, $2)",
4482 ) => Bool,
4483 oid::FUNC_HAS_SECRET_PRIVILEGE_TEXT_TEXT_OID;
4484 params!(Oid, String) => sql_impl_func(
4485 "has_secret_privilege(current_user, $1, $2)",
4486 ) => Bool,
4487 oid::FUNC_HAS_SECRET_PRIVILEGE_OID_TEXT_OID;
4488 },
4489 "has_system_privilege" => Scalar {
4490 params!(String, String) => sql_impl_func(
4491 "has_system_privilege(mz_internal.mz_role_oid($1), $2)",
4492 ) => Bool, oid::FUNC_HAS_SYSTEM_PRIVILEGE_TEXT_TEXT_OID;
4493 params!(Oid, String) => sql_impl_func(&format!("
4494 CASE
4495 -- We need to validate the privileges to return a proper error before
4496 -- anything else.
4497 WHEN NOT mz_internal.mz_validate_privileges($2)
4498 OR $1 IS NULL
4499 OR $2 IS NULL
4500 OR $1 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
4501 THEN NULL
4502 ELSE COALESCE(
4503 (
4504 SELECT
4505 bool_or(
4506 mz_internal.mz_acl_item_contains_privilege(privileges, $2)
4507 )
4508 AS has_system_privilege
4509 FROM mz_catalog.mz_system_privileges
4510 LEFT JOIN mz_catalog.mz_roles ON
4511 mz_internal.mz_aclitem_grantee(privileges) = mz_roles.id
4512 WHERE
4513 mz_internal.mz_aclitem_grantee(privileges) = '{}'
4514 OR pg_has_role($1, mz_roles.oid, 'USAGE')
4515 ),
4516 false
4517 )
4518 END
4519 ", RoleId::Public))
4520 => Bool, oid::FUNC_HAS_SYSTEM_PRIVILEGE_OID_TEXT_OID;
4521 params!(String) => sql_impl_func(
4522 "has_system_privilege(current_user, $1)",
4523 ) => Bool, oid::FUNC_HAS_SYSTEM_PRIVILEGE_TEXT_OID;
4524 },
4525 "has_type_privilege" => Scalar {
4526 params!(String, String, String) => sql_impl_func(
4527 "has_type_privilege(mz_internal.mz_role_oid($1), $2::regtype::oid, $3)",
4528 ) => Bool, 3138;
4529 params!(String, Oid, String) => sql_impl_func(
4530 "has_type_privilege(mz_internal.mz_role_oid($1), $2, $3)",
4531 ) => Bool, 3139;
4532 params!(Oid, String, String) => sql_impl_func(
4533 "has_type_privilege($1, $2::regtype::oid, $3)",
4534 ) => Bool, 3140;
4535 params!(Oid, Oid, String) => sql_impl_func(
4536 &privilege_fn!("has_type_privilege", "mz_types"),
4537 ) => Bool, 3141;
4538 params!(String, String) => sql_impl_func(
4539 "has_type_privilege(current_user, $1, $2)",
4540 ) => Bool, 3142;
4541 params!(Oid, String) => sql_impl_func(
4542 "has_type_privilege(current_user, $1, $2)",
4543 ) => Bool, 3143;
4544 },
4545 "kafka_murmur2" => Scalar {
4546 params!(String) => UnaryFunc::KafkaMurmur2String(func::KafkaMurmur2String)
4547 => Int32, oid::FUNC_KAFKA_MURMUR2_STRING_OID;
4548 params!(Bytes) => UnaryFunc::KafkaMurmur2Bytes(func::KafkaMurmur2Bytes)
4549 => Int32, oid::FUNC_KAFKA_MURMUR2_BYTES_OID;
4550 },
4551 "list_agg" => Aggregate {
4552 params!(Any) => Operation::unary_ordered(|ecx, e, order_by| {
4553 if let SqlScalarType::Char {.. } = ecx.scalar_type(&e) {
4554 bail_unsupported!("list_agg on char");
4555 };
4556 let e_arr = HirScalarExpr::call_variadic(
4559 variadic::ListCreate { elem_type: ecx.scalar_type(&e) },
4560 vec![e],
4561 );
4562 Ok((e_arr, AggregateFunc::ListConcat { order_by }))
4563 }) => ListAnyCompatible, oid::FUNC_LIST_AGG_OID;
4564 },
4565 "list_append" => Scalar {
4566 vec![ListAnyCompatible, ListElementAnyCompatible]
4567 => BinaryFunc::from(func::ListElementConcat)
4568 => ListAnyCompatible, oid::FUNC_LIST_APPEND_OID;
4569 },
4570 "list_cat" => Scalar {
4571 vec![ListAnyCompatible, ListAnyCompatible]
4572 => BinaryFunc::from(func::ListListConcat)
4573 => ListAnyCompatible, oid::FUNC_LIST_CAT_OID;
4574 },
4575 "list_n_layers" => Scalar {
4576 vec![ListAny] => Operation::unary(|ecx, e| {
4577 ecx.require_feature_flag(&vars::ENABLE_LIST_N_LAYERS)?;
4578 let d = ecx.scalar_type(&e).unwrap_list_n_layers();
4579 match i32::try_from(d) {
4580 Ok(d) => Ok(HirScalarExpr::literal(Datum::Int32(d), SqlScalarType::Int32)),
4581 Err(_) => sql_bail!("list has more than {} layers", i32::MAX),
4582 }
4583
4584 }) => Int32, oid::FUNC_LIST_N_LAYERS_OID;
4585 },
4586 "list_length" => Scalar {
4587 vec![ListAny] => UnaryFunc::ListLength(func::ListLength)
4588 => Int32, oid::FUNC_LIST_LENGTH_OID;
4589 },
4590 "list_length_max" => Scalar {
4591 vec![ListAny, Plain(SqlScalarType::Int64)] => Operation::binary(|ecx, lhs, rhs| {
4592 ecx.require_feature_flag(&vars::ENABLE_LIST_LENGTH_MAX)?;
4593 let max_layer = ecx.scalar_type(&lhs).unwrap_list_n_layers();
4594 Ok(lhs.call_binary(rhs, BinaryFunc::from(func::ListLengthMax { max_layer })))
4595 }) => Int32, oid::FUNC_LIST_LENGTH_MAX_OID;
4596 },
4597 "list_prepend" => Scalar {
4598 vec![ListElementAnyCompatible, ListAnyCompatible]
4599 => BinaryFunc::from(func::ElementListConcat)
4600 => ListAnyCompatible, oid::FUNC_LIST_PREPEND_OID;
4601 },
4602 "list_remove" => Scalar {
4603 vec![ListAnyCompatible, ListElementAnyCompatible] => Operation::binary(|ecx, lhs, rhs| {
4604 ecx.require_feature_flag(&vars::ENABLE_LIST_REMOVE)?;
4605 Ok(lhs.call_binary(rhs, func::ListRemove))
4606 }) => ListAnyCompatible, oid::FUNC_LIST_REMOVE_OID;
4607 },
4608 "map_agg" => Aggregate {
4609 params!(String, Any) => Operation::binary_ordered(|ecx, key, val, order_by| {
4610 let (value_type, val) = match ecx.scalar_type(&val) {
4611 SqlScalarType::Char { length } => (
4613 SqlScalarType::Char { length },
4614 val.call_unary(UnaryFunc::PadChar(func::PadChar { length })),
4615 ),
4616 typ => (typ, val),
4617 };
4618
4619 let e = HirScalarExpr::call_variadic(
4620 variadic::RecordCreate {
4621 field_names: vec![ColumnName::from("key"), ColumnName::from("val")],
4622 },
4623 vec![key, val],
4624 );
4625
4626 Ok((e, AggregateFunc::MapAgg { order_by, value_type }))
4627 }) => MapAny, oid::FUNC_MAP_AGG;
4628 },
4629 "map_build" => Scalar {
4630 params!(ListAny) => Operation::unary(|ecx, expr| {
4641 let ty = ecx.scalar_type(&expr);
4642
4643 let err = || {
4646 Err(sql_err!(
4647 "function map_build({}) does not exist",
4648 ecx.humanize_sql_scalar_type(&ty.clone(), false)
4649 ))
4650 };
4651
4652 let value_type = match &ty {
4655 SqlScalarType::List { element_type, .. } => match &**element_type {
4656 SqlScalarType::Record { fields, .. } if fields.len() == 2 => {
4657 if fields[0].1.scalar_type != SqlScalarType::String {
4658 return err();
4659 }
4660
4661 fields[1].1.scalar_type.clone()
4662 }
4663 _ => return err(),
4664 },
4665 _ => unreachable!("input guaranteed to be list"),
4666 };
4667
4668 Ok(expr.call_unary(UnaryFunc::MapBuildFromRecordList(
4669 func::MapBuildFromRecordList { value_type },
4670 )))
4671 }) => MapAny, oid::FUNC_MAP_BUILD;
4672 },
4673 "map_length" => Scalar {
4674 params![MapAny] => UnaryFunc::MapLength(func::MapLength)
4675 => Int32, oid::FUNC_MAP_LENGTH_OID;
4676 },
4677 "mz_environment_id" => Scalar {
4678 params!() => UnmaterializableFunc::MzEnvironmentId
4679 => String, oid::FUNC_MZ_ENVIRONMENT_ID_OID;
4680 },
4681 "mz_is_superuser" => Scalar {
4682 params!() => UnmaterializableFunc::MzIsSuperuser
4683 => SqlScalarType::Bool, oid::FUNC_MZ_IS_SUPERUSER;
4684 },
4685 "mz_logical_timestamp" => Scalar {
4686 params!() => Operation::nullary(|_ecx| {
4687 sql_bail!("mz_logical_timestamp() has been renamed to mz_now()")
4688 }) => MzTimestamp, oid::FUNC_MZ_LOGICAL_TIMESTAMP_OID;
4689 },
4690 "mz_now" => Scalar {
4691 params!() => UnmaterializableFunc::MzNow => MzTimestamp, oid::FUNC_MZ_NOW_OID;
4692 },
4693 "mz_uptime" => Scalar {
4694 params!() => UnmaterializableFunc::MzUptime => Interval, oid::FUNC_MZ_UPTIME_OID;
4695 },
4696 "mz_version" => Scalar {
4697 params!() => UnmaterializableFunc::MzVersion => String, oid::FUNC_MZ_VERSION_OID;
4698 },
4699 "mz_version_num" => Scalar {
4700 params!() => UnmaterializableFunc::MzVersionNum => Int32, oid::FUNC_MZ_VERSION_NUM_OID;
4701 },
4702 "pretty_sql" => Scalar {
4703 params!(String, Int32) => BinaryFunc::from(func::PrettySql)
4704 => String, oid::FUNC_PRETTY_SQL;
4705 params!(String) => Operation::unary(|_ecx, s| {
4706 let w: i32 = mz_sql_pretty::DEFAULT_WIDTH.try_into().expect("must fit");
4707 let width = HirScalarExpr::literal(Datum::Int32(w), SqlScalarType::Int32);
4708 Ok(s.call_binary(width, func::PrettySql))
4709 }) => String, oid::FUNC_PRETTY_SQL_NOWIDTH;
4710 },
4711 "regexp_extract" => Table {
4712 params!(String, String) => Operation::binary(move |_ecx, regex, haystack| {
4713 let regex = match regex.into_literal_string() {
4714 None => sql_bail!(
4715 "regexp_extract requires a string \
4716 literal as its first argument"
4717 ),
4718 Some(regex) => {
4719 let opts = mz_expr::AnalyzedRegexOpts::default();
4720 mz_expr::AnalyzedRegex::new(®ex, opts)
4721 .map_err(|e| {
4722 sql_err!("analyzing regex: {}", e)
4723 })?
4724 },
4725 };
4726 let column_names = regex
4727 .capture_groups_iter()
4728 .map(|cg| {
4729 cg.name.clone().unwrap_or_else(|| format!("column{}", cg.index)).into()
4730 })
4731 .collect::<Vec<_>>();
4732 if column_names.is_empty(){
4733 sql_bail!("regexp_extract must specify at least one capture group");
4734 }
4735 Ok(TableFuncPlan {
4736 imp: TableFuncImpl::CallTable {
4737 func: TableFunc::RegexpExtract(regex),
4738 exprs: vec![haystack],
4739 },
4740 column_names,
4741 })
4742 }) => ReturnType::set_of(RecordAny), oid::FUNC_REGEXP_EXTRACT_OID;
4743 },
4744 mz_expr::REPEAT_ROW_NAME => Table {
4745 params!(Int64) => Operation::unary(move |ecx, n| {
4746 ecx.require_feature_flag(&vars::ENABLE_REPEAT_ROW)?;
4747 Ok(TableFuncPlan {
4748 imp: TableFuncImpl::CallTable {
4749 func: TableFunc::RepeatRow,
4750 exprs: vec![n],
4751 },
4752 column_names: vec![]
4753 })
4754 }) => ReturnType::none(true), oid::FUNC_REPEAT_ROW_OID;
4755 },
4756 "repeat_row_non_negative" => Table {
4757 params!(Int64) => Operation::unary(move |ecx, n| {
4758 ecx.require_feature_flag(&vars::ENABLE_REPEAT_ROW_NON_NEGATIVE)?;
4759 Ok(TableFuncPlan {
4760 imp: TableFuncImpl::CallTable {
4761 func: TableFunc::RepeatRowNonNegative,
4762 exprs: vec![n],
4763 },
4764 column_names: vec![]
4765 })
4766 }) => ReturnType::none(true), oid::FUNC_REPEAT_ROW_NON_NEGATIVE_OID;
4767 },
4768 "seahash" => Scalar {
4769 params!(String) => UnaryFunc::SeahashString(func::SeahashString)
4770 => UInt64, oid::FUNC_SEAHASH_STRING_OID;
4771 params!(Bytes) => UnaryFunc::SeahashBytes(func::SeahashBytes)
4772 => UInt64, oid::FUNC_SEAHASH_BYTES_OID;
4773 },
4774 "starts_with" => Scalar {
4775 params!(String, String) => BinaryFunc::from(func::StartsWith) => Bool, 3696;
4776 },
4777 "timezone_offset" => Scalar {
4778 params!(String, TimestampTz) => BinaryFunc::from(func::TimezoneOffset)
4779 => RecordAny, oid::FUNC_TIMEZONE_OFFSET;
4780 },
4781 "try_parse_monotonic_iso8601_timestamp" => Scalar {
4782 params!(String) => Operation::unary(move |_ecx, e| {
4783 Ok(e.call_unary(UnaryFunc::TryParseMonotonicIso8601Timestamp(
4784 func::TryParseMonotonicIso8601Timestamp,
4785 )))
4786 }) => Timestamp, oid::FUNC_TRY_PARSE_MONOTONIC_ISO8601_TIMESTAMP;
4787 },
4788 "unnest" => Table {
4789 vec![ArrayAny] => Operation::unary(move |ecx, e| {
4790 let el_typ = ecx.scalar_type(&e).unwrap_array_element_type().clone();
4791 Ok(TableFuncPlan {
4792 imp: TableFuncImpl::CallTable {
4793 func: TableFunc::UnnestArray { el_typ },
4794 exprs: vec![e],
4795 },
4796 column_names: vec!["unnest".into()],
4797 })
4798 }) =>
4799 ReturnType::set_of(AnyElement), 2331;
4802 vec![ListAny] => Operation::unary(move |ecx, e| {
4803 let el_typ = ecx.scalar_type(&e).unwrap_list_element_type().clone();
4804 Ok(TableFuncPlan {
4805 imp: TableFuncImpl::CallTable {
4806 func: TableFunc::UnnestList { el_typ },
4807 exprs: vec![e],
4808 },
4809 column_names: vec!["unnest".into()],
4810 })
4811 }) =>
4812 ReturnType::set_of(Any), oid::FUNC_UNNEST_LIST_OID;
4815 vec![MapAny] => Operation::unary(move |ecx, e| {
4816 let value_type = ecx.scalar_type(&e).unwrap_map_value_type().clone();
4817 Ok(TableFuncPlan {
4818 imp: TableFuncImpl::CallTable {
4819 func: TableFunc::UnnestMap { value_type },
4820 exprs: vec![e],
4821 },
4822 column_names: vec!["key".into(), "value".into()],
4823 })
4824 }) =>
4825 ReturnType::set_of(Any), oid::FUNC_UNNEST_MAP_OID;
4828 }
4829 }
4830});
4831
4832pub static MZ_INTERNAL_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
4833 use ParamType::*;
4834 use SqlScalarBaseType::*;
4835 builtins! {
4836 "aclitem_grantor" => Scalar {
4837 params!(AclItem) => UnaryFunc::AclItemGrantor(func::AclItemGrantor)
4838 => Oid, oid::FUNC_ACL_ITEM_GRANTOR_OID;
4839 },
4840 "aclitem_grantee" => Scalar {
4841 params!(AclItem) => UnaryFunc::AclItemGrantee(func::AclItemGrantee)
4842 => Oid, oid::FUNC_ACL_ITEM_GRANTEE_OID;
4843 },
4844 "aclitem_privileges" => Scalar {
4845 params!(AclItem) => UnaryFunc::AclItemPrivileges(func::AclItemPrivileges)
4846 => String, oid::FUNC_ACL_ITEM_PRIVILEGES_OID;
4847 },
4848 "is_rbac_enabled" => Scalar {
4849 params!() => UnmaterializableFunc::IsRbacEnabled => Bool, oid::FUNC_IS_RBAC_ENABLED_OID;
4850 },
4851 "make_mz_aclitem" => Scalar {
4852 params!(String, String, String) => VariadicFunc::from(variadic::MakeMzAclItem)
4853 => MzAclItem, oid::FUNC_MAKE_MZ_ACL_ITEM_OID;
4854 },
4855 "mz_acl_item_contains_privilege" => Scalar {
4856 params!(MzAclItem, String)
4857 => BinaryFunc::from(func::MzAclItemContainsPrivilege)
4858 => Bool, oid::FUNC_MZ_ACL_ITEM_CONTAINS_PRIVILEGE_OID;
4859 },
4860 "mz_aclexplode" => Table {
4861 params!(SqlScalarType::Array(Box::new(SqlScalarType::MzAclItem)))
4862 => Operation::unary(move |_ecx, mz_aclitems| {
4863 Ok(TableFuncPlan {
4864 imp: TableFuncImpl::CallTable {
4865 func: TableFunc::MzAclExplode,
4866 exprs: vec![mz_aclitems],
4867 },
4868 column_names: vec![
4869 "grantor".into(), "grantee".into(),
4870 "privilege_type".into(), "is_grantable".into(),
4871 ],
4872 })
4873 }) => ReturnType::set_of(RecordAny), oid::FUNC_MZ_ACL_ITEM_EXPLODE_OID;
4874 },
4875 "mz_aclitem_grantor" => Scalar {
4876 params!(MzAclItem) => UnaryFunc::MzAclItemGrantor(func::MzAclItemGrantor)
4877 => String, oid::FUNC_MZ_ACL_ITEM_GRANTOR_OID;
4878 },
4879 "mz_aclitem_grantee" => Scalar {
4880 params!(MzAclItem) => UnaryFunc::MzAclItemGrantee(func::MzAclItemGrantee)
4881 => String, oid::FUNC_MZ_ACL_ITEM_GRANTEE_OID;
4882 },
4883 "mz_aclitem_privileges" => Scalar {
4884 params!(MzAclItem) => UnaryFunc::MzAclItemPrivileges(
4885 func::MzAclItemPrivileges,
4886 ) => String, oid::FUNC_MZ_ACL_ITEM_PRIVILEGES_OID;
4887 },
4888 "mz_connection_oid" => Scalar {
4893 params!(String) => sql_impl_func("
4894 CASE
4895 WHEN $1 IS NULL THEN NULL
4896 ELSE (
4897 mz_unsafe.mz_error_if_null(
4898 (SELECT oid FROM mz_catalog.mz_objects
4899 WHERE name = $1 AND type = 'connection'),
4900 'connection \"' || $1 || '\" does not exist'
4901 )
4902 )
4903 END
4904 ") => Oid, oid::FUNC_CONNECTION_OID_OID;
4905 },
4906 "mz_format_privileges" => Scalar {
4907 params!(String) => UnaryFunc::MzFormatPrivileges(func::MzFormatPrivileges)
4908 => SqlScalarType::Array(Box::new(SqlScalarType::String)),
4909 oid::FUNC_MZ_FORMAT_PRIVILEGES_OID;
4910 },
4911 "mz_name_rank" => Table {
4912 params!(
4915 String,
4917 ParamType::Plain(SqlScalarType::Array(Box::new(SqlScalarType::String))),
4919 String,
4921 String
4923 ) =>
4924 sql_impl_table_func("
4926 -- The best ranked name is the one that belongs to the schema correlated with the lowest
4927 -- index in the search path
4928 SELECT id, name, count, min(schema_pref) OVER () = schema_pref AS best_ranked FROM (
4929 SELECT DISTINCT
4930 o.id,
4931 ARRAY[CASE WHEN s.database_id IS NULL THEN NULL ELSE d.name END, s.name, o.name]
4932 AS name,
4933 o.count,
4934 pg_catalog.array_position($2, s.name) AS schema_pref
4935 FROM
4936 (
4937 SELECT
4938 o.id,
4939 o.schema_id,
4940 o.name,
4941 count(*)
4942 FROM mz_catalog.mz_objects AS o
4943 JOIN mz_internal.mz_object_oid_alias AS a
4944 ON o.type = a.object_type
4945 WHERE o.name = CAST($3 AS pg_catalog.text) AND a.oid_alias = $4
4946 GROUP BY 1, 2, 3
4947 )
4948 AS o
4949 JOIN mz_catalog.mz_schemas AS s ON o.schema_id = s.id
4950 JOIN
4951 unnest($2) AS search_schema (name)
4952 ON search_schema.name = s.name
4953 JOIN
4954 (
4955 SELECT id, name FROM mz_catalog.mz_databases
4956 -- If the provided database does not exist, add a row for it so that it
4957 -- can still join against ambient schemas.
4958 UNION ALL
4959 SELECT '', $1 WHERE $1 NOT IN (SELECT name FROM mz_catalog.mz_databases)
4960 ) AS d
4961 ON d.id = COALESCE(s.database_id, d.id)
4962 WHERE d.name = CAST($1 AS pg_catalog.text)
4963 );
4964 ") => ReturnType::set_of(RecordAny), oid::FUNC_MZ_NAME_RANK;
4965 },
4966 "mz_resolve_object_name" => Table {
4967 params!(String, String) =>
4968 sql_impl_table_func("
4971 SELECT
4972 o.id, o.oid, o.schema_id, o.name, o.type, o.owner_id, o.privileges
4973 FROM
4974 (SELECT mz_internal.mz_normalize_object_name($2))
4975 AS normalized (n),
4976 mz_internal.mz_name_rank(
4977 COALESCE(n[1], pg_catalog.current_database()),
4978 CASE
4979 WHEN n[2] IS NULL
4980 THEN pg_catalog.current_schemas(true)
4981 ELSE
4982 ARRAY[n[2]]
4983 END,
4984 n[3],
4985 $1
4986 ) AS r,
4987 mz_catalog.mz_objects AS o
4988 WHERE r.id = o.id AND r.best_ranked;
4989 ") => ReturnType::set_of(RecordAny), oid::FUNC_MZ_RESOLVE_OBJECT_NAME;
4990 },
4991 "mz_minimal_name_qualification" => Scalar {
5003 params!(SqlScalarType::Array(Box::new(SqlScalarType::String)), String) => {
5004 sql_impl_func("(
5005 SELECT
5006 CASE
5007 WHEN $1::pg_catalog.text[] IS NULL
5008 THEN NULL
5009 -- If DB doesn't match, requires full qual
5010 WHEN $1[1] != pg_catalog.current_database()
5011 THEN $1
5012 -- If not in currently searchable schema, must be schema qualified
5013 WHEN NOT $1[2] = ANY(pg_catalog.current_schemas(true))
5014 THEN ARRAY[$1[2], $1[3]]
5015 ELSE
5016 minimal_name
5017 END
5018 FROM (
5019 -- Subquery so we return one null row in the cases where
5020 -- there are no matches.
5021 SELECT (
5022 SELECT DISTINCT
5023 CASE
5024 -- If there is only one item with this name and it's rank 1,
5025 -- it is uniquely nameable with just the final element
5026 WHEN best_ranked AND count = 1
5027 THEN ARRAY[r.name[3]]
5028 -- Otherwise, it is findable in the search path, so does not
5029 -- need database qualification
5030 ELSE
5031 ARRAY[r.name[2], r.name[3]]
5032 END AS minimal_name
5033 FROM mz_catalog.mz_objects AS o
5034 JOIN mz_internal.mz_object_oid_alias AS a
5035 ON o.type = a.object_type,
5036 -- implied lateral to put the OID alias into scope
5037 mz_internal.mz_name_rank(
5038 pg_catalog.current_database(),
5039 pg_catalog.current_schemas(true),
5040 $1[3],
5041 a.oid_alias
5042 ) AS r
5043 WHERE o.id = $2 AND r.id = $2
5044 )
5045 )
5046 )")
5047 } => SqlScalarType::Array(Box::new(SqlScalarType::String)),
5048 oid::FUNC_MZ_MINIMINAL_NAME_QUALIFICATION;
5049 },
5050 "mz_global_id_to_name" => Scalar {
5051 params!(String) => sql_impl_func("
5052 CASE
5053 WHEN $1 IS NULL THEN NULL
5054 ELSE (
5055 SELECT array_to_string(minimal_name, '.')
5056 FROM (
5057 SELECT mz_unsafe.mz_error_if_null(
5058 (
5059 -- Return the fully-qualified name
5060 SELECT DISTINCT ARRAY[qual.d, qual.s, item.name]
5061 FROM
5062 mz_catalog.mz_objects AS item
5063 JOIN
5064 (
5065 SELECT
5066 d.name AS d,
5067 s.name AS s,
5068 s.id AS schema_id
5069 FROM
5070 mz_catalog.mz_schemas AS s
5071 LEFT JOIN
5072 (SELECT id, name FROM mz_catalog.mz_databases)
5073 AS d
5074 ON s.database_id = d.id
5075 ) AS qual
5076 ON qual.schema_id = item.schema_id
5077 WHERE item.id = CAST($1 AS text)
5078 ),
5079 'global ID ' || $1 || ' does not exist'
5080 )
5081 ) AS n (fqn),
5082 LATERAL (
5083 -- Get the minimal qualification of the fully qualified name
5084 SELECT mz_internal.mz_minimal_name_qualification(fqn, $1)
5085 ) AS m (minimal_name)
5086 )
5087 END
5088 ") => String, oid::FUNC_MZ_GLOBAL_ID_TO_NAME;
5089 },
5090 "mz_normalize_object_name" => Scalar {
5091 params!(String) => sql_impl_func("
5092 (
5093 SELECT
5094 CASE
5095 WHEN $1 IS NULL OR ident IS NULL THEN NULL
5096 WHEN pg_catalog.array_length(ident, 1) > 3
5097 THEN mz_unsafe.mz_error_if_null(
5098 NULL::pg_catalog.text[],
5099 'improper relation name (too many dotted names): ' || $1
5100 )
5101 ELSE pg_catalog.array_cat(
5102 pg_catalog.array_fill(
5103 CAST(NULL AS pg_catalog.text),
5104 ARRAY[3 - pg_catalog.array_length(ident, 1)]
5105 ),
5106 ident
5107 )
5108 END
5109 FROM (
5110 SELECT pg_catalog.parse_ident($1) AS ident
5111 ) AS i
5112 )") => SqlScalarType::Array(Box::new(SqlScalarType::String)),
5113 oid::FUNC_MZ_NORMALIZE_OBJECT_NAME;
5114 },
5115 "mz_normalize_schema_name" => Scalar {
5116 params!(String) => sql_impl_func("
5117 (
5118 SELECT
5119 CASE
5120 WHEN $1 IS NULL OR ident IS NULL THEN NULL
5121 WHEN pg_catalog.array_length(ident, 1) > 2
5122 THEN mz_unsafe.mz_error_if_null(
5123 NULL::pg_catalog.text[],
5124 'improper schema name (too many dotted names): ' || $1
5125 )
5126 ELSE pg_catalog.array_cat(
5127 pg_catalog.array_fill(
5128 CAST(NULL AS pg_catalog.text),
5129 ARRAY[2 - pg_catalog.array_length(ident, 1)]
5130 ),
5131 ident
5132 )
5133 END
5134 FROM (
5135 SELECT pg_catalog.parse_ident($1) AS ident
5136 ) AS i
5137 )") => SqlScalarType::Array(Box::new(SqlScalarType::String)),
5138 oid::FUNC_MZ_NORMALIZE_SCHEMA_NAME;
5139 },
5140 "mz_render_typmod" => Scalar {
5141 params!(Oid, Int32) => BinaryFunc::from(func::MzRenderTypmod)
5142 => String, oid::FUNC_MZ_RENDER_TYPMOD_OID;
5143 },
5144 "mz_role_oid_memberships" => Scalar {
5145 params!() => UnmaterializableFunc::MzRoleOidMemberships
5146 => SqlScalarType::Map {
5147 value_type: Box::new(SqlScalarType::Array(
5148 Box::new(SqlScalarType::String),
5149 )),
5150 custom_id: None,
5151 }, oid::FUNC_MZ_ROLE_OID_MEMBERSHIPS;
5152 },
5153 "mz_session_role_memberships" => Scalar {
5154 params!() => UnmaterializableFunc::MzSessionRoleMemberships
5155 => SqlScalarType::Array(Box::new(SqlScalarType::String)),
5156 oid::FUNC_MZ_SESSION_ROLE_MEMBERSHIPS_OID;
5157 },
5158 "mz_database_oid" => Scalar {
5161 params!(String) => sql_impl_func("
5162 CASE
5163 WHEN $1 IS NULL THEN NULL
5164 ELSE (
5165 mz_unsafe.mz_error_if_null(
5166 (SELECT oid FROM mz_databases WHERE name = $1),
5167 'database \"' || $1 || '\" does not exist'
5168 )
5169 )
5170 END
5171 ") => Oid, oid::FUNC_DATABASE_OID_OID;
5172 },
5173 "mz_schema_oid" => Scalar {
5176 params!(String) => sql_impl_func("
5177 CASE
5178 WHEN $1 IS NULL THEN NULL
5179 ELSE
5180 mz_unsafe.mz_error_if_null(
5181 (
5182 SELECT
5183 (
5184 SELECT s.oid
5185 FROM mz_catalog.mz_schemas AS s
5186 LEFT JOIN mz_databases AS d ON s.database_id = d.id
5187 WHERE
5188 (
5189 -- Filter to only schemas in the named database or the
5190 -- current database if no database was specified.
5191 d.name = COALESCE(n[1], pg_catalog.current_database())
5192 -- Always include all ambient schemas.
5193 OR s.database_id IS NULL
5194 )
5195 AND s.name = n[2]
5196 )
5197 FROM mz_internal.mz_normalize_schema_name($1) AS n
5198 ),
5199 'schema \"' || $1 || '\" does not exist'
5200 )
5201 END
5202 ") => Oid, oid::FUNC_SCHEMA_OID_OID;
5203 },
5204 "mz_role_oid" => Scalar {
5207 params!(String) => sql_impl_func("
5208 CASE
5209 WHEN $1 IS NULL THEN NULL
5210 ELSE (
5211 mz_unsafe.mz_error_if_null(
5212 (SELECT oid FROM mz_catalog.mz_roles WHERE name = $1),
5213 'role \"' || $1 || '\" does not exist'
5214 )
5215 )
5216 END
5217 ") => Oid, oid::FUNC_ROLE_OID_OID;
5218 },
5219 "mz_secret_oid" => Scalar {
5224 params!(String) => sql_impl_func("
5225 CASE
5226 WHEN $1 IS NULL THEN NULL
5227 ELSE (
5228 mz_unsafe.mz_error_if_null(
5229 (SELECT oid FROM mz_catalog.mz_objects WHERE name = $1 AND type = 'secret'),
5230 'secret \"' || $1 || '\" does not exist'
5231 )
5232 )
5233 END
5234 ") => Oid, oid::FUNC_SECRET_OID_OID;
5235 },
5236 "mz_session_id" => Scalar {
5240 params!() => UnmaterializableFunc::MzSessionId => Uuid, oid::FUNC_MZ_SESSION_ID_OID;
5241 },
5242 "mz_type_name" => Scalar {
5243 params!(Oid) => UnaryFunc::MzTypeName(func::MzTypeName)
5244 => String, oid::FUNC_MZ_TYPE_NAME;
5245 },
5246 "mz_validate_privileges" => Scalar {
5247 params!(String) => UnaryFunc::MzValidatePrivileges(func::MzValidatePrivileges)
5248 => Bool, oid::FUNC_MZ_VALIDATE_PRIVILEGES_OID;
5249 },
5250 "mz_validate_role_privilege" => Scalar {
5251 params!(String) => UnaryFunc::MzValidateRolePrivilege(
5252 func::MzValidateRolePrivilege,
5253 ) => Bool, oid::FUNC_MZ_VALIDATE_ROLE_PRIVILEGE_OID;
5254 },
5255 "parse_catalog_create_sql" => Scalar {
5256 params!(String) => UnaryFunc::ParseCatalogCreateSql(func::ParseCatalogCreateSql)
5257 => Jsonb, oid::FUNC_PARSE_CATALOG_CREATE_SQL_OID;
5258 },
5259 "parse_catalog_id" => Scalar {
5260 params!(Jsonb) => UnaryFunc::ParseCatalogId(func::ParseCatalogId)
5261 => String, oid::FUNC_PARSE_CATALOG_ID_OID;
5262 },
5263 "parse_catalog_privileges" => Scalar {
5264 params!(Jsonb) => UnaryFunc::ParseCatalogPrivileges(func::ParseCatalogPrivileges)
5265 => SqlScalarType::Array(Box::new(SqlScalarType::MzAclItem)),
5266 oid::FUNC_PARSE_CATALOG_PRIVILEGES_OID;
5267 },
5268 "redact_sql" => Scalar {
5269 params!(String) => UnaryFunc::RedactSql(func::RedactSql)
5270 => String, oid::FUNC_REDACT_SQL_OID;
5271 }
5272 }
5273});
5274
5275pub static MZ_UNSAFE_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
5276 use ParamType::*;
5277 use SqlScalarBaseType::*;
5278 builtins! {
5279 "mz_all" => Aggregate {
5280 params!(Any) => AggregateFunc::All => Bool, oid::FUNC_MZ_ALL_OID;
5281 },
5282 "mz_any" => Aggregate {
5283 params!(Any) => AggregateFunc::Any => Bool, oid::FUNC_MZ_ANY_OID;
5284 },
5285 "mz_avg_promotion_internal_v1" => Scalar {
5286 params!(Float32) => Operation::identity()
5292 => Float32, oid::FUNC_MZ_AVG_PROMOTION_F32_OID_INTERNAL_V1;
5293 params!(Float64) => Operation::identity()
5294 => Float64, oid::FUNC_MZ_AVG_PROMOTION_F64_OID_INTERNAL_V1;
5295 params!(Int16) => Operation::unary(|ecx, e| {
5296 typeconv::plan_cast(
5297 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5298 )
5299 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I16_OID_INTERNAL_V1;
5300 params!(Int32) => Operation::unary(|ecx, e| {
5301 typeconv::plan_cast(
5302 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5303 )
5304 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I32_OID_INTERNAL_V1;
5305 params!(UInt16) => Operation::unary(|ecx, e| {
5306 typeconv::plan_cast(
5307 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5308 )
5309 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U16_OID_INTERNAL_V1;
5310 params!(UInt32) => Operation::unary(|ecx, e| {
5311 typeconv::plan_cast(
5312 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5313 )
5314 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U32_OID_INTERNAL_V1;
5315 },
5316 "mz_avg_promotion" => Scalar {
5317 params!(Float32) => Operation::identity()
5323 => Float32, oid::FUNC_MZ_AVG_PROMOTION_F32_OID;
5324 params!(Float64) => Operation::identity()
5325 => Float64, oid::FUNC_MZ_AVG_PROMOTION_F64_OID;
5326 params!(Int16) => Operation::unary(|ecx, e| {
5327 typeconv::plan_cast(
5328 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5329 )
5330 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I16_OID;
5331 params!(Int32) => Operation::unary(|ecx, e| {
5332 typeconv::plan_cast(
5333 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5334 )
5335 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I32_OID;
5336 params!(Int64) => Operation::unary(|ecx, e| {
5337 typeconv::plan_cast(
5338 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5339 )
5340 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I64_OID;
5341 params!(UInt16) => Operation::unary(|ecx, e| {
5342 typeconv::plan_cast(
5343 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5344 )
5345 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U16_OID;
5346 params!(UInt32) => Operation::unary(|ecx, e| {
5347 typeconv::plan_cast(
5348 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5349 )
5350 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U32_OID;
5351 params!(UInt64) => Operation::unary(|ecx, e| {
5352 typeconv::plan_cast(
5353 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5354 )
5355 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U64_OID;
5356 params!(Numeric) => Operation::unary(|ecx, e| {
5357 typeconv::plan_cast(
5358 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5359 )
5360 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_NUMERIC_OID;
5361 },
5362 "mz_error_if_null" => Scalar {
5363 params!(Any, String) => VariadicFunc::from(variadic::ErrorIfNull)
5366 => Any, oid::FUNC_MZ_ERROR_IF_NULL_OID;
5367 },
5368 "mz_sleep" => Scalar {
5369 params!(Float64) => UnaryFunc::Sleep(func::Sleep)
5370 => TimestampTz, oid::FUNC_MZ_SLEEP_OID;
5371 },
5372 "mz_panic" => Scalar {
5373 params!(String) => UnaryFunc::Panic(func::Panic) => String, oid::FUNC_MZ_PANIC_OID;
5374 }
5375 }
5376});
5377
5378fn digest(algorithm: &'static str) -> Operation<HirScalarExpr> {
5379 Operation::unary(move |_ecx, input| {
5380 let algorithm = HirScalarExpr::literal(Datum::String(algorithm), SqlScalarType::String);
5381 Ok(input.call_binary(algorithm, BinaryFunc::from(func::DigestBytes)))
5382 })
5383}
5384
5385fn array_to_string(
5386 ecx: &ExprContext,
5387 exprs: Vec<HirScalarExpr>,
5388) -> Result<HirScalarExpr, PlanError> {
5389 let elem_type = match ecx.scalar_type(&exprs[0]) {
5390 SqlScalarType::Array(elem_type) => *elem_type,
5391 _ => unreachable!("array_to_string is guaranteed to receive array as first argument"),
5392 };
5393 Ok(HirScalarExpr::call_variadic(
5394 variadic::ArrayToString { elem_type },
5395 exprs,
5396 ))
5397}
5398
5399pub static OP_IMPLS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
5401 use BinaryFunc as BF;
5402 use ParamType::*;
5403 use SqlScalarBaseType::*;
5404 builtins! {
5405 "+" => Scalar {
5428 params!(Any) => Operation::new(|ecx, exprs, _params, _order_by| {
5429 typeconv::plan_coerce(ecx, exprs.into_element(), &SqlScalarType::Float64)
5442 }) => Any, oid::OP_UNARY_PLUS_OID;
5443 params!(Int16, Int16) => BF::from(func::AddInt16) => Int16, 550;
5444 params!(Int32, Int32) => BF::from(func::AddInt32) => Int32, 551;
5445 params!(Int64, Int64) => BF::from(func::AddInt64) => Int64, 684;
5446 params!(UInt16, UInt16) => BF::from(func::AddUint16) => UInt16, oid::FUNC_ADD_UINT16;
5447 params!(UInt32, UInt32) => BF::from(func::AddUint32) => UInt32, oid::FUNC_ADD_UINT32;
5448 params!(UInt64, UInt64) => BF::from(func::AddUint64) => UInt64, oid::FUNC_ADD_UINT64;
5449 params!(Float32, Float32) => BF::from(func::AddFloat32) => Float32, 586;
5450 params!(Float64, Float64) => BF::from(func::AddFloat64) => Float64, 591;
5451 params!(Interval, Interval) => BF::from(func::AddInterval) => Interval, 1337;
5452 params!(Timestamp, Interval) => BF::from(func::AddTimestampInterval) => Timestamp, 2066;
5453 params!(Interval, Timestamp) => {
5454 Operation::binary(|_ecx, lhs, rhs| {
5455 Ok(rhs.call_binary(lhs, func::AddTimestampInterval))
5456 })
5457 } => Timestamp, 2553;
5458 params!(TimestampTz, Interval)
5459 => BF::from(func::AddTimestampTzInterval) => TimestampTz, 1327;
5460 params!(Interval, TimestampTz) => {
5461 Operation::binary(|_ecx, lhs, rhs| {
5462 Ok(rhs.call_binary(lhs, func::AddTimestampTzInterval))
5463 })
5464 } => TimestampTz, 2554;
5465 params!(Date, Interval) => BF::from(func::AddDateInterval) => Timestamp, 1076;
5466 params!(Interval, Date) => {
5467 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, func::AddDateInterval)))
5468 } => Timestamp, 2551;
5469 params!(Date, Time) => BF::from(func::AddDateTime) => Timestamp, 1360;
5470 params!(Time, Date) => {
5471 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, func::AddDateTime)))
5472 } => Timestamp, 1363;
5473 params!(Time, Interval) => BF::from(func::AddTimeInterval) => Time, 1800;
5474 params!(Interval, Time) => {
5475 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, func::AddTimeInterval)))
5476 } => Time, 1849;
5477 params!(Numeric, Numeric) => BF::from(func::AddNumeric) => Numeric, 1758;
5478 params!(RangeAny, RangeAny) => BF::from(func::RangeUnion) => RangeAny, 3898;
5479 },
5480 "-" => Scalar {
5481 params!(Int16) => UnaryFunc::NegInt16(func::NegInt16) => Int16, 559;
5482 params!(Int32) => UnaryFunc::NegInt32(func::NegInt32) => Int32, 558;
5483 params!(Int64) => UnaryFunc::NegInt64(func::NegInt64) => Int64, 484;
5484 params!(Float32) => UnaryFunc::NegFloat32(func::NegFloat32) => Float32, 584;
5485 params!(Float64) => UnaryFunc::NegFloat64(func::NegFloat64) => Float64, 585;
5486 params!(Numeric) => UnaryFunc::NegNumeric(func::NegNumeric) => Numeric, 17510;
5487 params!(Interval) => UnaryFunc::NegInterval(func::NegInterval) => Interval, 1336;
5488 params!(Int32, Int32) => BF::from(func::SubInt32) => Int32, 555;
5489 params!(Int64, Int64) => BF::from(func::SubInt64) => Int64, 685;
5490 params!(UInt16, UInt16) => BF::from(func::SubUint16) => UInt16, oid::FUNC_SUB_UINT16;
5491 params!(UInt32, UInt32) => BF::from(func::SubUint32) => UInt32, oid::FUNC_SUB_UINT32;
5492 params!(UInt64, UInt64) => BF::from(func::SubUint64) => UInt64, oid::FUNC_SUB_UINT64;
5493 params!(Float32, Float32) => BF::from(func::SubFloat32) => Float32, 587;
5494 params!(Float64, Float64) => BF::from(func::SubFloat64) => Float64, 592;
5495 params!(Numeric, Numeric) => BF::from(func::SubNumeric) => Numeric, 17590;
5496 params!(Interval, Interval) => BF::from(func::SubInterval) => Interval, 1338;
5497 params!(Timestamp, Timestamp) => BF::from(func::SubTimestamp) => Interval, 2067;
5498 params!(TimestampTz, TimestampTz) => BF::from(func::SubTimestampTz) => Interval, 1328;
5499 params!(Timestamp, Interval) => BF::from(func::SubTimestampInterval) => Timestamp, 2068;
5500 params!(TimestampTz, Interval)
5501 => BF::from(func::SubTimestampTzInterval) => TimestampTz, 1329;
5502 params!(Date, Date) => BF::from(func::SubDate) => Int32, 1099;
5503 params!(Date, Interval) => BF::from(func::SubDateInterval) => Timestamp, 1077;
5504 params!(Time, Time) => BF::from(func::SubTime) => Interval, 1399;
5505 params!(Time, Interval) => BF::from(func::SubTimeInterval) => Time, 1801;
5506 params!(Jsonb, Int64) => BF::from(func::JsonbDeleteInt64) => Jsonb, 3286;
5507 params!(Jsonb, String) => BF::from(func::JsonbDeleteString) => Jsonb, 3285;
5508 params!(RangeAny, RangeAny) => BF::from(func::RangeDifference) => RangeAny, 3899;
5509 },
5512 "*" => Scalar {
5513 params!(Int16, Int16) => BF::from(func::MulInt16) => Int16, 526;
5514 params!(Int32, Int32) => BF::from(func::MulInt32) => Int32, 514;
5515 params!(Int64, Int64) => BF::from(func::MulInt64) => Int64, 686;
5516 params!(UInt16, UInt16) => BF::from(func::MulUint16) => UInt16, oid::FUNC_MUL_UINT16;
5517 params!(UInt32, UInt32) => BF::from(func::MulUint32) => UInt32, oid::FUNC_MUL_UINT32;
5518 params!(UInt64, UInt64) => BF::from(func::MulUint64) => UInt64, oid::FUNC_MUL_UINT64;
5519 params!(Float32, Float32) => BF::from(func::MulFloat32) => Float32, 589;
5520 params!(Float64, Float64) => BF::from(func::MulFloat64) => Float64, 594;
5521 params!(Interval, Float64) => BF::from(func::MulInterval) => Interval, 1583;
5522 params!(Float64, Interval) => {
5523 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, func::MulInterval)))
5524 } => Interval, 1584;
5525 params!(Numeric, Numeric) => BF::from(func::MulNumeric) => Numeric, 1760;
5526 params!(RangeAny, RangeAny) => BF::from(func::RangeIntersection) => RangeAny, 3900;
5527 },
5528 "/" => Scalar {
5529 params!(Int16, Int16) => BF::from(func::DivInt16) => Int16, 527;
5530 params!(Int32, Int32) => BF::from(func::DivInt32) => Int32, 528;
5531 params!(Int64, Int64) => BF::from(func::DivInt64) => Int64, 687;
5532 params!(UInt16, UInt16) => BF::from(func::DivUint16) => UInt16, oid::FUNC_DIV_UINT16;
5533 params!(UInt32, UInt32) => BF::from(func::DivUint32) => UInt32, oid::FUNC_DIV_UINT32;
5534 params!(UInt64, UInt64) => BF::from(func::DivUint64) => UInt64, oid::FUNC_DIV_UINT64;
5535 params!(Float32, Float32) => BF::from(func::DivFloat32) => Float32, 588;
5536 params!(Float64, Float64) => BF::from(func::DivFloat64) => Float64, 593;
5537 params!(Interval, Float64) => BF::from(func::DivInterval) => Interval, 1585;
5538 params!(Numeric, Numeric) => BF::from(func::DivNumeric) => Numeric, 1761;
5539 },
5540 "%" => Scalar {
5541 params!(Int16, Int16) => BF::from(func::ModInt16) => Int16, 529;
5542 params!(Int32, Int32) => BF::from(func::ModInt32) => Int32, 530;
5543 params!(Int64, Int64) => BF::from(func::ModInt64) => Int64, 439;
5544 params!(UInt16, UInt16) => BF::from(func::ModUint16) => UInt16, oid::FUNC_MOD_UINT16;
5545 params!(UInt32, UInt32) => BF::from(func::ModUint32) => UInt32, oid::FUNC_MOD_UINT32;
5546 params!(UInt64, UInt64) => BF::from(func::ModUint64) => UInt64, oid::FUNC_MOD_UINT64;
5547 params!(Float32, Float32) => BF::from(func::ModFloat32) => Float32, oid::OP_MOD_F32_OID;
5548 params!(Float64, Float64) => BF::from(func::ModFloat64) => Float64, oid::OP_MOD_F64_OID;
5549 params!(Numeric, Numeric) => BF::from(func::ModNumeric) => Numeric, 1762;
5550 },
5551 "&" => Scalar {
5552 params!(Int16, Int16) => BF::from(func::BitAndInt16) => Int16, 1874;
5553 params!(Int32, Int32) => BF::from(func::BitAndInt32) => Int32, 1880;
5554 params!(Int64, Int64) => BF::from(func::BitAndInt64) => Int64, 1886;
5555 params!(UInt16, UInt16) => BF::from(func::BitAndUint16) => UInt16, oid::FUNC_AND_UINT16;
5556 params!(UInt32, UInt32) => BF::from(func::BitAndUint32) => UInt32, oid::FUNC_AND_UINT32;
5557 params!(UInt64, UInt64) => BF::from(func::BitAndUint64) => UInt64, oid::FUNC_AND_UINT64;
5558 },
5559 "|" => Scalar {
5560 params!(Int16, Int16) => BF::from(func::BitOrInt16) => Int16, 1875;
5561 params!(Int32, Int32) => BF::from(func::BitOrInt32) => Int32, 1881;
5562 params!(Int64, Int64) => BF::from(func::BitOrInt64) => Int64, 1887;
5563 params!(UInt16, UInt16) => BF::from(func::BitOrUint16) => UInt16, oid::FUNC_OR_UINT16;
5564 params!(UInt32, UInt32) => BF::from(func::BitOrUint32) => UInt32, oid::FUNC_OR_UINT32;
5565 params!(UInt64, UInt64) => BF::from(func::BitOrUint64) => UInt64, oid::FUNC_OR_UINT64;
5566 },
5567 "#" => Scalar {
5568 params!(Int16, Int16) => BF::from(func::BitXorInt16) => Int16, 1876;
5569 params!(Int32, Int32) => BF::from(func::BitXorInt32) => Int32, 1882;
5570 params!(Int64, Int64) => BF::from(func::BitXorInt64) => Int64, 1888;
5571 params!(UInt16, UInt16) => BF::from(func::BitXorUint16) => UInt16, oid::FUNC_XOR_UINT16;
5572 params!(UInt32, UInt32) => BF::from(func::BitXorUint32) => UInt32, oid::FUNC_XOR_UINT32;
5573 params!(UInt64, UInt64) => BF::from(func::BitXorUint64) => UInt64, oid::FUNC_XOR_UINT64;
5574 },
5575 "<<" => Scalar {
5576 params!(Int16, Int32) => BF::from(func::BitShiftLeftInt16) => Int16, 1878;
5577 params!(Int32, Int32) => BF::from(func::BitShiftLeftInt32) => Int32, 1884;
5578 params!(Int64, Int32) => BF::from(func::BitShiftLeftInt64) => Int64, 1890;
5579 params!(UInt16, UInt32) => BF::from(func::BitShiftLeftUint16)
5580 => UInt16, oid::FUNC_SHIFT_LEFT_UINT16;
5581 params!(UInt32, UInt32) => BF::from(func::BitShiftLeftUint32)
5582 => UInt32, oid::FUNC_SHIFT_LEFT_UINT32;
5583 params!(UInt64, UInt32) => BF::from(func::BitShiftLeftUint64)
5584 => UInt64, oid::FUNC_SHIFT_LEFT_UINT64;
5585 params!(RangeAny, RangeAny) => BF::from(func::RangeBefore) => Bool, 3893;
5586 },
5587 ">>" => Scalar {
5588 params!(Int16, Int32) => BF::from(func::BitShiftRightInt16) => Int16, 1879;
5589 params!(Int32, Int32) => BF::from(func::BitShiftRightInt32) => Int32, 1885;
5590 params!(Int64, Int32) => BF::from(func::BitShiftRightInt64) => Int64, 1891;
5591 params!(UInt16, UInt32) => BF::from(func::BitShiftRightUint16)
5592 => UInt16, oid::FUNC_SHIFT_RIGHT_UINT16;
5593 params!(UInt32, UInt32) => BF::from(func::BitShiftRightUint32)
5594 => UInt32, oid::FUNC_SHIFT_RIGHT_UINT32;
5595 params!(UInt64, UInt32) => BF::from(func::BitShiftRightUint64)
5596 => UInt64, oid::FUNC_SHIFT_RIGHT_UINT64;
5597 params!(RangeAny, RangeAny) => BF::from(func::RangeAfter) => Bool, 3894;
5598 },
5599
5600 "~~*" => Scalar {
5602 params!(String, String) => BF::from(func::IsLikeMatchCaseInsensitive) => Bool, 1627;
5603 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5604 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5605 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5606 .call_binary(rhs, BF::from(func::IsLikeMatchCaseInsensitive))
5607 )
5608 }) => Bool, 1629;
5609 },
5610 "!~~*" => Scalar {
5611 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
5612 Ok(lhs
5613 .call_binary(rhs, BF::from(func::IsLikeMatchCaseInsensitive))
5614 .call_unary(UnaryFunc::Not(func::Not)))
5615 }) => Bool, 1628;
5616 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5617 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5618 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5619 .call_binary(rhs, BF::from(func::IsLikeMatchCaseInsensitive))
5620 .call_unary(UnaryFunc::Not(func::Not))
5621 )
5622 }) => Bool, 1630;
5623 },
5624
5625
5626 "~~" => Scalar {
5628 params!(String, String) => BF::from(func::IsLikeMatchCaseSensitive) => Bool, 1209;
5629 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5630 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5631 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5632 .call_binary(rhs, BF::from(func::IsLikeMatchCaseSensitive))
5633 )
5634 }) => Bool, 1211;
5635 },
5636 "!~~" => Scalar {
5637 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
5638 Ok(lhs
5639 .call_binary(rhs, BF::from(func::IsLikeMatchCaseSensitive))
5640 .call_unary(UnaryFunc::Not(func::Not)))
5641 }) => Bool, 1210;
5642 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5643 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5644 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5645 .call_binary(rhs, BF::from(func::IsLikeMatchCaseSensitive))
5646 .call_unary(UnaryFunc::Not(func::Not))
5647 )
5648 }) => Bool, 1212;
5649 },
5650
5651 "~" => Scalar {
5653 params!(Int16) => UnaryFunc::BitNotInt16(func::BitNotInt16) => Int16, 1877;
5654 params!(Int32) => UnaryFunc::BitNotInt32(func::BitNotInt32) => Int32, 1883;
5655 params!(Int64) => UnaryFunc::BitNotInt64(func::BitNotInt64) => Int64, 1889;
5656 params!(UInt16) => UnaryFunc::BitNotUint16(func::BitNotUint16)
5657 => UInt16, oid::FUNC_BIT_NOT_UINT16_OID;
5658 params!(UInt32) => UnaryFunc::BitNotUint32(func::BitNotUint32)
5659 => UInt32, oid::FUNC_BIT_NOT_UINT32_OID;
5660 params!(UInt64) => UnaryFunc::BitNotUint64(func::BitNotUint64)
5661 => UInt64, oid::FUNC_BIT_NOT_UINT64_OID;
5662 params!(String, String)
5663 => BinaryFunc::IsRegexpMatchCaseSensitive(
5664 func::IsRegexpMatchCaseSensitive,
5665 ) => Bool, 641;
5666 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5667 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5668 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5669 .call_binary(rhs, BinaryFunc::IsRegexpMatchCaseSensitive(
5670 func::IsRegexpMatchCaseSensitive,
5671 )))
5672 }) => Bool, 1055;
5673 },
5674 "~*" => Scalar {
5675 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
5676 Ok(lhs.call_binary(
5677 rhs,
5678 BinaryFunc::IsRegexpMatchCaseInsensitive(
5679 func::IsRegexpMatchCaseInsensitive,
5680 ),
5681 ))
5682 }) => Bool, 1228;
5683 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5684 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5685 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5686 .call_binary(rhs, BinaryFunc::IsRegexpMatchCaseInsensitive(
5687 func::IsRegexpMatchCaseInsensitive,
5688 )))
5689 }) => Bool, 1234;
5690 },
5691 "!~" => Scalar {
5692 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
5693 Ok(lhs
5694 .call_binary(rhs, BinaryFunc::IsRegexpMatchCaseSensitive(
5695 func::IsRegexpMatchCaseSensitive,
5696 ))
5697 .call_unary(UnaryFunc::Not(func::Not)))
5698 }) => Bool, 642;
5699 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5700 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5701 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5702 .call_binary(rhs, BinaryFunc::IsRegexpMatchCaseSensitive(
5703 func::IsRegexpMatchCaseSensitive,
5704 ))
5705 .call_unary(UnaryFunc::Not(func::Not)))
5706 }) => Bool, 1056;
5707 },
5708 "!~*" => Scalar {
5709 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
5710 Ok(lhs
5711 .call_binary(rhs, BinaryFunc::IsRegexpMatchCaseInsensitive(
5712 func::IsRegexpMatchCaseInsensitive,
5713 ))
5714 .call_unary(UnaryFunc::Not(func::Not)))
5715 }) => Bool, 1229;
5716 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5717 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5718 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5719 .call_binary(rhs, BinaryFunc::IsRegexpMatchCaseInsensitive(
5720 func::IsRegexpMatchCaseInsensitive,
5721 ))
5722 .call_unary(UnaryFunc::Not(func::Not)))
5723 }) => Bool, 1235;
5724 },
5725
5726 "||" => Scalar {
5728 params!(String, NonVecAny) => Operation::binary(|ecx, lhs, rhs| {
5729 let rhs = typeconv::plan_cast(
5730 ecx,
5731 CastContext::Explicit,
5732 rhs,
5733 &SqlScalarType::String,
5734 )?;
5735 Ok(lhs.call_binary(rhs, func::TextConcatBinary))
5736 }) => String, 2779;
5737 params!(NonVecAny, String) => Operation::binary(|ecx, lhs, rhs| {
5738 let lhs = typeconv::plan_cast(
5739 ecx,
5740 CastContext::Explicit,
5741 lhs,
5742 &SqlScalarType::String,
5743 )?;
5744 Ok(lhs.call_binary(rhs, func::TextConcatBinary))
5745 }) => String, 2780;
5746 params!(String, String) => BF::from(func::TextConcatBinary) => String, 654;
5747 params!(Jsonb, Jsonb) => BF::from(func::JsonbConcat) => Jsonb, 3284;
5748 params!(ArrayAnyCompatible, ArrayAnyCompatible)
5749 => BF::from(func::ArrayArrayConcat) => ArrayAnyCompatible, 375;
5750 params!(ListAnyCompatible, ListAnyCompatible)
5751 => BF::from(func::ListListConcat)
5752 => ListAnyCompatible, oid::OP_CONCAT_LIST_LIST_OID;
5753 params!(ListAnyCompatible, ListElementAnyCompatible)
5754 => BF::from(func::ListElementConcat)
5755 => ListAnyCompatible, oid::OP_CONCAT_LIST_ELEMENT_OID;
5756 params!(ListElementAnyCompatible, ListAnyCompatible)
5757 => BF::from(func::ElementListConcat)
5758 => ListAnyCompatible, oid::OP_CONCAT_ELEMENY_LIST_OID;
5759 },
5760
5761 "->" => Scalar {
5763 params!(Jsonb, Int64) => BF::from(func::JsonbGetInt64) => Jsonb, 3212;
5764 params!(Jsonb, String) => BF::from(func::JsonbGetString) => Jsonb, 3211;
5765 params!(MapAny, String) => BF::from(func::MapGetValue)
5766 => Any, oid::OP_GET_VALUE_MAP_OID;
5767 },
5768 "->>" => Scalar {
5769 params!(Jsonb, Int64) => BF::from(func::JsonbGetInt64Stringify) => String, 3481;
5770 params!(Jsonb, String) => BF::from(func::JsonbGetStringStringify) => String, 3477;
5771 },
5772 "#>" => Scalar {
5773 params!(Jsonb, SqlScalarType::Array(Box::new(SqlScalarType::String)))
5774 => BF::from(func::JsonbGetPath) => Jsonb, 3213;
5775 },
5776 "#>>" => Scalar {
5777 params!(Jsonb, SqlScalarType::Array(Box::new(SqlScalarType::String)))
5778 => BF::from(func::JsonbGetPathStringify) => String, 3206;
5779 },
5780 "@>" => Scalar {
5781 params!(Jsonb, Jsonb) => BF::from(func::JsonbContainsJsonb) => Bool, 3246;
5782 params!(Jsonb, String) => Operation::binary(|_ecx, lhs, rhs| {
5783 Ok(lhs.call_binary(
5784 rhs.call_unary(UnaryFunc::CastStringToJsonb(func::CastStringToJsonb)),
5785 BinaryFunc::from(func::JsonbContainsJsonb),
5786 ))
5787 }) => Bool, oid::OP_CONTAINS_JSONB_STRING_OID;
5788 params!(String, Jsonb) => Operation::binary(|_ecx, lhs, rhs| {
5789 Ok(lhs.call_unary(UnaryFunc::CastStringToJsonb(func::CastStringToJsonb))
5790 .call_binary(rhs, func::JsonbContainsJsonb))
5791 }) => Bool, oid::OP_CONTAINS_STRING_JSONB_OID;
5792 params!(MapAnyCompatible, MapAnyCompatible)
5793 => BF::from(func::MapContainsMap)
5794 => Bool, oid::OP_CONTAINS_MAP_MAP_OID;
5795 params!(RangeAny, AnyElement) => Operation::binary(|ecx, lhs, rhs| {
5796 let elem_type = ecx.scalar_type(&lhs).unwrap_range_element_type().clone();
5797 let f = match elem_type {
5798 SqlScalarType::Int32 => BF::from(func::RangeContainsI32),
5799 SqlScalarType::Int64 => BF::from(func::RangeContainsI64),
5800 SqlScalarType::Date => BF::from(func::RangeContainsDate),
5801 SqlScalarType::Numeric { .. } => BF::from(func::RangeContainsNumeric),
5802 SqlScalarType::Timestamp { .. } => BF::from(func::RangeContainsTimestamp),
5803 SqlScalarType::TimestampTz { .. } => BF::from(func::RangeContainsTimestampTz),
5804 _ => bail_unsupported!(format!("range element type: {elem_type:?}")),
5805 };
5806 Ok(lhs.call_binary(rhs, f))
5807 }) => Bool, 3889;
5808 params!(RangeAny, RangeAny) => Operation::binary(|_ecx, lhs, rhs| {
5809 Ok(lhs.call_binary(rhs, BF::from(func::RangeContainsRange)))
5810 }) => Bool, 3890;
5811 params!(ArrayAny, ArrayAny) => Operation::binary(|_ecx, lhs, rhs| {
5812 Ok(lhs.call_binary(rhs, BF::from(func::ArrayContainsArray)))
5813 }) => Bool, 2751;
5814 params!(ListAny, ListAny) => Operation::binary(|_ecx, lhs, rhs| {
5815 Ok(lhs.call_binary(rhs, BF::from(func::ListContainsList)))
5816 }) => Bool, oid::OP_CONTAINS_LIST_LIST_OID;
5817 },
5818 "<@" => Scalar {
5819 params!(Jsonb, Jsonb) => Operation::binary(|_ecx, lhs, rhs| {
5820 Ok(rhs.call_binary(
5821 lhs,
5822 func::JsonbContainsJsonb
5823 ))
5824 }) => Bool, 3250;
5825 params!(Jsonb, String) => Operation::binary(|_ecx, lhs, rhs| {
5826 Ok(rhs.call_unary(UnaryFunc::CastStringToJsonb(func::CastStringToJsonb))
5827 .call_binary(lhs, func::JsonbContainsJsonb))
5828 }) => Bool, oid::OP_CONTAINED_JSONB_STRING_OID;
5829 params!(String, Jsonb) => Operation::binary(|_ecx, lhs, rhs| {
5830 Ok(rhs.call_binary(
5831 lhs.call_unary(UnaryFunc::CastStringToJsonb(func::CastStringToJsonb)),
5832 func::JsonbContainsJsonb,
5833 ))
5834 }) => Bool, oid::OP_CONTAINED_STRING_JSONB_OID;
5835 params!(MapAnyCompatible, MapAnyCompatible) => Operation::binary(|_ecx, lhs, rhs| {
5836 Ok(rhs.call_binary(lhs, func::MapContainsMap))
5837 }) => Bool, oid::OP_CONTAINED_MAP_MAP_OID;
5838 params!(AnyElement, RangeAny) => Operation::binary(|ecx, lhs, rhs| {
5839 let elem_type = ecx.scalar_type(&rhs).unwrap_range_element_type().clone();
5840 let f = match elem_type {
5841 SqlScalarType::Int32 => BF::from(func::RangeContainsI32Rev),
5842 SqlScalarType::Int64 => BF::from(func::RangeContainsI64Rev),
5843 SqlScalarType::Date => BF::from(func::RangeContainsDateRev),
5844 SqlScalarType::Numeric { .. } => BF::from(func::RangeContainsNumericRev),
5845 SqlScalarType::Timestamp { .. } => BF::from(func::RangeContainsTimestampRev),
5846 SqlScalarType::TimestampTz { .. } => {
5847 BF::from(func::RangeContainsTimestampTzRev)
5848 }
5849 _ => bail_unsupported!(format!("range element type: {elem_type:?}")),
5850 };
5851 Ok(rhs.call_binary(lhs, f))
5852 }) => Bool, 3891;
5853 params!(RangeAny, RangeAny) => Operation::binary(|_ecx, lhs, rhs| {
5854 Ok(rhs.call_binary(lhs, BF::from(func::RangeContainsRangeRev)))
5855 }) => Bool, 3892;
5856 params!(ArrayAny, ArrayAny) => Operation::binary(|_ecx, lhs, rhs| {
5857 Ok(lhs.call_binary(rhs, BF::from(func::ArrayContainsArrayRev)))
5858 }) => Bool, 2752;
5859 params!(ListAny, ListAny) => Operation::binary(|_ecx, lhs, rhs| {
5860 Ok(lhs.call_binary(rhs, BF::from(func::ListContainsListRev)))
5861 }) => Bool, oid::OP_IS_CONTAINED_LIST_LIST_OID;
5862 },
5863 "?" => Scalar {
5864 params!(Jsonb, String) => BF::from(func::JsonbContainsString) => Bool, 3247;
5865 params!(MapAny, String) => BF::from(func::MapContainsKey)
5866 => Bool, oid::OP_CONTAINS_KEY_MAP_OID;
5867 },
5868 "?&" => Scalar {
5869 params!(MapAny, SqlScalarType::Array(Box::new(SqlScalarType::String)))
5870 => BF::from(func::MapContainsAllKeys)
5871 => Bool, oid::OP_CONTAINS_ALL_KEYS_MAP_OID;
5872 },
5873 "?|" => Scalar {
5874 params!(MapAny, SqlScalarType::Array(Box::new(SqlScalarType::String)))
5875 => BF::from(func::MapContainsAnyKeys)
5876 => Bool, oid::OP_CONTAINS_ANY_KEYS_MAP_OID;
5877 },
5878 "&&" => Scalar {
5879 params!(RangeAny, RangeAny) => BF::from(func::RangeOverlaps) => Bool, 3888;
5880 },
5881 "&<" => Scalar {
5882 params!(RangeAny, RangeAny) => BF::from(func::RangeOverleft) => Bool, 3895;
5883 },
5884 "&>" => Scalar {
5885 params!(RangeAny, RangeAny) => BF::from(func::RangeOverright) => Bool, 3896;
5886 },
5887 "-|-" => Scalar {
5888 params!(RangeAny, RangeAny) => BF::from(func::RangeAdjacent) => Bool, 3897;
5889 },
5890
5891 "<" => Scalar {
5893 params!(Numeric, Numeric) => BF::from(func::Lt) => Bool, 1754;
5894 params!(Bool, Bool) => BF::from(func::Lt) => Bool, 58;
5895 params!(Int16, Int16) => BF::from(func::Lt) => Bool, 95;
5896 params!(Int32, Int32) => BF::from(func::Lt) => Bool, 97;
5897 params!(Int64, Int64) => BF::from(func::Lt) => Bool, 412;
5898 params!(UInt16, UInt16) => BF::from(func::Lt) => Bool, oid::FUNC_LT_UINT16_OID;
5899 params!(UInt32, UInt32) => BF::from(func::Lt) => Bool, oid::FUNC_LT_UINT32_OID;
5900 params!(UInt64, UInt64) => BF::from(func::Lt) => Bool, oid::FUNC_LT_UINT64_OID;
5901 params!(Float32, Float32) => BF::from(func::Lt) => Bool, 622;
5902 params!(Float64, Float64) => BF::from(func::Lt) => Bool, 672;
5903 params!(Oid, Oid) => BF::from(func::Lt) => Bool, 609;
5904 params!(Date, Date) => BF::from(func::Lt) => Bool, 1095;
5905 params!(Time, Time) => BF::from(func::Lt) => Bool, 1110;
5906 params!(Timestamp, Timestamp) => BF::from(func::Lt) => Bool, 2062;
5907 params!(TimestampTz, TimestampTz) => BF::from(func::Lt) => Bool, 1322;
5908 params!(Uuid, Uuid) => BF::from(func::Lt) => Bool, 2974;
5909 params!(Interval, Interval) => BF::from(func::Lt) => Bool, 1332;
5910 params!(Bytes, Bytes) => BF::from(func::Lt) => Bool, 1957;
5911 params!(String, String) => BF::from(func::Lt) => Bool, 664;
5912 params!(Char, Char) => BF::from(func::Lt) => Bool, 1058;
5913 params!(PgLegacyChar, PgLegacyChar) => BF::from(func::Lt) => Bool, 631;
5914 params!(PgLegacyName, PgLegacyName) => BF::from(func::Lt) => Bool, 660;
5915 params!(Jsonb, Jsonb) => BF::from(func::Lt) => Bool, 3242;
5916 params!(ArrayAny, ArrayAny) => BF::from(func::Lt) => Bool, 1072;
5917 params!(RecordAny, RecordAny) => BF::from(func::Lt) => Bool, 2990;
5918 params!(MzTimestamp, MzTimestamp) => BF::from(func::Lt)
5919 => Bool, oid::FUNC_MZ_TIMESTAMP_LT_MZ_TIMESTAMP_OID;
5920 params!(RangeAny, RangeAny) => BF::from(func::Lt) => Bool, 3884;
5921 },
5922 "<=" => Scalar {
5923 params!(Numeric, Numeric) => BF::from(func::Lte) => Bool, 1755;
5924 params!(Bool, Bool) => BF::from(func::Lte) => Bool, 1694;
5925 params!(Int16, Int16) => BF::from(func::Lte) => Bool, 522;
5926 params!(Int32, Int32) => BF::from(func::Lte) => Bool, 523;
5927 params!(Int64, Int64) => BF::from(func::Lte) => Bool, 414;
5928 params!(UInt16, UInt16) => BF::from(func::Lte) => Bool, oid::FUNC_LTE_UINT16_OID;
5929 params!(UInt32, UInt32) => BF::from(func::Lte) => Bool, oid::FUNC_LTE_UINT32_OID;
5930 params!(UInt64, UInt64) => BF::from(func::Lte) => Bool, oid::FUNC_LTE_UINT64_OID;
5931 params!(Float32, Float32) => BF::from(func::Lte) => Bool, 624;
5932 params!(Float64, Float64) => BF::from(func::Lte) => Bool, 673;
5933 params!(Oid, Oid) => BF::from(func::Lte) => Bool, 611;
5934 params!(Date, Date) => BF::from(func::Lte) => Bool, 1096;
5935 params!(Time, Time) => BF::from(func::Lte) => Bool, 1111;
5936 params!(Timestamp, Timestamp) => BF::from(func::Lte) => Bool, 2063;
5937 params!(TimestampTz, TimestampTz) => BF::from(func::Lte) => Bool, 1323;
5938 params!(Uuid, Uuid) => BF::from(func::Lte) => Bool, 2976;
5939 params!(Interval, Interval) => BF::from(func::Lte) => Bool, 1333;
5940 params!(Bytes, Bytes) => BF::from(func::Lte) => Bool, 1958;
5941 params!(String, String) => BF::from(func::Lte) => Bool, 665;
5942 params!(Char, Char) => BF::from(func::Lte) => Bool, 1059;
5943 params!(PgLegacyChar, PgLegacyChar) => BF::from(func::Lte) => Bool, 632;
5944 params!(PgLegacyName, PgLegacyName) => BF::from(func::Lte) => Bool, 661;
5945 params!(Jsonb, Jsonb) => BF::from(func::Lte) => Bool, 3244;
5946 params!(ArrayAny, ArrayAny) => BF::from(func::Lte) => Bool, 1074;
5947 params!(RecordAny, RecordAny) => BF::from(func::Lte) => Bool, 2992;
5948 params!(MzTimestamp, MzTimestamp) => BF::from(func::Lte)
5949 => Bool, oid::FUNC_MZ_TIMESTAMP_LTE_MZ_TIMESTAMP_OID;
5950 params!(RangeAny, RangeAny) => BF::from(func::Lte) => Bool, 3885;
5951 },
5952 ">" => Scalar {
5953 params!(Numeric, Numeric) => BF::from(func::Gt) => Bool, 1756;
5954 params!(Bool, Bool) => BF::from(func::Gt) => Bool, 59;
5955 params!(Int16, Int16) => BF::from(func::Gt) => Bool, 520;
5956 params!(Int32, Int32) => BF::from(func::Gt) => Bool, 521;
5957 params!(Int64, Int64) => BF::from(func::Gt) => Bool, 413;
5958 params!(UInt16, UInt16) => BF::from(func::Gt) => Bool, oid::FUNC_GT_UINT16_OID;
5959 params!(UInt32, UInt32) => BF::from(func::Gt) => Bool, oid::FUNC_GT_UINT32_OID;
5960 params!(UInt64, UInt64) => BF::from(func::Gt) => Bool, oid::FUNC_GT_UINT64_OID;
5961 params!(Float32, Float32) => BF::from(func::Gt) => Bool, 623;
5962 params!(Float64, Float64) => BF::from(func::Gt) => Bool, 674;
5963 params!(Oid, Oid) => BF::from(func::Gt) => Bool, 610;
5964 params!(Date, Date) => BF::from(func::Gt) => Bool, 1097;
5965 params!(Time, Time) => BF::from(func::Gt) => Bool, 1112;
5966 params!(Timestamp, Timestamp) => BF::from(func::Gt) => Bool, 2064;
5967 params!(TimestampTz, TimestampTz) => BF::from(func::Gt) => Bool, 1324;
5968 params!(Uuid, Uuid) => BF::from(func::Gt) => Bool, 2975;
5969 params!(Interval, Interval) => BF::from(func::Gt) => Bool, 1334;
5970 params!(Bytes, Bytes) => BF::from(func::Gt) => Bool, 1959;
5971 params!(String, String) => BF::from(func::Gt) => Bool, 666;
5972 params!(Char, Char) => BF::from(func::Gt) => Bool, 1060;
5973 params!(PgLegacyChar, PgLegacyChar) => BF::from(func::Gt) => Bool, 633;
5974 params!(PgLegacyName, PgLegacyName) => BF::from(func::Gt) => Bool, 662;
5975 params!(Jsonb, Jsonb) => BF::from(func::Gt) => Bool, 3243;
5976 params!(ArrayAny, ArrayAny) => BF::from(func::Gt) => Bool, 1073;
5977 params!(RecordAny, RecordAny) => BF::from(func::Gt) => Bool, 2991;
5978 params!(MzTimestamp, MzTimestamp) => BF::from(func::Gt)
5979 => Bool, oid::FUNC_MZ_TIMESTAMP_GT_MZ_TIMESTAMP_OID;
5980 params!(RangeAny, RangeAny) => BF::from(func::Gt) => Bool, 3887;
5981 },
5982 ">=" => Scalar {
5983 params!(Numeric, Numeric) => BF::from(func::Gte) => Bool, 1757;
5984 params!(Bool, Bool) => BF::from(func::Gte) => Bool, 1695;
5985 params!(Int16, Int16) => BF::from(func::Gte) => Bool, 524;
5986 params!(Int32, Int32) => BF::from(func::Gte) => Bool, 525;
5987 params!(Int64, Int64) => BF::from(func::Gte) => Bool, 415;
5988 params!(UInt16, UInt16) => BF::from(func::Gte) => Bool, oid::FUNC_GTE_UINT16_OID;
5989 params!(UInt32, UInt32) => BF::from(func::Gte) => Bool, oid::FUNC_GTE_UINT32_OID;
5990 params!(UInt64, UInt64) => BF::from(func::Gte) => Bool, oid::FUNC_GTE_UINT64_OID;
5991 params!(Float32, Float32) => BF::from(func::Gte) => Bool, 625;
5992 params!(Float64, Float64) => BF::from(func::Gte) => Bool, 675;
5993 params!(Oid, Oid) => BF::from(func::Gte) => Bool, 612;
5994 params!(Date, Date) => BF::from(func::Gte) => Bool, 1098;
5995 params!(Time, Time) => BF::from(func::Gte) => Bool, 1113;
5996 params!(Timestamp, Timestamp) => BF::from(func::Gte) => Bool, 2065;
5997 params!(TimestampTz, TimestampTz) => BF::from(func::Gte) => Bool, 1325;
5998 params!(Uuid, Uuid) => BF::from(func::Gte) => Bool, 2977;
5999 params!(Interval, Interval) => BF::from(func::Gte) => Bool, 1335;
6000 params!(Bytes, Bytes) => BF::from(func::Gte) => Bool, 1960;
6001 params!(String, String) => BF::from(func::Gte) => Bool, 667;
6002 params!(Char, Char) => BF::from(func::Gte) => Bool, 1061;
6003 params!(PgLegacyChar, PgLegacyChar) => BF::from(func::Gte) => Bool, 634;
6004 params!(PgLegacyName, PgLegacyName) => BF::from(func::Gte) => Bool, 663;
6005 params!(Jsonb, Jsonb) => BF::from(func::Gte) => Bool, 3245;
6006 params!(ArrayAny, ArrayAny) => BF::from(func::Gte) => Bool, 1075;
6007 params!(RecordAny, RecordAny) => BF::from(func::Gte) => Bool, 2993;
6008 params!(MzTimestamp, MzTimestamp) => BF::from(func::Gte)
6009 => Bool, oid::FUNC_MZ_TIMESTAMP_GTE_MZ_TIMESTAMP_OID;
6010 params!(RangeAny, RangeAny) => BF::from(func::Gte) => Bool, 3886;
6011 },
6012 "=" => Scalar {
6023 params!(Numeric, Numeric) => BF::from(func::Eq) => Bool, 1752;
6024 params!(Bool, Bool) => BF::from(func::Eq) => Bool, 91;
6025 params!(Int16, Int16) => BF::from(func::Eq) => Bool, 94;
6026 params!(Int32, Int32) => BF::from(func::Eq) => Bool, 96;
6027 params!(Int64, Int64) => BF::from(func::Eq) => Bool, 410;
6028 params!(UInt16, UInt16) => BF::from(func::Eq) => Bool, oid::FUNC_EQ_UINT16_OID;
6029 params!(UInt32, UInt32) => BF::from(func::Eq) => Bool, oid::FUNC_EQ_UINT32_OID;
6030 params!(UInt64, UInt64) => BF::from(func::Eq) => Bool, oid::FUNC_EQ_UINT64_OID;
6031 params!(Float32, Float32) => BF::from(func::Eq) => Bool, 620;
6032 params!(Float64, Float64) => BF::from(func::Eq) => Bool, 670;
6033 params!(Oid, Oid) => BF::from(func::Eq) => Bool, 607;
6034 params!(Date, Date) => BF::from(func::Eq) => Bool, 1093;
6035 params!(Time, Time) => BF::from(func::Eq) => Bool, 1108;
6036 params!(Timestamp, Timestamp) => BF::from(func::Eq) => Bool, 2060;
6037 params!(TimestampTz, TimestampTz) => BF::from(func::Eq) => Bool, 1320;
6038 params!(Uuid, Uuid) => BF::from(func::Eq) => Bool, 2972;
6039 params!(Interval, Interval) => BF::from(func::Eq) => Bool, 1330;
6040 params!(Bytes, Bytes) => BF::from(func::Eq) => Bool, 1955;
6041 params!(String, String) => BF::from(func::Eq) => Bool, 98;
6042 params!(Char, Char) => BF::from(func::Eq) => Bool, 1054;
6043 params!(PgLegacyChar, PgLegacyChar) => BF::from(func::Eq) => Bool, 92;
6044 params!(PgLegacyName, PgLegacyName) => BF::from(func::Eq) => Bool, 93;
6045 params!(Jsonb, Jsonb) => BF::from(func::Eq) => Bool, 3240;
6046 params!(ListAny, ListAny) => BF::from(func::Eq) => Bool, oid::FUNC_LIST_EQ_OID;
6047 params!(ArrayAny, ArrayAny) => BF::from(func::Eq) => Bool, 1070;
6048 params!(RecordAny, RecordAny) => BF::from(func::Eq) => Bool, 2988;
6049 params!(MzTimestamp, MzTimestamp) => BF::from(func::Eq)
6050 => Bool, oid::FUNC_MZ_TIMESTAMP_EQ_MZ_TIMESTAMP_OID;
6051 params!(RangeAny, RangeAny) => BF::from(func::Eq) => Bool, 3882;
6052 params!(MzAclItem, MzAclItem) => BF::from(func::Eq)
6053 => Bool, oid::FUNC_MZ_ACL_ITEM_EQ_MZ_ACL_ITEM_OID;
6054 params!(AclItem, AclItem) => BF::from(func::Eq) => Bool, 974;
6055 },
6056 "<>" => Scalar {
6057 params!(Numeric, Numeric) => BF::from(func::NotEq) => Bool, 1753;
6058 params!(Bool, Bool) => BF::from(func::NotEq) => Bool, 85;
6059 params!(Int16, Int16) => BF::from(func::NotEq) => Bool, 519;
6060 params!(Int32, Int32) => BF::from(func::NotEq) => Bool, 518;
6061 params!(Int64, Int64) => BF::from(func::NotEq) => Bool, 411;
6062 params!(UInt16, UInt16) => BF::from(func::NotEq) => Bool, oid::FUNC_NOT_EQ_UINT16_OID;
6063 params!(UInt32, UInt32) => BF::from(func::NotEq) => Bool, oid::FUNC_NOT_EQ_UINT32_OID;
6064 params!(UInt64, UInt64) => BF::from(func::NotEq) => Bool, oid::FUNC_NOT_EQ_UINT64_OID;
6065 params!(Float32, Float32) => BF::from(func::NotEq) => Bool, 621;
6066 params!(Float64, Float64) => BF::from(func::NotEq) => Bool, 671;
6067 params!(Oid, Oid) => BF::from(func::NotEq) => Bool, 608;
6068 params!(Date, Date) => BF::from(func::NotEq) => Bool, 1094;
6069 params!(Time, Time) => BF::from(func::NotEq) => Bool, 1109;
6070 params!(Timestamp, Timestamp) => BF::from(func::NotEq) => Bool, 2061;
6071 params!(TimestampTz, TimestampTz) => BF::from(func::NotEq) => Bool, 1321;
6072 params!(Uuid, Uuid) => BF::from(func::NotEq) => Bool, 2973;
6073 params!(Interval, Interval) => BF::from(func::NotEq) => Bool, 1331;
6074 params!(Bytes, Bytes) => BF::from(func::NotEq) => Bool, 1956;
6075 params!(String, String) => BF::from(func::NotEq) => Bool, 531;
6076 params!(Char, Char) => BF::from(func::NotEq) => Bool, 1057;
6077 params!(PgLegacyChar, PgLegacyChar) => BF::from(func::NotEq) => Bool, 630;
6078 params!(PgLegacyName, PgLegacyName) => BF::from(func::NotEq) => Bool, 643;
6079 params!(Jsonb, Jsonb) => BF::from(func::NotEq) => Bool, 3241;
6080 params!(ArrayAny, ArrayAny) => BF::from(func::NotEq) => Bool, 1071;
6081 params!(RecordAny, RecordAny) => BF::from(func::NotEq) => Bool, 2989;
6082 params!(MzTimestamp, MzTimestamp) => BF::from(func::NotEq)
6083 => Bool, oid::FUNC_MZ_TIMESTAMP_NOT_EQ_MZ_TIMESTAMP_OID;
6084 params!(RangeAny, RangeAny) => BF::from(func::NotEq) => Bool, 3883;
6085 params!(MzAclItem, MzAclItem) => BF::from(func::NotEq)
6086 => Bool, oid::FUNC_MZ_ACL_ITEM_NOT_EQ_MZ_ACL_ITEM_OID;
6087 }
6088 }
6089});
6090
6091pub fn resolve_op(op: &str) -> Result<&'static [FuncImpl<HirScalarExpr>], PlanError> {
6093 match OP_IMPLS.get(op) {
6094 Some(Func::Scalar(impls)) => Ok(impls),
6095 Some(_) => unreachable!("all operators must be scalar functions"),
6096 None => bail_unsupported!(format!("[{}]", op)),
6106 }
6107}
6108
6109fn current_settings(
6112 name: HirScalarExpr,
6113 missing_ok: HirScalarExpr,
6114) -> Result<HirScalarExpr, PlanError> {
6115 let expr = HirScalarExpr::call_binary(
6117 HirScalarExpr::call_unmaterializable(UnmaterializableFunc::ViewableVariables),
6118 HirScalarExpr::call_unary(name, UnaryFunc::Lower(func::Lower)),
6119 func::MapGetValue,
6120 );
6121 let expr = HirScalarExpr::if_then_else(
6122 missing_ok,
6123 expr.clone(),
6124 HirScalarExpr::call_variadic(
6125 variadic::ErrorIfNull,
6126 vec![
6127 expr,
6128 HirScalarExpr::literal(
6129 Datum::String("unrecognized configuration parameter"),
6130 SqlScalarType::String,
6131 ),
6132 ],
6133 ),
6134 );
6135 Ok(expr)
6136}