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 if let SqlScalarType::Array(elem) = &target {
1631 if matches!(
1632 **elem,
1633 SqlScalarType::List { .. } | SqlScalarType::Map { .. }
1634 ) {
1635 bail_unsupported!(format!(
1636 "{}[]",
1637 ecx.humanize_sql_scalar_type(elem, false)
1638 ));
1639 }
1640 }
1641 do_convert(cexpr, &target)?
1642 }
1643 };
1644 res_exprs.push(expr);
1645 }
1646
1647 Ok(res_exprs)
1648}
1649
1650macro_rules! params {
1652 ([$($p:expr),*], $v:ident...) => {
1653 ParamList::Variadic {
1654 leading: vec![$($p.into(),)*],
1655 trailing: $v.into(),
1656 }
1657 };
1658 ($v:ident...) => { ParamList::Variadic { leading: vec![], trailing: $v.into() } };
1659 ($($p:expr),*) => { ParamList::Exact(vec![$($p.into(),)*]) };
1660}
1661
1662macro_rules! impl_def {
1663 ($params:expr, $op:expr, $return_type:expr, $oid:expr) => {{
1673 FuncImpl {
1674 oid: $oid,
1675 params: $params.into(),
1676 op: $op.into(),
1677 return_type: $return_type.into(),
1678 }
1679 }};
1680}
1681
1682macro_rules! builtins {
1684 {
1685 $(
1686 $name:expr => $ty:ident {
1687 $($params:expr => $op:expr => $return_type:expr, $oid:expr;)+
1688 }
1689 ),+
1690 } => {{
1691
1692 let mut builtins = BTreeMap::new();
1693 $(
1694 let impls = vec![$(impl_def!($params, $op, $return_type, $oid)),+];
1695 let func = Func::$ty(impls);
1696 let expect_set_return = matches!(&func, Func::Table(_));
1697 for imp in func.func_impls() {
1698 assert_eq!(
1699 imp.return_is_set, expect_set_return,
1700 "wrong set return value for func with oid {}",
1701 imp.oid
1702 );
1703 }
1704 let old = builtins.insert($name, func);
1705 mz_ore::assert_none!(old, "duplicate entry in builtins list");
1706 )+
1707 builtins
1708 }};
1709}
1710
1711#[derive(Debug)]
1712pub struct TableFuncPlan {
1713 pub imp: TableFuncImpl,
1714 pub column_names: Vec<ColumnName>,
1715}
1716
1717#[derive(Debug)]
1750pub enum TableFuncImpl {
1751 CallTable {
1752 func: TableFunc,
1753 exprs: Vec<HirScalarExpr>,
1754 },
1755 Expr(HirRelationExpr),
1756}
1757
1758#[derive(Debug)]
1759pub enum Func {
1760 Scalar(Vec<FuncImpl<HirScalarExpr>>),
1761 Aggregate(Vec<FuncImpl<(HirScalarExpr, AggregateFunc)>>),
1762 Table(Vec<FuncImpl<TableFuncPlan>>),
1763 ScalarWindow(Vec<FuncImpl<ScalarWindowFunc>>),
1764 ValueWindow(Vec<FuncImpl<(HirScalarExpr, ValueWindowFunc)>>),
1765}
1766
1767impl Func {
1768 pub fn func_impls(&self) -> Vec<FuncImplCatalogDetails> {
1769 match self {
1770 Func::Scalar(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1771 Func::Aggregate(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1772 Func::Table(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1773 Func::ScalarWindow(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1774 Func::ValueWindow(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1775 }
1776 }
1777
1778 pub fn class(&self) -> &str {
1779 match self {
1780 Func::Scalar(..) => "scalar",
1781 Func::Aggregate(..) => "aggregate",
1782 Func::Table(..) => "table",
1783 Func::ScalarWindow(..) => "window",
1784 Func::ValueWindow(..) => "window",
1785 }
1786 }
1787}
1788
1789macro_rules! catalog_name_only {
1793 ($name:expr) => {
1794 panic!(
1795 "{} should be planned away before reaching function selection",
1796 $name
1797 )
1798 };
1799}
1800
1801macro_rules! privilege_fn {
1803 ( $fn_name:expr, $catalog_tbl:expr ) => {{
1804 let fn_name = $fn_name;
1805 let catalog_tbl = $catalog_tbl;
1806 let public_role = RoleId::Public;
1807 format!(
1808 "
1809 CASE
1810 -- We need to validate the privileges to return a proper error before anything
1811 -- else.
1812 WHEN NOT mz_internal.mz_validate_privileges($3)
1813 OR $1 IS NULL
1814 OR $2 IS NULL
1815 OR $3 IS NULL
1816 OR $1 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
1817 OR $2 NOT IN (SELECT oid FROM {catalog_tbl})
1818 THEN NULL
1819 ELSE COALESCE(
1820 (
1821 SELECT
1822 bool_or(
1823 mz_internal.mz_acl_item_contains_privilege(privilege, $3)
1824 )
1825 AS {fn_name}
1826 FROM
1827 (
1828 SELECT
1829 unnest(privileges)
1830 FROM
1831 {catalog_tbl}
1832 WHERE
1833 {catalog_tbl}.oid = $2
1834 )
1835 AS user_privs (privilege)
1836 LEFT JOIN mz_catalog.mz_roles ON
1837 mz_internal.mz_aclitem_grantee(privilege) = mz_roles.id
1838 WHERE
1839 mz_internal.mz_aclitem_grantee(privilege) = '{public_role}'
1840 OR pg_has_role($1, mz_roles.oid, 'USAGE')
1841 ),
1842 false
1843 )
1844 END
1845 ",
1846 )
1847 }};
1848}
1849
1850pub static PG_CATALOG_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
1852 use ParamType::*;
1853 use SqlScalarBaseType::*;
1854 let mut builtins = builtins! {
1855 "abs" => Scalar {
1868 params!(Int16) => UnaryFunc::AbsInt16(func::AbsInt16) => Int16, 1398;
1869 params!(Int32) => UnaryFunc::AbsInt32(func::AbsInt32) => Int32, 1397;
1870 params!(Int64) => UnaryFunc::AbsInt64(func::AbsInt64) => Int64, 1396;
1871 params!(Numeric) => UnaryFunc::AbsNumeric(func::AbsNumeric) => Numeric, 1705;
1872 params!(Float32) => UnaryFunc::AbsFloat32(func::AbsFloat32) => Float32, 1394;
1873 params!(Float64) => UnaryFunc::AbsFloat64(func::AbsFloat64) => Float64, 1395;
1874 },
1875 "aclexplode" => Table {
1876 params!(SqlScalarType::Array(Box::new(
1877 SqlScalarType::AclItem,
1878 ))) => Operation::unary(move |_ecx, aclitems| {
1879 Ok(TableFuncPlan {
1880 imp: TableFuncImpl::CallTable {
1881 func: TableFunc::AclExplode,
1882 exprs: vec![aclitems],
1883 },
1884 column_names: vec![
1885 "grantor".into(), "grantee".into(),
1886 "privilege_type".into(), "is_grantable".into(),
1887 ],
1888 })
1889 }) => ReturnType::set_of(RecordAny), 1689;
1890 },
1891 "array_cat" => Scalar {
1892 params!(ArrayAnyCompatible, ArrayAnyCompatible) => Operation::binary(|_ecx, lhs, rhs| {
1893 Ok(lhs.call_binary(rhs, func::ArrayArrayConcat))
1894 }) => ArrayAnyCompatible, 383;
1895 },
1896 "array_fill" => Scalar {
1897 params!(AnyElement, SqlScalarType::Array(Box::new(SqlScalarType::Int32)))
1898 => Operation::binary(|ecx, elem, dims| {
1899 let elem_type = ecx.scalar_type(&elem);
1900
1901 let elem_type = match elem_type.array_of_self_elem_type() {
1902 Ok(elem_type) => elem_type,
1903 Err(elem_type) => bail_unsupported!(
1904 format!("array_fill on {}", ecx.humanize_sql_scalar_type(&elem_type, false))
1907 ),
1908 };
1909
1910 Ok(HirScalarExpr::call_variadic(
1911 variadic::ArrayFill { elem_type },
1912 vec![elem, dims]
1913 ))
1914 }) => ArrayAny, 1193;
1915 params!(
1916 AnyElement,
1917 SqlScalarType::Array(Box::new(SqlScalarType::Int32)),
1918 SqlScalarType::Array(Box::new(SqlScalarType::Int32))
1919 ) => Operation::variadic(|ecx, exprs| {
1920 let elem_type = ecx.scalar_type(&exprs[0]);
1921
1922 let elem_type = match elem_type.array_of_self_elem_type() {
1923 Ok(elem_type) => elem_type,
1924 Err(elem_type) => bail_unsupported!(
1925 format!("array_fill on {}", ecx.humanize_sql_scalar_type(&elem_type, false))
1926 ),
1927 };
1928
1929 Ok(HirScalarExpr::call_variadic(variadic::ArrayFill { elem_type }, exprs))
1930 }) => ArrayAny, 1286;
1931 },
1932 "array_length" => Scalar {
1933 params![ArrayAny, Int64] => BinaryFunc::from(func::ArrayLength) => Int32, 2176;
1934 },
1935 "array_lower" => Scalar {
1936 params!(ArrayAny, Int64) => BinaryFunc::from(func::ArrayLower) => Int32, 2091;
1937 },
1938 "array_position" => Scalar {
1939 params!(ArrayAnyCompatible, AnyCompatible)
1940 => VariadicFunc::from(variadic::ArrayPosition) => Int32, 3277;
1941 params!(ArrayAnyCompatible, AnyCompatible, Int32)
1942 => VariadicFunc::from(variadic::ArrayPosition) => Int32, 3278;
1943 },
1944 "array_remove" => Scalar {
1945 params!(ArrayAnyCompatible, AnyCompatible)
1946 => BinaryFunc::from(func::ArrayRemove)
1947 => ArrayAnyCompatible, 3167;
1948 },
1949 "array_to_string" => Scalar {
1950 params!(ArrayAny, String) => Operation::variadic(array_to_string) => String, 395;
1951 params!(ArrayAny, String, String)
1952 => Operation::variadic(array_to_string) => String, 384;
1953 },
1954 "array_upper" => Scalar {
1955 params!(ArrayAny, Int64) => BinaryFunc::from(func::ArrayUpper) => Int32, 2092;
1956 },
1957 "ascii" => Scalar {
1958 params!(String) => UnaryFunc::Ascii(func::Ascii) => Int32, 1620;
1959 },
1960 "avg" => Scalar {
1961 params!(Int64) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Numeric, 2100;
1962 params!(Int32) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Numeric, 2101;
1963 params!(Int16) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Numeric, 2102;
1964 params!(UInt64) =>
1965 Operation::nullary(|_ecx| catalog_name_only!("avg"))
1966 => Numeric, oid::FUNC_AVG_UINT64_OID;
1967 params!(UInt32) =>
1968 Operation::nullary(|_ecx| catalog_name_only!("avg"))
1969 => Numeric, oid::FUNC_AVG_UINT32_OID;
1970 params!(UInt16) =>
1971 Operation::nullary(|_ecx| catalog_name_only!("avg"))
1972 => Numeric, oid::FUNC_AVG_UINT16_OID;
1973 params!(Float32) =>
1974 Operation::nullary(|_ecx| catalog_name_only!("avg"))
1975 => Float64, 2104;
1976 params!(Float64) =>
1977 Operation::nullary(|_ecx| catalog_name_only!("avg"))
1978 => Float64, 2105;
1979 params!(Interval) =>
1980 Operation::nullary(|_ecx| catalog_name_only!("avg"))
1981 => Interval, 2106;
1982 },
1983 "bit_count" => Scalar {
1984 params!(Bytes) => UnaryFunc::BitCountBytes(func::BitCountBytes) => Int64, 6163;
1985 },
1986 "bit_length" => Scalar {
1987 params!(Bytes) => UnaryFunc::BitLengthBytes(func::BitLengthBytes) => Int32, 1810;
1988 params!(String) => UnaryFunc::BitLengthString(func::BitLengthString) => Int32, 1811;
1989 },
1990 "btrim" => Scalar {
1991 params!(String) => UnaryFunc::TrimWhitespace(func::TrimWhitespace) => String, 885;
1992 params!(String, String) => BinaryFunc::from(func::Trim) => String, 884;
1993 },
1994 "cbrt" => Scalar {
1995 params!(Float64) => UnaryFunc::CbrtFloat64(func::CbrtFloat64) => Float64, 1345;
1996 },
1997 "ceil" => Scalar {
1998 params!(Float32) => UnaryFunc::CeilFloat32(func::CeilFloat32)
1999 => Float32, oid::FUNC_CEIL_F32_OID;
2000 params!(Float64) => UnaryFunc::CeilFloat64(func::CeilFloat64) => Float64, 2308;
2001 params!(Numeric) => UnaryFunc::CeilNumeric(func::CeilNumeric) => Numeric, 1711;
2002 },
2003 "ceiling" => Scalar {
2004 params!(Float32) => UnaryFunc::CeilFloat32(func::CeilFloat32)
2005 => Float32, oid::FUNC_CEILING_F32_OID;
2006 params!(Float64) => UnaryFunc::CeilFloat64(func::CeilFloat64) => Float64, 2320;
2007 params!(Numeric) => UnaryFunc::CeilNumeric(func::CeilNumeric) => Numeric, 2167;
2008 },
2009 "char_length" => Scalar {
2010 params!(String) => UnaryFunc::CharLength(func::CharLength) => Int32, 1381;
2011 },
2012 "col_description" => Scalar {
2014 params!(Oid, Int32) => sql_impl_func(
2015 "(SELECT description
2016 FROM pg_description
2017 WHERE objoid = $1 AND classoid = 'pg_class'::regclass AND objsubid = $2)"
2018 ) => String, 1216;
2019 },
2020 "concat" => Scalar {
2021 params!(Any...) => Operation::variadic(|ecx, cexprs| {
2022 if cexprs.is_empty() {
2023 sql_bail!("No function matches the given name and argument types. \
2024 You might need to add explicit type casts.")
2025 }
2026 let mut exprs = vec![];
2027 for expr in cexprs {
2028 exprs.push(match ecx.scalar_type(&expr) {
2029 SqlScalarType::Bool => expr.call_unary(
2032 UnaryFunc::CastBoolToStringNonstandard(
2033 func::CastBoolToStringNonstandard,
2034 ),
2035 ),
2036 SqlScalarType::Char { length } => {
2038 expr.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
2039 }
2040 _ => typeconv::to_string(ecx, expr)?
2041 });
2042 }
2043 Ok(HirScalarExpr::call_variadic(variadic::Concat, exprs))
2044 }) => String, 3058;
2045 },
2046 "concat_ws" => Scalar {
2047 params!([String], Any...) => Operation::variadic(|ecx, cexprs| {
2048 if cexprs.len() < 2 {
2049 sql_bail!("No function matches the given name and argument types. \
2050 You might need to add explicit type casts.")
2051 }
2052 let mut exprs = vec![];
2053 for expr in cexprs {
2054 exprs.push(match ecx.scalar_type(&expr) {
2055 SqlScalarType::Bool => expr.call_unary(
2058 UnaryFunc::CastBoolToStringNonstandard(
2059 func::CastBoolToStringNonstandard,
2060 ),
2061 ),
2062 SqlScalarType::Char { length } => {
2064 expr.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
2065 }
2066 _ => typeconv::to_string(ecx, expr)?
2067 });
2068 }
2069 Ok(HirScalarExpr::call_variadic(variadic::ConcatWs, exprs))
2070 }) => String, 3059;
2071 },
2072 "convert_from" => Scalar {
2073 params!(Bytes, String) => BinaryFunc::from(func::ConvertFrom) => String, 1714;
2074 },
2075 "cos" => Scalar {
2076 params!(Float64) => UnaryFunc::Cos(func::Cos) => Float64, 1605;
2077 },
2078 "acos" => Scalar {
2079 params!(Float64) => UnaryFunc::Acos(func::Acos) => Float64, 1601;
2080 },
2081 "cosh" => Scalar {
2082 params!(Float64) => UnaryFunc::Cosh(func::Cosh) => Float64, 2463;
2083 },
2084 "acosh" => Scalar {
2085 params!(Float64) => UnaryFunc::Acosh(func::Acosh) => Float64, 2466;
2086 },
2087 "cot" => Scalar {
2088 params!(Float64) => UnaryFunc::Cot(func::Cot) => Float64, 1607;
2089 },
2090 "current_schema" => Scalar {
2091 params!() => UnmaterializableFunc::CurrentSchema => String, 1402;
2095 },
2096 "current_schemas" => Scalar {
2097 params!(Bool) => Operation::unary(|_ecx, e| {
2098 Ok(HirScalarExpr::if_then_else(
2099 e,
2100 HirScalarExpr::call_unmaterializable(
2101 UnmaterializableFunc::CurrentSchemasWithSystem,
2102 ),
2103 HirScalarExpr::call_unmaterializable(
2104 UnmaterializableFunc::CurrentSchemasWithoutSystem,
2105 ),
2106 ))
2107 }) => SqlScalarType::Array(Box::new(SqlScalarType::String)), 1403;
2111 },
2112 "current_database" => Scalar {
2113 params!() => UnmaterializableFunc::CurrentDatabase => String, 861;
2114 },
2115 "current_catalog" => Scalar {
2116 params!() => UnmaterializableFunc::CurrentDatabase => String, oid::FUNC_CURRENT_CATALOG;
2117 },
2118 "current_setting" => Scalar {
2119 params!(String) => Operation::unary(|_ecx, name| {
2120 current_settings(name, HirScalarExpr::literal_false())
2121 }) => SqlScalarType::String, 2077;
2122 params!(String, Bool) => Operation::binary(|_ecx, name, missing_ok| {
2123 current_settings(name, missing_ok)
2124 }) => SqlScalarType::String, 3294;
2125 },
2126 "current_timestamp" => Scalar {
2127 params!() => UnmaterializableFunc::CurrentTimestamp
2128 => TimestampTz, oid::FUNC_CURRENT_TIMESTAMP_OID;
2129 },
2130 "current_user" => Scalar {
2131 params!() => UnmaterializableFunc::CurrentUser => String, 745;
2132 },
2133 "current_role" => Scalar {
2134 params!() => UnmaterializableFunc::CurrentUser => String, oid::FUNC_CURRENT_ROLE;
2135 },
2136 "user" => Scalar {
2137 params!() => UnmaterializableFunc::CurrentUser => String, oid::FUNC_USER;
2138 },
2139 "session_user" => Scalar {
2140 params!() => UnmaterializableFunc::SessionUser => String, 746;
2141 },
2142 "chr" => Scalar {
2143 params!(Int32) => UnaryFunc::Chr(func::Chr) => String, 1621;
2144 },
2145 "date" => Scalar {
2146 params!(String) => UnaryFunc::CastStringToDate(func::CastStringToDate)
2147 => Date, oid::FUNC_DATE_FROM_TEXT;
2148 params!(Timestamp) => UnaryFunc::CastTimestampToDate(func::CastTimestampToDate)
2149 => Date, 2029;
2150 params!(TimestampTz) => UnaryFunc::CastTimestampTzToDate(func::CastTimestampTzToDate)
2151 => Date, 1178;
2152 },
2153 "date_bin" => Scalar {
2154 params!(Interval, Timestamp) => Operation::binary(|ecx, stride, source| {
2155 ecx.require_feature_flag(&vars::ENABLE_BINARY_DATE_BIN)?;
2156 Ok(stride.call_binary(source, func::DateBinTimestamp))
2157 }) => Timestamp, oid::FUNC_MZ_DATE_BIN_UNIX_EPOCH_TS_OID;
2158 params!(Interval, TimestampTz) => Operation::binary(|ecx, stride, source| {
2159 ecx.require_feature_flag(&vars::ENABLE_BINARY_DATE_BIN)?;
2160 Ok(stride.call_binary(source, func::DateBinTimestampTz))
2161 }) => TimestampTz, oid::FUNC_MZ_DATE_BIN_UNIX_EPOCH_TSTZ_OID;
2162 params!(Interval, Timestamp, Timestamp)
2163 => VariadicFunc::from(variadic::DateBinTimestamp) => Timestamp, 6177;
2164 params!(Interval, TimestampTz, TimestampTz)
2165 => VariadicFunc::from(variadic::DateBinTimestampTz) => TimestampTz, 6178;
2166 },
2167 "extract" => Scalar {
2168 params!(String, Interval)
2169 => BinaryFunc::from(func::DatePartIntervalNumeric) => Numeric, 6204;
2170 params!(String, Time)
2171 => BinaryFunc::from(func::DatePartTimeNumeric) => Numeric, 6200;
2172 params!(String, Timestamp)
2173 => BinaryFunc::from(func::DatePartTimestampTimestampNumeric)
2174 => Numeric, 6202;
2175 params!(String, TimestampTz)
2176 => BinaryFunc::from(func::DatePartTimestampTimestampTzNumeric)
2177 => Numeric, 6203;
2178 params!(String, Date) => BinaryFunc::from(func::ExtractDateUnits) => Numeric, 6199;
2179 },
2180 "date_part" => Scalar {
2181 params!(String, Interval)
2182 => BinaryFunc::from(func::DatePartIntervalF64) => Float64, 1172;
2183 params!(String, Time)
2184 => BinaryFunc::from(func::DatePartTimeF64) => Float64, 1385;
2185 params!(String, Timestamp)
2186 => BinaryFunc::from(func::DatePartTimestampTimestampF64)
2187 => Float64, 2021;
2188 params!(String, TimestampTz)
2189 => BinaryFunc::from(func::DatePartTimestampTimestampTzF64)
2190 => Float64, 1171;
2191 },
2192 "date_trunc" => Scalar {
2193 params!(String, Timestamp)
2194 => BinaryFunc::from(func::DateTruncUnitsTimestamp) => Timestamp, 2020;
2195 params!(String, TimestampTz)
2196 => BinaryFunc::from(func::DateTruncUnitsTimestampTz)
2197 => TimestampTz, 1217;
2198 params!(String, Interval)
2199 => BinaryFunc::from(func::DateTruncInterval) => Interval, 1218;
2200 },
2201 "daterange" => Scalar {
2202 params!(Date, Date) => Operation::variadic(|_ecx, mut exprs| {
2203 exprs.push(HirScalarExpr::literal(
2204 Datum::String("[)"), SqlScalarType::String,
2205 ));
2206 Ok(HirScalarExpr::call_variadic(
2207 variadic::RangeCreate { elem_type: SqlScalarType::Date },
2208 exprs,
2209 ))
2210 }) => SqlScalarType::Range {
2211 element_type: Box::new(SqlScalarType::Date),
2212 }, 3941;
2213 params!(Date, Date, String) => Operation::variadic(|_ecx, exprs| {
2214 Ok(HirScalarExpr::call_variadic(
2215 variadic::RangeCreate { elem_type: SqlScalarType::Date },
2216 exprs,
2217 ))
2218 }) => SqlScalarType::Range {
2219 element_type: Box::new(SqlScalarType::Date),
2220 }, 3942;
2221 },
2222 "degrees" => Scalar {
2223 params!(Float64) => UnaryFunc::Degrees(func::Degrees) => Float64, 1608;
2224 },
2225 "digest" => Scalar {
2226 params!(String, String) => BinaryFunc::from(func::DigestString)
2227 => Bytes, oid::FUNC_PG_DIGEST_STRING;
2228 params!(Bytes, String) => BinaryFunc::from(func::DigestBytes)
2229 => Bytes, oid::FUNC_PG_DIGEST_BYTES;
2230 },
2231 "exp" => Scalar {
2232 params!(Float64) => UnaryFunc::Exp(func::Exp) => Float64, 1347;
2233 params!(Numeric) => UnaryFunc::ExpNumeric(func::ExpNumeric) => Numeric, 1732;
2234 },
2235 "floor" => Scalar {
2236 params!(Float32) => UnaryFunc::FloorFloat32(func::FloorFloat32)
2237 => Float32, oid::FUNC_FLOOR_F32_OID;
2238 params!(Float64) => UnaryFunc::FloorFloat64(func::FloorFloat64) => Float64, 2309;
2239 params!(Numeric) => UnaryFunc::FloorNumeric(func::FloorNumeric) => Numeric, 1712;
2240 },
2241 "format_type" => Scalar {
2242 params!(Oid, Int32) => sql_impl_func(
2243 "CASE
2244 WHEN $1 IS NULL THEN NULL
2245 -- timestamp and timestamptz have the typmod in
2246 -- a nonstandard location that requires special
2247 -- handling.
2248 WHEN $1 = 1114 AND $2 >= 0 THEN 'timestamp(' || $2 || ') without time zone'
2249 WHEN $1 = 1184 AND $2 >= 0 THEN 'timestamp(' || $2 || ') with time zone'
2250 ELSE coalesce(
2251 (SELECT pg_catalog.concat(
2252 coalesce(mz_internal.mz_type_name($1), name),
2253 mz_internal.mz_render_typmod($1, $2))
2254 FROM mz_catalog.mz_types WHERE oid = $1),
2255 '???')
2256 END"
2257 ) => String, 1081;
2258 },
2259 "get_bit" => Scalar {
2260 params!(Bytes, Int32) => BinaryFunc::from(func::GetBit) => Int32, 723;
2261 },
2262 "get_byte" => Scalar {
2263 params!(Bytes, Int32) => BinaryFunc::from(func::GetByte) => Int32, 721;
2264 },
2265 "pg_get_ruledef" => Scalar {
2266 params!(Oid) => sql_impl_func("NULL::pg_catalog.text") => String, 1573;
2267 params!(Oid, Bool) => sql_impl_func("NULL::pg_catalog.text") => String, 2504;
2268 },
2269 "has_schema_privilege" => Scalar {
2270 params!(String, String, String) => sql_impl_func(
2271 "has_schema_privilege(\
2272 mz_internal.mz_role_oid($1), \
2273 mz_internal.mz_schema_oid($2), $3)",
2274 ) => Bool, 2268;
2275 params!(String, Oid, String) => sql_impl_func(
2276 "has_schema_privilege(\
2277 mz_internal.mz_role_oid($1), $2, $3)",
2278 ) => Bool, 2269;
2279 params!(Oid, String, String) => sql_impl_func(
2280 "has_schema_privilege(\
2281 $1, mz_internal.mz_schema_oid($2), $3)",
2282 ) => Bool, 2270;
2283 params!(Oid, Oid, String) => sql_impl_func(
2284 &privilege_fn!(
2285 "has_schema_privilege", "mz_schemas"
2286 ),
2287 ) => Bool, 2271;
2288 params!(String, String) => sql_impl_func(
2289 "has_schema_privilege(current_user, $1, $2)",
2290 ) => Bool, 2272;
2291 params!(Oid, String) => sql_impl_func(
2292 "has_schema_privilege(current_user, $1, $2)",
2293 ) => Bool, 2273;
2294 },
2295 "has_database_privilege" => Scalar {
2296 params!(String, String, String) => sql_impl_func(
2297 "has_database_privilege(\
2298 mz_internal.mz_role_oid($1), \
2299 mz_internal.mz_database_oid($2), $3)",
2300 ) => Bool, 2250;
2301 params!(String, Oid, String) => sql_impl_func(
2302 "has_database_privilege(\
2303 mz_internal.mz_role_oid($1), $2, $3)",
2304 ) => Bool, 2251;
2305 params!(Oid, String, String) => sql_impl_func(
2306 "has_database_privilege(\
2307 $1, mz_internal.mz_database_oid($2), $3)",
2308 ) => Bool, 2252;
2309 params!(Oid, Oid, String) => sql_impl_func(
2310 &privilege_fn!(
2311 "has_database_privilege", "mz_databases"
2312 ),
2313 ) => Bool, 2253;
2314 params!(String, String) => sql_impl_func(
2315 "has_database_privilege(current_user, $1, $2)",
2316 ) => Bool, 2254;
2317 params!(Oid, String) => sql_impl_func(
2318 "has_database_privilege(current_user, $1, $2)",
2319 ) => Bool, 2255;
2320 },
2321 "has_table_privilege" => Scalar {
2322 params!(String, String, String) => sql_impl_func(
2323 "has_table_privilege(\
2324 mz_internal.mz_role_oid($1), \
2325 $2::regclass::oid, $3)",
2326 ) => Bool, 1922;
2327 params!(String, Oid, String) => sql_impl_func(
2328 "has_table_privilege(\
2329 mz_internal.mz_role_oid($1), $2, $3)",
2330 ) => Bool, 1923;
2331 params!(Oid, String, String) => sql_impl_func(
2332 "has_table_privilege(\
2333 $1, $2::regclass::oid, $3)",
2334 ) => Bool, 1924;
2335 params!(Oid, Oid, String) => sql_impl_func(
2336 &privilege_fn!(
2337 "has_table_privilege", "mz_relations"
2338 ),
2339 ) => Bool, 1925;
2340 params!(String, String) => sql_impl_func(
2341 "has_table_privilege(current_user, $1, $2)",
2342 ) => Bool, 1926;
2343 params!(Oid, String) => sql_impl_func(
2344 "has_table_privilege(current_user, $1, $2)",
2345 ) => Bool, 1927;
2346 },
2347 "hmac" => Scalar {
2348 params!(String, String, String) => VariadicFunc::from(variadic::HmacString)
2349 => Bytes, oid::FUNC_PG_HMAC_STRING;
2350 params!(Bytes, Bytes, String) => VariadicFunc::from(variadic::HmacBytes)
2351 => Bytes, oid::FUNC_PG_HMAC_BYTES;
2352 },
2353 "initcap" => Scalar {
2354 params!(String) => UnaryFunc::Initcap(func::Initcap) => String, 872;
2355 },
2356 "int4range" => Scalar {
2357 params!(Int32, Int32) => Operation::variadic(|_ecx, mut exprs| {
2358 exprs.push(HirScalarExpr::literal(
2359 Datum::String("[)"), SqlScalarType::String,
2360 ));
2361 Ok(HirScalarExpr::call_variadic(
2362 variadic::RangeCreate { elem_type: SqlScalarType::Int32 },
2363 exprs,
2364 ))
2365 }) => SqlScalarType::Range {
2366 element_type: Box::new(SqlScalarType::Int32),
2367 }, 3840;
2368 params!(Int32, Int32, String) => Operation::variadic(|_ecx, exprs| {
2369 Ok(HirScalarExpr::call_variadic(
2370 variadic::RangeCreate { elem_type: SqlScalarType::Int32 },
2371 exprs,
2372 ))
2373 }) => SqlScalarType::Range {
2374 element_type: Box::new(SqlScalarType::Int32),
2375 }, 3841;
2376 },
2377 "int8range" => Scalar {
2378 params!(Int64, Int64) => Operation::variadic(|_ecx, mut exprs| {
2379 exprs.push(HirScalarExpr::literal(
2380 Datum::String("[)"), SqlScalarType::String,
2381 ));
2382 Ok(HirScalarExpr::call_variadic(
2383 variadic::RangeCreate { elem_type: SqlScalarType::Int64 },
2384 exprs,
2385 ))
2386 }) => SqlScalarType::Range {
2387 element_type: Box::new(SqlScalarType::Int64),
2388 }, 3945;
2389 params!(Int64, Int64, String) => Operation::variadic(|_ecx, exprs| {
2390 Ok(HirScalarExpr::call_variadic(
2391 variadic::RangeCreate { elem_type: SqlScalarType::Int64 },
2392 exprs,
2393 ))
2394 }) => SqlScalarType::Range {
2395 element_type: Box::new(SqlScalarType::Int64),
2396 }, 3946;
2397 },
2398 "isempty" => Scalar {
2399 params!(RangeAny) => UnaryFunc::RangeEmpty(func::RangeEmpty) => Bool, 3850;
2400 },
2401 "jsonb_array_length" => Scalar {
2402 params!(Jsonb) => UnaryFunc::JsonbArrayLength(func::JsonbArrayLength) => Int32, 3207;
2403 },
2404 "jsonb_build_array" => Scalar {
2405 params!() => VariadicFunc::from(variadic::JsonbBuildArray) => Jsonb, 3272;
2406 params!(Any...) => Operation::variadic(|ecx, exprs| {
2407 Ok(HirScalarExpr::call_variadic(
2408 variadic::JsonbBuildArray,
2409 exprs
2410 .into_iter()
2411 .map(|e| typeconv::to_jsonb(ecx, e))
2412 .collect::<Result<Vec<_>, _>>()?,
2413 ))
2414 }) => Jsonb, 3271;
2415 },
2416 "jsonb_build_object" => Scalar {
2417 params!() => VariadicFunc::from(variadic::JsonbBuildObject) => Jsonb, 3274;
2418 params!(Any...) => Operation::variadic(|ecx, exprs| {
2419 if exprs.len() % 2 != 0 {
2420 sql_bail!("argument list must have even number of elements")
2421 }
2422 let mut elems = Vec::with_capacity(exprs.len());
2423 for (key, val) in exprs.into_iter().tuples() {
2424 elems.push(typeconv::to_string(ecx, key)?);
2425 elems.push(typeconv::to_jsonb(ecx, val)?);
2426 }
2427 Ok(HirScalarExpr::call_variadic(variadic::JsonbBuildObject, elems))
2428 }) => Jsonb, 3273;
2429 },
2430 "jsonb_pretty" => Scalar {
2431 params!(Jsonb) => UnaryFunc::JsonbPretty(func::JsonbPretty) => String, 3306;
2432 },
2433 "jsonb_strip_nulls" => Scalar {
2434 params!(Jsonb) => UnaryFunc::JsonbStripNulls(func::JsonbStripNulls) => Jsonb, 3262;
2435 },
2436 "jsonb_typeof" => Scalar {
2437 params!(Jsonb) => UnaryFunc::JsonbTypeof(func::JsonbTypeof) => String, 3210;
2438 },
2439 "justify_days" => Scalar {
2440 params!(Interval) => UnaryFunc::JustifyDays(func::JustifyDays) => Interval, 1295;
2441 },
2442 "justify_hours" => Scalar {
2443 params!(Interval) => UnaryFunc::JustifyHours(func::JustifyHours) => Interval, 1175;
2444 },
2445 "justify_interval" => Scalar {
2446 params!(Interval) => UnaryFunc::JustifyInterval(func::JustifyInterval)
2447 => Interval, 2711;
2448 },
2449 "left" => Scalar {
2450 params!(String, Int32) => BinaryFunc::from(func::Left) => String, 3060;
2451 },
2452 "length" => Scalar {
2453 params!(Bytes) => UnaryFunc::ByteLengthBytes(func::ByteLengthBytes) => Int32, 2010;
2454 params!(String) => UnaryFunc::CharLength(func::CharLength) => Int32, 1317;
2456 params!(Bytes, String) => BinaryFunc::from(func::EncodedBytesCharLength) => Int32, 1713;
2457 },
2458 "like_escape" => Scalar {
2459 params!(String, String) => BinaryFunc::from(func::LikeEscape) => String, 1637;
2460 },
2461 "ln" => Scalar {
2462 params!(Float64) => UnaryFunc::Ln(func::Ln) => Float64, 1341;
2463 params!(Numeric) => UnaryFunc::LnNumeric(func::LnNumeric) => Numeric, 1734;
2464 },
2465 "log10" => Scalar {
2466 params!(Float64) => UnaryFunc::Log10(func::Log10) => Float64, 1194;
2467 params!(Numeric) => UnaryFunc::Log10Numeric(func::Log10Numeric) => Numeric, 1481;
2468 },
2469 "log" => Scalar {
2470 params!(Float64) => UnaryFunc::Log10(func::Log10) => Float64, 1340;
2471 params!(Numeric) => UnaryFunc::Log10Numeric(func::Log10Numeric) => Numeric, 1741;
2472 params!(Numeric, Numeric) => BinaryFunc::from(func::LogBaseNumeric) => Numeric, 1736;
2473 },
2474 "lower" => Scalar {
2475 params!(String) => UnaryFunc::Lower(func::Lower) => String, 870;
2476 params!(RangeAny) => UnaryFunc::RangeLower(func::RangeLower) => AnyElement, 3848;
2477 },
2478 "lower_inc" => Scalar {
2479 params!(RangeAny) => UnaryFunc::RangeLowerInc(func::RangeLowerInc) => Bool, 3851;
2480 },
2481 "lower_inf" => Scalar {
2482 params!(RangeAny) => UnaryFunc::RangeLowerInf(func::RangeLowerInf) => Bool, 3853;
2483 },
2484 "lpad" => Scalar {
2485 params!(String, Int32) => VariadicFunc::from(variadic::PadLeading) => String, 879;
2486 params!(String, Int32, String) => VariadicFunc::from(variadic::PadLeading)
2487 => String, 873;
2488 },
2489 "ltrim" => Scalar {
2490 params!(String) => UnaryFunc::TrimLeadingWhitespace(
2491 func::TrimLeadingWhitespace,
2492 ) => String, 881;
2493 params!(String, String) => BinaryFunc::from(func::TrimLeading) => String, 875;
2494 },
2495 "makeaclitem" => Scalar {
2496 params!(Oid, Oid, String, Bool)
2497 => VariadicFunc::from(variadic::MakeAclItem) => AclItem, 1365;
2498 },
2499 "make_timestamp" => Scalar {
2500 params!(Int64, Int64, Int64, Int64, Int64, Float64)
2501 => VariadicFunc::from(variadic::MakeTimestamp) => Timestamp, 3461;
2502 },
2503 "md5" => Scalar {
2504 params!(String) => Operation::unary(move |_ecx, input| {
2505 let algorithm = HirScalarExpr::literal(Datum::String("md5"), SqlScalarType::String);
2506 let encoding = HirScalarExpr::literal(Datum::String("hex"), SqlScalarType::String);
2507 Ok(input
2508 .call_binary(algorithm, func::DigestString)
2509 .call_binary(encoding, func::Encode))
2510 }) => String, 2311;
2511 params!(Bytes) => Operation::unary(move |_ecx, input| {
2512 let algorithm = HirScalarExpr::literal(
2513 Datum::String("md5"), SqlScalarType::String,
2514 );
2515 let encoding = HirScalarExpr::literal(
2516 Datum::String("hex"), SqlScalarType::String,
2517 );
2518 Ok(input
2519 .call_binary(algorithm, func::DigestBytes)
2520 .call_binary(encoding, func::Encode))
2521 }) => String, 2321;
2522 },
2523 "mod" => Scalar {
2524 params!(Numeric, Numeric) =>
2525 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2526 => Numeric, 1728;
2527 params!(Int16, Int16) =>
2528 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2529 => Int16, 940;
2530 params!(Int32, Int32) =>
2531 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2532 => Int32, 941;
2533 params!(Int64, Int64) =>
2534 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2535 => Int64, 947;
2536 params!(UInt16, UInt16) =>
2537 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2538 => UInt16, oid::FUNC_MOD_UINT16_OID;
2539 params!(UInt32, UInt32) =>
2540 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2541 => UInt32, oid::FUNC_MOD_UINT32_OID;
2542 params!(UInt64, UInt64) =>
2543 Operation::nullary(|_ecx| catalog_name_only!("mod"))
2544 => UInt64, oid::FUNC_MOD_UINT64_OID;
2545 },
2546 "normalize" => Scalar {
2547 params!(String, String) => BinaryFunc::Normalize(func::Normalize)
2549 => String, oid::FUNC_NORMALIZE_OID;
2550 },
2551 "now" => Scalar {
2552 params!() => UnmaterializableFunc::CurrentTimestamp => TimestampTz, 1299;
2553 },
2554 "numrange" => Scalar {
2555 params!(Numeric, Numeric) => Operation::variadic(|_ecx, mut exprs| {
2556 exprs.push(HirScalarExpr::literal(
2557 Datum::String("[)"), SqlScalarType::String,
2558 ));
2559 Ok(HirScalarExpr::call_variadic(
2560 variadic::RangeCreate {
2561 elem_type: SqlScalarType::Numeric { max_scale: None },
2562 },
2563 exprs,
2564 ))
2565 }) => SqlScalarType::Range {
2566 element_type: Box::new(SqlScalarType::Numeric { max_scale: None }),
2567 }, 3844;
2568 params!(Numeric, Numeric, String) => Operation::variadic(|_ecx, exprs| {
2569 Ok(HirScalarExpr::call_variadic(
2570 variadic::RangeCreate {
2571 elem_type: SqlScalarType::Numeric { max_scale: None },
2572 },
2573 exprs,
2574 ))
2575 }) => SqlScalarType::Range {
2576 element_type: Box::new(SqlScalarType::Numeric { max_scale: None }),
2577 }, 3845;
2578 },
2579 "octet_length" => Scalar {
2580 params!(Bytes) => UnaryFunc::ByteLengthBytes(func::ByteLengthBytes) => Int32, 720;
2581 params!(String) => UnaryFunc::ByteLengthString(func::ByteLengthString) => Int32, 1374;
2582 params!(Char) => Operation::unary(|ecx, e| {
2583 let length = ecx.scalar_type(&e).unwrap_char_length();
2584 Ok(e.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
2585 .call_unary(UnaryFunc::ByteLengthString(func::ByteLengthString))
2586 )
2587 }) => Int32, 1375;
2588 },
2589 "obj_description" => Scalar {
2593 params!(Oid, String) => sql_impl_func(&format!(
2594 "(SELECT description FROM pg_description
2595 WHERE objoid = $1
2596 AND classoid = (
2597 SELECT oid FROM pg_class WHERE relname = $2 AND relnamespace = {})
2598 AND objsubid = 0)",
2599 oid::SCHEMA_PG_CATALOG_OID
2600 )) => String, 1215;
2601 },
2602 "pg_column_size" => Scalar {
2603 params!(Any) => UnaryFunc::PgColumnSize(func::PgColumnSize) => Int32, 1269;
2604 },
2605 "pg_size_pretty" => Scalar {
2606 params!(Numeric) => UnaryFunc::PgSizePretty(func::PgSizePretty) => String, 3166;
2607 },
2608 "mz_row_size" => Scalar {
2609 params!(Any) => Operation::unary(|ecx, e| {
2610 let s = ecx.scalar_type(&e);
2611 if !matches!(s, SqlScalarType::Record{..}) {
2612 sql_bail!("mz_row_size requires a record type");
2613 }
2614 Ok(e.call_unary(UnaryFunc::MzRowSize(func::MzRowSize)))
2615 }) => Int32, oid::FUNC_MZ_ROW_SIZE;
2616 },
2617 "parse_ident" => Scalar {
2618 params!(String) => Operation::unary(|_ecx, ident| {
2619 Ok(ident.call_binary(HirScalarExpr::literal_true(), func::ParseIdent))
2620 }) => SqlScalarType::Array(Box::new(SqlScalarType::String)),
2621 oid::FUNC_PARSE_IDENT_DEFAULT_STRICT;
2622 params!(String, Bool) => BinaryFunc::from(func::ParseIdent)
2623 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 1268;
2624 },
2625 "pg_encoding_to_char" => Scalar {
2626 params!(Int64) => sql_impl_func(
2629 "CASE WHEN $1 = 6 THEN 'UTF8' ELSE NULL END",
2630 ) => String, 1597;
2631 },
2632 "pg_backend_pid" => Scalar {
2633 params!() => UnmaterializableFunc::PgBackendPid => Int32, 2026;
2634 },
2635 "pg_get_constraintdef" => Scalar {
2641 params!(Oid) => Operation::unary(|_ecx, _oid|
2642 Ok(HirScalarExpr::literal_null(SqlScalarType::String))) => String, 1387;
2643 params!(Oid, Bool) => Operation::binary(|_ecx, _oid, _pretty|
2644 Ok(HirScalarExpr::literal_null(SqlScalarType::String))) => String, 2508;
2645 },
2646 "pg_get_indexdef" => Scalar {
2651 params!(Oid) => sql_impl_func(
2652 "(SELECT 'CREATE INDEX ' || i.name
2653 || ' ON ' || r.name
2654 || ' USING arrangement (' || (
2655 SELECT pg_catalog.string_agg(
2656 cols.col_exp, ',' ORDER BY cols.index_position)
2657 FROM (
2658 SELECT c.name AS col_exp, ic.index_position
2659 FROM mz_catalog.mz_index_columns AS ic
2660 JOIN mz_catalog.mz_indexes AS i2
2661 ON ic.index_id = i2.id
2662 JOIN mz_catalog.mz_columns AS c
2663 ON i2.on_id = c.id
2664 AND ic.on_position = c.position
2665 WHERE ic.index_id = i.id
2666 AND ic.on_expression IS NULL
2667 UNION
2668 SELECT ic.on_expression AS col_exp,
2669 ic.index_position
2670 FROM mz_catalog.mz_index_columns AS ic
2671 WHERE ic.index_id = i.id
2672 AND ic.on_expression IS NOT NULL
2673 ) AS cols
2674 ) || ')'
2675 FROM mz_catalog.mz_indexes AS i
2676 JOIN mz_catalog.mz_relations AS r
2677 ON i.on_id = r.id
2678 WHERE i.oid = $1)"
2679 ) => String, 1643;
2680 params!(Oid, Int32, Bool) => sql_impl_func(
2683 "(SELECT CASE
2684 WHEN $2 = 0
2685 THEN pg_catalog.pg_get_indexdef($1)
2686 ELSE (
2687 SELECT c.name
2688 FROM mz_catalog.mz_indexes AS i
2689 JOIN mz_catalog.mz_index_columns AS ic
2690 ON i.id = ic.index_id
2691 JOIN mz_catalog.mz_columns AS c
2692 ON i.on_id = c.id
2693 AND ic.on_position = c.position
2694 WHERE i.oid = $1
2695 AND ic.on_expression IS NULL
2696 AND ic.index_position = $2
2697 UNION
2698 SELECT ic.on_expression
2699 FROM mz_catalog.mz_indexes AS i
2700 JOIN mz_catalog.mz_index_columns AS ic
2701 ON i.id = ic.index_id
2702 WHERE i.oid = $1
2703 AND ic.on_expression IS NOT NULL
2704 AND ic.index_position = $2)
2705 END)"
2706 ) => String, 2507;
2707 },
2708 "pg_get_viewdef" => Scalar {
2711 params!(String) => sql_impl_func(
2712 "(SELECT definition FROM mz_catalog.mz_views WHERE name = $1)"
2713 ) => String, 1640;
2714 params!(Oid) => sql_impl_func(
2715 "(SELECT definition FROM mz_catalog.mz_views WHERE oid = $1)"
2716 ) => String, 1641;
2717 params!(String, Bool) => sql_impl_func(
2718 "(SELECT definition FROM mz_catalog.mz_views WHERE name = $1)"
2719 ) => String, 2505;
2720 params!(Oid, Bool) => sql_impl_func(
2721 "(SELECT definition FROM mz_catalog.mz_views WHERE oid = $1)"
2722 ) => String, 2506;
2723 params!(Oid, Int32) => sql_impl_func(
2724 "(SELECT definition FROM mz_catalog.mz_views WHERE oid = $1)"
2725 ) => String, 3159;
2726 },
2727 "pg_get_expr" => Scalar {
2735 params!(String, Oid) => Operation::binary(|_ecx, l, _r| Ok(l)) => String, 1716;
2736 params!(String, Oid, Bool) => Operation::variadic(
2737 move |_ecx, mut args| Ok(args.remove(0)),
2738 ) => String, 2509;
2739 },
2740 "pg_get_userbyid" => Scalar {
2741 params!(Oid) => sql_impl_func(
2742 "CASE \
2743 WHEN $1 IS NULL THEN NULL \
2744 ELSE COALESCE(\
2745 (SELECT name FROM mz_catalog.mz_roles WHERE oid = $1),\
2746 'unknown (OID=' || $1 || ')'\
2747 ) \
2748 END"
2749 ) => String, 1642;
2750 },
2751 "pg_has_role" => Scalar {
2758 params!(String, String, String) => sql_impl_func(
2759 "pg_has_role(\
2760 mz_internal.mz_role_oid($1), \
2761 mz_internal.mz_role_oid($2), $3)",
2762 ) => Bool, 2705;
2763 params!(String, Oid, String) => sql_impl_func(
2764 "pg_has_role(\
2765 mz_internal.mz_role_oid($1), $2, $3)",
2766 ) => Bool, 2706;
2767 params!(Oid, String, String) => sql_impl_func(
2768 "pg_has_role(\
2769 $1, mz_internal.mz_role_oid($2), $3)",
2770 ) => Bool, 2707;
2771 params!(Oid, Oid, String) => sql_impl_func(
2772 "CASE
2773 -- We need to validate the privilege to return a proper error before anything
2774 -- else.
2775 WHEN NOT mz_internal.mz_validate_role_privilege($3)
2776 OR $1 IS NULL
2777 OR $2 IS NULL
2778 OR $3 IS NULL
2779 THEN NULL
2780 WHEN $1 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
2781 OR $2 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
2782 THEN false
2783 ELSE $2::text IN (SELECT UNNEST(mz_internal.mz_role_oid_memberships() -> $1::text))
2784 END",
2785 ) => Bool, 2708;
2786 params!(String, String) => sql_impl_func(
2787 "pg_has_role(current_user, $1, $2)",
2788 ) => Bool, 2709;
2789 params!(Oid, String) => sql_impl_func(
2790 "pg_has_role(current_user, $1, $2)",
2791 ) => Bool, 2710;
2792 },
2793 "pg_is_in_recovery" => Scalar {
2796 params!() => Operation::nullary(|_ecx| {
2797 Ok(HirScalarExpr::literal_false())
2798 }) => Bool, 3810;
2799 },
2800 "pg_postmaster_start_time" => Scalar {
2801 params!() => UnmaterializableFunc::PgPostmasterStartTime => TimestampTz, 2560;
2802 },
2803 "pg_relation_size" => Scalar {
2804 params!(RegClass, String) => sql_impl_func(
2805 "CASE WHEN $1 IS NULL OR $2 IS NULL \
2806 THEN NULL ELSE -1::pg_catalog.int8 END",
2807 ) => Int64, 2332;
2808 params!(RegClass) => sql_impl_func(
2809 "CASE WHEN $1 IS NULL \
2810 THEN NULL ELSE -1::pg_catalog.int8 END",
2811 ) => Int64, 2325;
2812 },
2813 "pg_stat_get_numscans" => Scalar {
2814 params!(Oid) => sql_impl_func(
2815 "CASE WHEN $1 IS NULL \
2816 THEN NULL ELSE -1::pg_catalog.int8 END",
2817 ) => Int64, 1928;
2818 },
2819 "pg_table_is_visible" => Scalar {
2820 params!(Oid) => sql_impl_func(
2821 "(SELECT s.name = ANY(pg_catalog.current_schemas(true))
2822 FROM mz_catalog.mz_objects o JOIN mz_catalog.mz_schemas s ON o.schema_id = s.id
2823 WHERE o.oid = $1)"
2824 ) => Bool, 2079;
2825 },
2826 "pg_type_is_visible" => Scalar {
2827 params!(Oid) => sql_impl_func(
2828 "(SELECT s.name = ANY(pg_catalog.current_schemas(true))
2829 FROM mz_catalog.mz_types t JOIN mz_catalog.mz_schemas s ON t.schema_id = s.id
2830 WHERE t.oid = $1)"
2831 ) => Bool, 2080;
2832 },
2833 "pg_function_is_visible" => Scalar {
2834 params!(Oid) => sql_impl_func(
2835 "(SELECT s.name = ANY(pg_catalog.current_schemas(true))
2836 FROM mz_catalog.mz_functions f
2837 JOIN mz_catalog.mz_schemas s
2838 ON f.schema_id = s.id
2839 WHERE f.oid = $1)"
2840 ) => Bool, 2081;
2841 },
2842 "pg_tablespace_location" => Scalar {
2846 params!(Oid) => Operation::unary(|_ecx, _e| {
2847 Ok(HirScalarExpr::literal_null(SqlScalarType::String))
2848 }) => String, 3778;
2849 },
2850 "pg_typeof" => Scalar {
2851 params!(Any) => Operation::new(|ecx, exprs, params, _order_by| {
2852 let name = match ecx.scalar_type(&exprs[0]) {
2854 CoercibleScalarType::Uncoerced => "unknown".to_string(),
2855 CoercibleScalarType::Record(_) => "record".to_string(),
2856 CoercibleScalarType::Coerced(ty) => ecx.humanize_sql_scalar_type(&ty, true),
2857 };
2858
2859 coerce_args_to_types(ecx, exprs, params)?;
2863
2864 Ok(HirScalarExpr::literal(Datum::String(&name), SqlScalarType::String))
2869 }) => String, 1619;
2870 },
2871 "position" => Scalar {
2872 params!(String, String) => BinaryFunc::from(func::Position) => Int32, 849;
2873 },
2874 "pow" => Scalar {
2875 params!(Float64, Float64) =>
2876 Operation::nullary(|_ecx| catalog_name_only!("pow"))
2877 => Float64, 1346;
2878 },
2879 "power" => Scalar {
2880 params!(Float64, Float64) => BinaryFunc::from(func::Power) => Float64, 1368;
2881 params!(Numeric, Numeric) => BinaryFunc::from(func::PowerNumeric) => Numeric, 2169;
2882 },
2883 "quote_ident" => Scalar {
2884 params!(String) => UnaryFunc::QuoteIdent(func::QuoteIdent) => String, 1282;
2885 },
2886 "radians" => Scalar {
2887 params!(Float64) => UnaryFunc::Radians(func::Radians) => Float64, 1609;
2888 },
2889 "repeat" => Scalar {
2890 params!(String, Int32) => BinaryFunc::RepeatString(func::RepeatString) => String, 1622;
2891 },
2892 "regexp_match" => Scalar {
2893 params!(String, String) => VariadicFunc::from(variadic::RegexpMatch)
2894 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 3396;
2895 params!(String, String, String) => VariadicFunc::from(variadic::RegexpMatch)
2896 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 3397;
2897 },
2898 "replace" => Scalar {
2899 params!(String, String, String) => VariadicFunc::from(variadic::Replace)
2900 => String, 2087;
2901 },
2902 "right" => Scalar {
2903 params!(String, Int32) => BinaryFunc::from(func::Right) => String, 3061;
2904 },
2905 "round" => Scalar {
2906 params!(Float32) => UnaryFunc::RoundFloat32(func::RoundFloat32)
2907 => Float32, oid::FUNC_ROUND_F32_OID;
2908 params!(Float64) => UnaryFunc::RoundFloat64(func::RoundFloat64) => Float64, 1342;
2909 params!(Numeric) => UnaryFunc::RoundNumeric(func::RoundNumeric) => Numeric, 1708;
2910 params!(Numeric, Int32) => BinaryFunc::from(func::RoundNumericBinary) => Numeric, 1707;
2911 },
2912 "rtrim" => Scalar {
2913 params!(String) => UnaryFunc::TrimTrailingWhitespace(
2914 func::TrimTrailingWhitespace,
2915 ) => String, 882;
2916 params!(String, String) => BinaryFunc::from(func::TrimTrailing) => String, 876;
2917 },
2918 "sha224" => Scalar {
2919 params!(Bytes) => digest("sha224") => Bytes, 3419;
2920 },
2921 "sha256" => Scalar {
2922 params!(Bytes) => digest("sha256") => Bytes, 3420;
2923 },
2924 "sha384" => Scalar {
2925 params!(Bytes) => digest("sha384") => Bytes, 3421;
2926 },
2927 "sha512" => Scalar {
2928 params!(Bytes) => digest("sha512") => Bytes, 3422;
2929 },
2930 "sin" => Scalar {
2931 params!(Float64) => UnaryFunc::Sin(func::Sin) => Float64, 1604;
2932 },
2933 "asin" => Scalar {
2934 params!(Float64) => UnaryFunc::Asin(func::Asin) => Float64, 1600;
2935 },
2936 "sinh" => Scalar {
2937 params!(Float64) => UnaryFunc::Sinh(func::Sinh) => Float64, 2462;
2938 },
2939 "asinh" => Scalar {
2940 params!(Float64) => UnaryFunc::Asinh(func::Asinh) => Float64, 2465;
2941 },
2942 "strpos" => Scalar {
2943 params!(String, String) => BinaryFunc::from(func::Strpos) => Int32, 868;
2944 },
2945 "split_part" => Scalar {
2946 params!(String, String, Int32) => VariadicFunc::from(variadic::SplitPart)
2947 => String, 2088;
2948 },
2949 "stddev" => Scalar {
2950 params!(Float32) =>
2951 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2952 => Float64, 2157;
2953 params!(Float64) =>
2954 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2955 => Float64, 2158;
2956 params!(Int16) =>
2957 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2958 => Numeric, 2156;
2959 params!(Int32) =>
2960 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2961 => Numeric, 2155;
2962 params!(Int64) =>
2963 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2964 => Numeric, 2154;
2965 params!(UInt16) =>
2966 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2967 => Numeric, oid::FUNC_STDDEV_UINT16_OID;
2968 params!(UInt32) =>
2969 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2970 => Numeric, oid::FUNC_STDDEV_UINT32_OID;
2971 params!(UInt64) =>
2972 Operation::nullary(|_ecx| catalog_name_only!("stddev"))
2973 => Numeric, oid::FUNC_STDDEV_UINT64_OID;
2974 },
2975 "stddev_pop" => Scalar {
2976 params!(Float32) =>
2977 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2978 => Float64, 2727;
2979 params!(Float64) =>
2980 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2981 => Float64, 2728;
2982 params!(Int16) =>
2983 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2984 => Numeric, 2726;
2985 params!(Int32) =>
2986 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2987 => Numeric, 2725;
2988 params!(Int64) =>
2989 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2990 => Numeric, 2724;
2991 params!(UInt16) =>
2992 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2993 => Numeric, oid::FUNC_STDDEV_POP_UINT16_OID;
2994 params!(UInt32) =>
2995 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2996 => Numeric, oid::FUNC_STDDEV_POP_UINT32_OID;
2997 params!(UInt64) =>
2998 Operation::nullary(|_ecx| catalog_name_only!("stddev_pop"))
2999 => Numeric, oid::FUNC_STDDEV_POP_UINT64_OID;
3000 },
3001 "stddev_samp" => Scalar {
3002 params!(Float32) =>
3003 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
3004 => Float64, 2715;
3005 params!(Float64) =>
3006 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
3007 => Float64, 2716;
3008 params!(Int16) =>
3009 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
3010 => Numeric, 2714;
3011 params!(Int32) =>
3012 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
3013 => Numeric, 2713;
3014 params!(Int64) =>
3015 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
3016 => Numeric, 2712;
3017 params!(UInt16) =>
3018 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
3019 => Numeric, oid::FUNC_STDDEV_SAMP_UINT16_OID;
3020 params!(UInt32) =>
3021 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
3022 => Numeric, oid::FUNC_STDDEV_SAMP_UINT32_OID;
3023 params!(UInt64) =>
3024 Operation::nullary(|_ecx| catalog_name_only!("stddev_samp"))
3025 => Numeric, oid::FUNC_STDDEV_SAMP_UINT64_OID;
3026 },
3027 "substr" => Scalar {
3028 params!(String, Int32) => VariadicFunc::from(variadic::Substr) => String, 883;
3029 params!(String, Int32, Int32) => VariadicFunc::from(variadic::Substr) => String, 877;
3030 },
3031 "substring" => Scalar {
3032 params!(String, Int32) => VariadicFunc::from(variadic::Substr) => String, 937;
3033 params!(String, Int32, Int32) => VariadicFunc::from(variadic::Substr) => String, 936;
3034 },
3035 "sqrt" => Scalar {
3036 params!(Float64) => UnaryFunc::SqrtFloat64(func::SqrtFloat64) => Float64, 1344;
3037 params!(Numeric) => UnaryFunc::SqrtNumeric(func::SqrtNumeric) => Numeric, 1730;
3038 },
3039 "tan" => Scalar {
3040 params!(Float64) => UnaryFunc::Tan(func::Tan) => Float64, 1606;
3041 },
3042 "atan" => Scalar {
3043 params!(Float64) => UnaryFunc::Atan(func::Atan) => Float64, 1602;
3044 },
3045 "tanh" => Scalar {
3046 params!(Float64) => UnaryFunc::Tanh(func::Tanh) => Float64, 2464;
3047 },
3048 "atanh" => Scalar {
3049 params!(Float64) => UnaryFunc::Atanh(func::Atanh) => Float64, 2467;
3050 },
3051 "age" => Scalar {
3052 params!(Timestamp, Timestamp) => BinaryFunc::from(func::AgeTimestamp) => Interval, 2058;
3053 params!(TimestampTz, TimestampTz)
3054 => BinaryFunc::from(func::AgeTimestampTz) => Interval, 1199;
3055 },
3056 "timezone" => Scalar {
3057 params!(String, Timestamp)
3058 => BinaryFunc::TimezoneTimestampBinary(
3059 func::TimezoneTimestampBinary,
3060 ) => TimestampTz, 2069;
3061 params!(String, TimestampTz)
3062 => BinaryFunc::TimezoneTimestampTzBinary(
3063 func::TimezoneTimestampTzBinary,
3064 ) => Timestamp, 1159;
3065 params!(String, Time) => Operation::binary(|ecx, lhs, rhs| {
3067 ecx.require_feature_flag(&ENABLE_TIME_AT_TIME_ZONE)?;
3081 Ok(HirScalarExpr::call_variadic(
3082 variadic::TimezoneTimeVariadic,
3083 vec![
3084 lhs,
3085 rhs,
3086 HirScalarExpr::call_unmaterializable(
3087 UnmaterializableFunc::CurrentTimestamp,
3088 ),
3089 ],
3090 ))
3091 }) => Time, 2037;
3092 params!(Interval, Timestamp)
3093 => BinaryFunc::from(func::TimezoneIntervalTimestampBinary)
3094 => TimestampTz, 2070;
3095 params!(Interval, TimestampTz)
3096 => BinaryFunc::from(func::TimezoneIntervalTimestampTzBinary)
3097 => Timestamp, 1026;
3098 params!(Interval, Time)
3100 => BinaryFunc::from(func::TimezoneIntervalTimeBinary) => Time, 2038;
3101 },
3102 "to_char" => Scalar {
3103 params!(Timestamp, String)
3104 => BinaryFunc::from(func::ToCharTimestampFormat) => String, 2049;
3105 params!(TimestampTz, String)
3106 => BinaryFunc::from(func::ToCharTimestampTzFormat) => String, 1770;
3107 },
3108 "to_jsonb" => Scalar {
3119 params!(Any) => Operation::unary(|ecx, e| {
3120 let e = match ecx.scalar_type(&e) {
3122 SqlScalarType::Char { length } => {
3123 e.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
3124 }
3125 _ => e,
3126 };
3127 typeconv::to_jsonb(ecx, e)
3128 }) => Jsonb, 3787;
3129 },
3130 "to_timestamp" => Scalar {
3131 params!(Float64) => UnaryFunc::ToTimestamp(func::ToTimestamp) => TimestampTz, 1158;
3132 },
3133 "translate" => Scalar {
3134 params!(String, String, String) => VariadicFunc::from(variadic::Translate)
3135 => String, 878;
3136 },
3137 "trunc" => Scalar {
3138 params!(Float32) => UnaryFunc::TruncFloat32(func::TruncFloat32)
3139 => Float32, oid::FUNC_TRUNC_F32_OID;
3140 params!(Float64) => UnaryFunc::TruncFloat64(func::TruncFloat64) => Float64, 1343;
3141 params!(Numeric) => UnaryFunc::TruncNumeric(func::TruncNumeric) => Numeric, 1710;
3142 },
3143 "tsrange" => Scalar {
3144 params!(Timestamp, Timestamp) => Operation::variadic(|_ecx, mut exprs| {
3145 exprs.push(HirScalarExpr::literal(
3146 Datum::String("[)"), SqlScalarType::String,
3147 ));
3148 Ok(HirScalarExpr::call_variadic(
3149 variadic::RangeCreate {
3150 elem_type: SqlScalarType::Timestamp { precision: None },
3151 },
3152 exprs,
3153 ))
3154 }) => SqlScalarType::Range {
3155 element_type: Box::new(SqlScalarType::Timestamp { precision: None }),
3156 }, 3933;
3157 params!(Timestamp, Timestamp, String) => Operation::variadic(|_ecx, exprs| {
3158 Ok(HirScalarExpr::call_variadic(
3159 variadic::RangeCreate {
3160 elem_type: SqlScalarType::Timestamp { precision: None },
3161 },
3162 exprs,
3163 ))
3164 }) => SqlScalarType::Range {
3165 element_type: Box::new(SqlScalarType::Timestamp { precision: None }),
3166 }, 3934;
3167 },
3168 "tstzrange" => Scalar {
3169 params!(TimestampTz, TimestampTz) => Operation::variadic(|_ecx, mut exprs| {
3170 exprs.push(HirScalarExpr::literal(
3171 Datum::String("[)"), SqlScalarType::String,
3172 ));
3173 Ok(HirScalarExpr::call_variadic(
3174 variadic::RangeCreate {
3175 elem_type: SqlScalarType::TimestampTz { precision: None },
3176 },
3177 exprs,
3178 ))
3179 }) => SqlScalarType::Range {
3180 element_type: Box::new(SqlScalarType::TimestampTz { precision: None }),
3181 }, 3937;
3182 params!(TimestampTz, TimestampTz, String) => Operation::variadic(|_ecx, exprs| {
3183 Ok(HirScalarExpr::call_variadic(
3184 variadic::RangeCreate {
3185 elem_type: SqlScalarType::TimestampTz { precision: None },
3186 },
3187 exprs,
3188 ))
3189 }) => SqlScalarType::Range {
3190 element_type: Box::new(SqlScalarType::TimestampTz { precision: None }),
3191 }, 3938;
3192 },
3193 "upper" => Scalar {
3194 params!(String) => UnaryFunc::Upper(func::Upper) => String, 871;
3195 params!(RangeAny) => UnaryFunc::RangeUpper(func::RangeUpper) => AnyElement, 3849;
3196 },
3197 "upper_inc" => Scalar {
3198 params!(RangeAny) => UnaryFunc::RangeUpperInc(func::RangeUpperInc) => Bool, 3852;
3199 },
3200 "upper_inf" => Scalar {
3201 params!(RangeAny) => UnaryFunc::RangeUpperInf(func::RangeUpperInf) => Bool, 3854;
3202 },
3203 "uuid_generate_v5" => Scalar {
3204 params!(Uuid, String) => BinaryFunc::from(func::UuidGenerateV5)
3205 => Uuid, oid::FUNC_PG_UUID_GENERATE_V5;
3206 },
3207 "variance" => Scalar {
3208 params!(Float32) =>
3209 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3210 => Float64, 2151;
3211 params!(Float64) =>
3212 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3213 => Float64, 2152;
3214 params!(Int16) =>
3215 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3216 => Numeric, 2150;
3217 params!(Int32) =>
3218 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3219 => Numeric, 2149;
3220 params!(Int64) =>
3221 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3222 => Numeric, 2148;
3223 params!(UInt16) =>
3224 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3225 => Numeric, oid::FUNC_VARIANCE_UINT16_OID;
3226 params!(UInt32) =>
3227 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3228 => Numeric, oid::FUNC_VARIANCE_UINT32_OID;
3229 params!(UInt64) =>
3230 Operation::nullary(|_ecx| catalog_name_only!("variance"))
3231 => Numeric, oid::FUNC_VARIANCE_UINT64_OID;
3232 },
3233 "var_pop" => Scalar {
3234 params!(Float32) =>
3235 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3236 => Float64, 2721;
3237 params!(Float64) =>
3238 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3239 => Float64, 2722;
3240 params!(Int16) =>
3241 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3242 => Numeric, 2720;
3243 params!(Int32) =>
3244 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3245 => Numeric, 2719;
3246 params!(Int64) =>
3247 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3248 => Numeric, 2718;
3249 params!(UInt16) =>
3250 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3251 => Numeric, oid::FUNC_VAR_POP_UINT16_OID;
3252 params!(UInt32) =>
3253 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3254 => Numeric, oid::FUNC_VAR_POP_UINT32_OID;
3255 params!(UInt64) =>
3256 Operation::nullary(|_ecx| catalog_name_only!("var_pop"))
3257 => Numeric, oid::FUNC_VAR_POP_UINT64_OID;
3258 },
3259 "var_samp" => Scalar {
3260 params!(Float32) =>
3261 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3262 => Float64, 2644;
3263 params!(Float64) =>
3264 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3265 => Float64, 2645;
3266 params!(Int16) =>
3267 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3268 => Numeric, 2643;
3269 params!(Int32) =>
3270 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3271 => Numeric, 2642;
3272 params!(Int64) =>
3273 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3274 => Numeric, 2641;
3275 params!(UInt16) =>
3276 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3277 => Numeric, oid::FUNC_VAR_SAMP_UINT16_OID;
3278 params!(UInt32) =>
3279 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3280 => Numeric, oid::FUNC_VAR_SAMP_UINT32_OID;
3281 params!(UInt64) =>
3282 Operation::nullary(|_ecx| catalog_name_only!("var_samp"))
3283 => Numeric, oid::FUNC_VAR_SAMP_UINT64_OID;
3284 },
3285 "version" => Scalar {
3286 params!() => UnmaterializableFunc::Version => String, 89;
3287 },
3288
3289 "aclitemin" => Scalar {
3291 params!(String) => Operation::variadic(|_ecx, _exprs| {
3292 bail_unsupported!("aclitemin")
3293 }) => AclItem, 1031;
3294 },
3295 "any_in" => Scalar {
3296 params!(String) => Operation::variadic(|_ecx, _exprs| {
3297 bail_unsupported!("any_in")
3298 }) => Any, 2294;
3299 },
3300 "anyarray_in" => Scalar {
3301 params!(String) => Operation::variadic(|_ecx, _exprs| {
3302 bail_unsupported!("anyarray_in")
3303 }) => ArrayAny, 2296;
3304 },
3305 "anycompatible_in" => Scalar {
3306 params!(String) => Operation::variadic(|_ecx, _exprs| {
3307 bail_unsupported!("anycompatible_in")
3308 }) => AnyCompatible, 5086;
3309 },
3310 "anycompatiblearray_in" => Scalar {
3311 params!(String) => Operation::variadic(|_ecx, _exprs| {
3312 bail_unsupported!("anycompatiblearray_in")
3313 }) => ArrayAnyCompatible, 5088;
3314 },
3315 "anycompatiblenonarray_in" => Scalar {
3316 params!(String) => Operation::variadic(|_ecx, _exprs| {
3317 bail_unsupported!("anycompatiblenonarray_in")
3318 }) => NonVecAnyCompatible, 5092;
3319 },
3320 "anycompatiblerange_in" => Scalar {
3321 params!(String, Oid, Int32) =>
3322 Operation::variadic(|_ecx, _exprs| {
3323 bail_unsupported!("anycompatiblerange_in")
3324 }) => RangeAnyCompatible, 5094;
3325 },
3326 "anyelement_in" => Scalar {
3327 params!(String) => Operation::variadic(|_ecx, _exprs| {
3328 bail_unsupported!("anyelement_in")
3329 }) => AnyElement, 2312;
3330 },
3331 "anynonarray_in" => Scalar {
3332 params!(String) => Operation::variadic(|_ecx, _exprs| {
3333 bail_unsupported!("anynonarray_in")
3334 }) => NonVecAny, 2777;
3335 },
3336 "anyrange_in" => Scalar {
3337 params!(String, Oid, Int32) =>
3338 Operation::variadic(|_ecx, _exprs| {
3339 bail_unsupported!("anyrange_in")
3340 }) => RangeAny, 3832;
3341 },
3342 "array_in" => Scalar {
3343 params!(String, Oid, Int32) =>
3344 Operation::variadic(|_ecx, _exprs| {
3345 bail_unsupported!("array_in")
3346 }) => ArrayAny, 750;
3347 },
3348 "boolin" => Scalar {
3349 params!(String) => Operation::variadic(|_ecx, _exprs| {
3350 bail_unsupported!("boolin")
3351 }) => Bool, 1242;
3352 },
3353 "bpcharin" => Scalar {
3354 params!(String, Oid, Int32) =>
3355 Operation::variadic(|_ecx, _exprs| {
3356 bail_unsupported!("bpcharin")
3357 }) => Char, 1044;
3358 },
3359 "byteain" => Scalar {
3360 params!(String) => Operation::variadic(|_ecx, _exprs| {
3361 bail_unsupported!("byteain")
3362 }) => Bytes, 1244;
3363 },
3364 "charin" => Scalar {
3365 params!(String) => Operation::variadic(|_ecx, _exprs| {
3366 bail_unsupported!("charin")
3367 }) => PgLegacyChar, 1245;
3368 },
3369 "date_in" => Scalar {
3370 params!(String) => Operation::variadic(|_ecx, _exprs| {
3371 bail_unsupported!("date_in")
3372 }) => Date, 1084;
3373 },
3374 "float4in" => Scalar {
3375 params!(String) => Operation::variadic(|_ecx, _exprs| {
3376 bail_unsupported!("float4in")
3377 }) => Float32, 200;
3378 },
3379 "float8in" => Scalar {
3380 params!(String) => Operation::variadic(|_ecx, _exprs| {
3381 bail_unsupported!("float8in")
3382 }) => Float64, 214;
3383 },
3384 "int2in" => Scalar {
3385 params!(String) => Operation::variadic(|_ecx, _exprs| {
3386 bail_unsupported!("int2in")
3387 }) => Int16, 38;
3388 },
3389 "int2vectorin" => Scalar {
3390 params!(String) => Operation::variadic(|_ecx, _exprs| {
3391 bail_unsupported!("int2vectorin")
3392 }) => Int2Vector, 40;
3393 },
3394 "int4in" => Scalar {
3395 params!(String) => Operation::variadic(|_ecx, _exprs| {
3396 bail_unsupported!("int4in")
3397 }) => Int32, 42;
3398 },
3399 "int8in" => Scalar {
3400 params!(String) => Operation::variadic(|_ecx, _exprs| {
3401 bail_unsupported!("int8in")
3402 }) => Int64, 460;
3403 },
3404 "internal_in" => Scalar {
3405 params!(String) => Operation::variadic(|_ecx, _exprs| {
3406 bail_unsupported!("internal_in")
3407 }) => Internal, 2304;
3408 },
3409 "interval_in" => Scalar {
3410 params!(String, Oid, Int32) =>
3411 Operation::variadic(|_ecx, _exprs| {
3412 bail_unsupported!("interval_in")
3413 }) => Interval, 1160;
3414 },
3415 "jsonb_in" => Scalar {
3416 params!(String) => Operation::variadic(|_ecx, _exprs| {
3417 bail_unsupported!("jsonb_in")
3418 }) => Jsonb, 3806;
3419 },
3420 "namein" => Scalar {
3421 params!(String) => Operation::variadic(|_ecx, _exprs| {
3422 bail_unsupported!("namein")
3423 }) => PgLegacyName, 34;
3424 },
3425 "numeric_in" => Scalar {
3426 params!(String, Oid, Int32) =>
3427 Operation::variadic(|_ecx, _exprs| {
3428 bail_unsupported!("numeric_in")
3429 }) => Numeric, 1701;
3430 },
3431 "oidin" => Scalar {
3432 params!(String) => Operation::variadic(|_ecx, _exprs| {
3433 bail_unsupported!("oidin")
3434 }) => Oid, 1798;
3435 },
3436 "range_in" => Scalar {
3437 params!(String, Oid, Int32) =>
3438 Operation::variadic(|_ecx, _exprs| {
3439 bail_unsupported!("range_in")
3440 }) => RangeAny, 3834;
3441 },
3442 "record_in" => Scalar {
3443 params!(String, Oid, Int32) =>
3444 Operation::variadic(|_ecx, _exprs| {
3445 bail_unsupported!("record_in")
3446 }) => RecordAny, 2290;
3447 },
3448 "regclassin" => Scalar {
3449 params!(String) => Operation::variadic(|_ecx, _exprs| {
3450 bail_unsupported!("regclassin")
3451 }) => RegClass, 2218;
3452 },
3453 "regprocin" => Scalar {
3454 params!(String) => Operation::variadic(|_ecx, _exprs| {
3455 bail_unsupported!("regprocin")
3456 }) => RegProc, 44;
3457 },
3458 "regtypein" => Scalar {
3459 params!(String) => Operation::variadic(|_ecx, _exprs| {
3460 bail_unsupported!("regtypein")
3461 }) => RegType, 2220;
3462 },
3463 "textin" => Scalar {
3464 params!(String) => Operation::variadic(|_ecx, _exprs| {
3465 bail_unsupported!("textin")
3466 }) => String, 46;
3467 },
3468 "time_in" => Scalar {
3469 params!(String, Oid, Int32) =>
3470 Operation::variadic(|_ecx, _exprs| {
3471 bail_unsupported!("time_in")
3472 }) => Time, 1143;
3473 },
3474 "timestamp_in" => Scalar {
3475 params!(String, Oid, Int32) =>
3476 Operation::variadic(|_ecx, _exprs| {
3477 bail_unsupported!("timestamp_in")
3478 }) => Timestamp, 1312;
3479 },
3480 "timestamptz_in" => Scalar {
3481 params!(String, Oid, Int32) =>
3482 Operation::variadic(|_ecx, _exprs| {
3483 bail_unsupported!("timestamptz_in")
3484 }) => TimestampTz, 1150;
3485 },
3486 "varcharin" => Scalar {
3487 params!(String, Oid, Int32) =>
3488 Operation::variadic(|_ecx, _exprs| {
3489 bail_unsupported!("varcharin")
3490 }) => VarChar, 1046;
3491 },
3492 "uuid_in" => Scalar {
3493 params!(String) => Operation::variadic(|_ecx, _exprs| {
3494 bail_unsupported!("uuid_in")
3495 }) => Uuid, 2952;
3496 },
3497 "boolrecv" => Scalar {
3498 params!(Internal) =>
3499 Operation::nullary(|_ecx| catalog_name_only!("boolrecv"))
3500 => Bool, 2436;
3501 },
3502 "textrecv" => Scalar {
3503 params!(Internal) =>
3504 Operation::nullary(|_ecx| catalog_name_only!("textrecv"))
3505 => String, 2414;
3506 },
3507 "anyarray_recv" => Scalar {
3508 params!(Internal) =>
3509 Operation::nullary(|_ecx| {
3510 catalog_name_only!("anyarray_recv")
3511 }) => ArrayAny, 2502;
3512 },
3513 "bytearecv" => Scalar {
3514 params!(Internal) =>
3515 Operation::nullary(|_ecx| catalog_name_only!("bytearecv"))
3516 => Bytes, 2412;
3517 },
3518 "bpcharrecv" => Scalar {
3519 params!(Internal) =>
3520 Operation::nullary(|_ecx| {
3521 catalog_name_only!("bpcharrecv")
3522 }) => Char, 2430;
3523 },
3524 "charrecv" => Scalar {
3525 params!(Internal) =>
3526 Operation::nullary(|_ecx| catalog_name_only!("charrecv"))
3527 => PgLegacyChar, 2434;
3528 },
3529 "date_recv" => Scalar {
3530 params!(Internal) =>
3531 Operation::nullary(|_ecx| catalog_name_only!("date_recv"))
3532 => Date, 2468;
3533 },
3534 "float4recv" => Scalar {
3535 params!(Internal) =>
3536 Operation::nullary(|_ecx| {
3537 catalog_name_only!("float4recv")
3538 }) => Float32, 2424;
3539 },
3540 "float8recv" => Scalar {
3541 params!(Internal) =>
3542 Operation::nullary(|_ecx| {
3543 catalog_name_only!("float8recv")
3544 }) => Float64, 2426;
3545 },
3546 "int4recv" => Scalar {
3547 params!(Internal) =>
3548 Operation::nullary(|_ecx| catalog_name_only!("int4recv"))
3549 => Int32, 2406;
3550 },
3551 "int8recv" => Scalar {
3552 params!(Internal) =>
3553 Operation::nullary(|_ecx| catalog_name_only!("int8recv"))
3554 => Int64, 2408;
3555 },
3556 "interval_recv" => Scalar {
3557 params!(Internal) =>
3558 Operation::nullary(|_ecx| {
3559 catalog_name_only!("interval_recv")
3560 }) => Interval, 2478;
3561 },
3562 "jsonb_recv" => Scalar {
3563 params!(Internal) =>
3564 Operation::nullary(|_ecx| {
3565 catalog_name_only!("jsonb_recv")
3566 }) => Jsonb, 3805;
3567 },
3568 "namerecv" => Scalar {
3569 params!(Internal) =>
3570 Operation::nullary(|_ecx| catalog_name_only!("namerecv"))
3571 => PgLegacyName, 2422;
3572 },
3573 "numeric_recv" => Scalar {
3574 params!(Internal) =>
3575 Operation::nullary(|_ecx| {
3576 catalog_name_only!("numeric_recv")
3577 }) => Numeric, 2460;
3578 },
3579 "oidrecv" => Scalar {
3580 params!(Internal) =>
3581 Operation::nullary(|_ecx| catalog_name_only!("oidrecv"))
3582 => Oid, 2418;
3583 },
3584 "record_recv" => Scalar {
3585 params!(Internal) =>
3586 Operation::nullary(|_ecx| {
3587 catalog_name_only!("recordrerecord_recvcv")
3588 }) => RecordAny, 2402;
3589 },
3590 "regclassrecv" => Scalar {
3591 params!(Internal) =>
3592 Operation::nullary(|_ecx| {
3593 catalog_name_only!("regclassrecv")
3594 }) => RegClass, 2452;
3595 },
3596 "regprocrecv" => Scalar {
3597 params!(Internal) =>
3598 Operation::nullary(|_ecx| {
3599 catalog_name_only!("regprocrecv")
3600 }) => RegProc, 2444;
3601 },
3602 "regtyperecv" => Scalar {
3603 params!(Internal) =>
3604 Operation::nullary(|_ecx| {
3605 catalog_name_only!("regtyperecv")
3606 }) => RegType, 2454;
3607 },
3608 "int2recv" => Scalar {
3609 params!(Internal) =>
3610 Operation::nullary(|_ecx| catalog_name_only!("int2recv"))
3611 => Int16, 2404;
3612 },
3613 "time_recv" => Scalar {
3614 params!(Internal) =>
3615 Operation::nullary(|_ecx| catalog_name_only!("time_recv"))
3616 => Time, 2470;
3617 },
3618 "timestamp_recv" => Scalar {
3619 params!(Internal) =>
3620 Operation::nullary(|_ecx| {
3621 catalog_name_only!("timestamp_recv")
3622 }) => Timestamp, 2474;
3623 },
3624 "timestamptz_recv" => Scalar {
3625 params!(Internal) =>
3626 Operation::nullary(|_ecx| {
3627 catalog_name_only!("timestamptz_recv")
3628 }) => TimestampTz, 2476;
3629 },
3630 "uuid_recv" => Scalar {
3631 params!(Internal) =>
3632 Operation::nullary(|_ecx| catalog_name_only!("uuid_recv"))
3633 => Uuid, 2961;
3634 },
3635 "varcharrecv" => Scalar {
3636 params!(Internal) =>
3637 Operation::nullary(|_ecx| {
3638 catalog_name_only!("varcharrecv")
3639 }) => VarChar, 2432;
3640 },
3641 "int2vectorrecv" => Scalar {
3642 params!(Internal) =>
3643 Operation::nullary(|_ecx| {
3644 catalog_name_only!("int2vectorrecv")
3645 }) => Int2Vector, 2410;
3646 },
3647 "anycompatiblearray_recv" => Scalar {
3648 params!(Internal) =>
3649 Operation::nullary(|_ecx| {
3650 catalog_name_only!("anycompatiblearray_recv")
3651 }) => ArrayAnyCompatible, 5090;
3652 },
3653 "array_recv" => Scalar {
3654 params!(Internal) =>
3655 Operation::nullary(|_ecx| {
3656 catalog_name_only!("array_recv")
3657 }) => ArrayAny, 2400;
3658 },
3659 "range_recv" => Scalar {
3660 params!(Internal) =>
3661 Operation::nullary(|_ecx| {
3662 catalog_name_only!("range_recv")
3663 }) => RangeAny, 3836;
3664 },
3665
3666
3667 "array_agg" => Aggregate {
3669 params!(NonVecAny) => Operation::unary_ordered(|ecx, e, order_by| {
3670 let elem_type = ecx.scalar_type(&e);
3671
3672 let elem_type = match elem_type.array_of_self_elem_type() {
3673 Ok(elem_type) => elem_type,
3674 Err(elem_type) => bail_unsupported!(
3675 format!("array_agg on {}", ecx.humanize_sql_scalar_type(&elem_type, false))
3676 ),
3677 };
3678
3679 let e_arr = HirScalarExpr::call_variadic(
3682 variadic::ArrayCreate { elem_type },
3683 vec![e],
3684 );
3685 Ok((e_arr, AggregateFunc::ArrayConcat { order_by }))
3686 }) => ArrayAny, 2335;
3687 params!(ArrayAny) => Operation::unary(|_ecx, _e| {
3688 bail_unsupported!("array_agg on arrays")
3689 }) => ArrayAny, 4053;
3690 },
3691 "bool_and" => Aggregate {
3692 params!(Bool) =>
3693 Operation::nullary(|_ecx| catalog_name_only!("bool_and"))
3694 => Bool, 2517;
3695 },
3696 "bool_or" => Aggregate {
3697 params!(Bool) => Operation::nullary(|_ecx| catalog_name_only!("bool_or")) => Bool, 2518;
3698 },
3699 "count" => Aggregate {
3700 params!() => Operation::nullary(|_ecx| {
3701 Ok((HirScalarExpr::literal_true(), AggregateFunc::Count))
3705 }) => Int64, 2803;
3706 params!(Any) => AggregateFunc::Count => Int64, 2147;
3707 },
3708 "max" => Aggregate {
3709 params!(Bool) => AggregateFunc::MaxBool => Bool, oid::FUNC_MAX_BOOL_OID;
3710 params!(Int16) => AggregateFunc::MaxInt16 => Int16, 2117;
3711 params!(Int32) => AggregateFunc::MaxInt32 => Int32, 2116;
3712 params!(Int64) => AggregateFunc::MaxInt64 => Int64, 2115;
3713 params!(UInt16) => AggregateFunc::MaxUInt16 => UInt16, oid::FUNC_MAX_UINT16_OID;
3714 params!(UInt32) => AggregateFunc::MaxUInt32 => UInt32, oid::FUNC_MAX_UINT32_OID;
3715 params!(UInt64) => AggregateFunc::MaxUInt64 => UInt64, oid::FUNC_MAX_UINT64_OID;
3716 params!(MzTimestamp) => AggregateFunc::MaxMzTimestamp
3717 => MzTimestamp, oid::FUNC_MAX_MZ_TIMESTAMP_OID;
3718 params!(Float32) => AggregateFunc::MaxFloat32 => Float32, 2119;
3719 params!(Float64) => AggregateFunc::MaxFloat64 => Float64, 2120;
3720 params!(String) => AggregateFunc::MaxString => String, 2129;
3721 params!(Char) => AggregateFunc::MaxString => Char, 2244;
3723 params!(Date) => AggregateFunc::MaxDate => Date, 2122;
3724 params!(Timestamp) => AggregateFunc::MaxTimestamp => Timestamp, 2126;
3725 params!(TimestampTz) => AggregateFunc::MaxTimestampTz => TimestampTz, 2127;
3726 params!(Numeric) => AggregateFunc::MaxNumeric => Numeric, oid::FUNC_MAX_NUMERIC_OID;
3727 params!(Interval) => AggregateFunc::MaxInterval => Interval, 2128;
3728 params!(Time) => AggregateFunc::MaxTime => Time, 2123;
3729 params!(ArrayAny) => AggregateFunc::MaxArray => ArrayAny, 2050;
3730 params!(ListAny) => AggregateFunc::MaxList => ListAny, oid::FUNC_MAX_LIST_OID;
3731 },
3732 "min" => Aggregate {
3733 params!(Bool) => AggregateFunc::MinBool => Bool, oid::FUNC_MIN_BOOL_OID;
3734 params!(Int16) => AggregateFunc::MinInt16 => Int16, 2133;
3735 params!(Int32) => AggregateFunc::MinInt32 => Int32, 2132;
3736 params!(Int64) => AggregateFunc::MinInt64 => Int64, 2131;
3737 params!(UInt16) => AggregateFunc::MinUInt16 => UInt16, oid::FUNC_MIN_UINT16_OID;
3738 params!(UInt32) => AggregateFunc::MinUInt32 => UInt32, oid::FUNC_MIN_UINT32_OID;
3739 params!(UInt64) => AggregateFunc::MinUInt64 => UInt64, oid::FUNC_MIN_UINT64_OID;
3740 params!(MzTimestamp) => AggregateFunc::MinMzTimestamp
3741 => MzTimestamp, oid::FUNC_MIN_MZ_TIMESTAMP_OID;
3742 params!(Float32) => AggregateFunc::MinFloat32 => Float32, 2135;
3743 params!(Float64) => AggregateFunc::MinFloat64 => Float64, 2136;
3744 params!(String) => AggregateFunc::MinString => String, 2145;
3745 params!(Char) => AggregateFunc::MinString => Char, 2245;
3747 params!(Date) => AggregateFunc::MinDate => Date, 2138;
3748 params!(Timestamp) => AggregateFunc::MinTimestamp => Timestamp, 2142;
3749 params!(TimestampTz) => AggregateFunc::MinTimestampTz => TimestampTz, 2143;
3750 params!(Numeric) => AggregateFunc::MinNumeric => Numeric, oid::FUNC_MIN_NUMERIC_OID;
3751 params!(Interval) => AggregateFunc::MinInterval => Interval, 2144;
3752 params!(Time) => AggregateFunc::MinTime => Time, 2139;
3753 params!(ArrayAny) => AggregateFunc::MinArray => ArrayAny, 2051;
3754 params!(ListAny) => AggregateFunc::MinList => ListAny, oid::FUNC_MIN_LIST_OID;
3755 },
3756 "jsonb_agg" => Aggregate {
3757 params!(Any) => Operation::unary_ordered(|ecx, e, order_by| {
3758 let e = match ecx.scalar_type(&e) {
3760 SqlScalarType::Char { length } => {
3761 e.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
3762 }
3763 _ => e,
3764 };
3765 let json_null = HirScalarExpr::literal(Datum::JsonNull, SqlScalarType::Jsonb);
3771 let e = HirScalarExpr::call_variadic(
3772 variadic::Coalesce,
3773 vec![typeconv::to_jsonb(ecx, e)?, json_null],
3774 );
3775 Ok((e, AggregateFunc::JsonbAgg { order_by }))
3776 }) => Jsonb, 3267;
3777 },
3778 "jsonb_object_agg" => Aggregate {
3779 params!(Any, Any) => Operation::binary_ordered(|ecx, key, val, order_by| {
3780 let key = match ecx.scalar_type(&key) {
3782 SqlScalarType::Char { length } => {
3783 key.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
3784 }
3785 _ => key,
3786 };
3787 let val = match ecx.scalar_type(&val) {
3788 SqlScalarType::Char { length } => {
3789 val.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
3790 }
3791 _ => val,
3792 };
3793
3794 let json_null = HirScalarExpr::literal(Datum::JsonNull, SqlScalarType::Jsonb);
3795 let key = typeconv::to_string(ecx, key)?;
3796 let val = HirScalarExpr::call_variadic(
3803 variadic::Coalesce,
3804 vec![typeconv::to_jsonb(ecx, val)?, json_null],
3805 );
3806 let e = HirScalarExpr::call_variadic(
3807 variadic::RecordCreate {
3808 field_names: vec![ColumnName::from("key"), ColumnName::from("val")],
3809 },
3810 vec![key, val],
3811 );
3812 Ok((e, AggregateFunc::JsonbObjectAgg { order_by }))
3813 }) => Jsonb, 3270;
3814 },
3815 "string_agg" => Aggregate {
3816 params!(String, String) => Operation::binary_ordered(|_ecx, value, sep, order_by| {
3817 let e = HirScalarExpr::call_variadic(
3818 variadic::RecordCreate {
3819 field_names: vec![ColumnName::from("value"), ColumnName::from("sep")],
3820 },
3821 vec![value, sep],
3822 );
3823 Ok((e, AggregateFunc::StringAgg { order_by }))
3824 }) => String, 3538;
3825 params!(Bytes, Bytes) =>
3826 Operation::binary(|_ecx, _l, _r| {
3827 bail_unsupported!("string_agg on BYTEA")
3828 }) => Bytes, 3545;
3829 },
3830 "string_to_array" => Scalar {
3831 params!(String, String) => VariadicFunc::from(variadic::StringToArray)
3832 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 376;
3833 params!(String, String, String) => VariadicFunc::from(variadic::StringToArray)
3834 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 394;
3835 },
3836 "sum" => Aggregate {
3837 params!(Int16) => AggregateFunc::SumInt16 => Int64, 2109;
3838 params!(Int32) => AggregateFunc::SumInt32 => Int64, 2108;
3839 params!(Int64) => AggregateFunc::SumInt64 => Numeric, 2107;
3840 params!(UInt16) => AggregateFunc::SumUInt16 => UInt64, oid::FUNC_SUM_UINT16_OID;
3841 params!(UInt32) => AggregateFunc::SumUInt32 => UInt64, oid::FUNC_SUM_UINT32_OID;
3842 params!(UInt64) => AggregateFunc::SumUInt64 => Numeric, oid::FUNC_SUM_UINT64_OID;
3843 params!(Float32) => AggregateFunc::SumFloat32 => Float32, 2110;
3844 params!(Float64) => AggregateFunc::SumFloat64 => Float64, 2111;
3845 params!(Numeric) => AggregateFunc::SumNumeric => Numeric, 2114;
3846 params!(Interval) => AggregateFunc::SumInterval => Interval, 2113;
3847 },
3848
3849 "row_number" => ScalarWindow {
3851 params!() => ScalarWindowFunc::RowNumber => Int64, 3100;
3852 },
3853 "rank" => ScalarWindow {
3854 params!() => ScalarWindowFunc::Rank => Int64, 3101;
3855 },
3856 "dense_rank" => ScalarWindow {
3857 params!() => ScalarWindowFunc::DenseRank => Int64, 3102;
3858 },
3859 "lag" => ValueWindow {
3860 params!(AnyElement) => Operation::unary(|ecx, e| {
3862 let typ = ecx.scalar_type(&e);
3863 let e = HirScalarExpr::call_variadic(
3864 variadic::RecordCreate {
3865 field_names: vec![
3866 ColumnName::from("expr"),
3867 ColumnName::from("offset"),
3868 ColumnName::from("default"),
3869 ],
3870 },
3871 vec![
3872 e,
3873 HirScalarExpr::literal(Datum::Int32(1), SqlScalarType::Int32),
3874 HirScalarExpr::literal_null(typ),
3875 ],
3876 );
3877 Ok((e, ValueWindowFunc::Lag))
3878 }) => AnyElement, 3106;
3879 params!(AnyElement, Int32) => Operation::binary(|ecx, e, offset| {
3880 let typ = ecx.scalar_type(&e);
3881 let e = HirScalarExpr::call_variadic(
3882 variadic::RecordCreate {
3883 field_names: vec![
3884 ColumnName::from("expr"),
3885 ColumnName::from("offset"),
3886 ColumnName::from("default"),
3887 ],
3888 },
3889 vec![e, offset, HirScalarExpr::literal_null(typ)],
3890 );
3891 Ok((e, ValueWindowFunc::Lag))
3892 }) => AnyElement, 3107;
3893 params!(AnyCompatible, Int32, AnyCompatible) => Operation::variadic(|_ecx, exprs| {
3894 let e = HirScalarExpr::call_variadic(
3895 variadic::RecordCreate {
3896 field_names: vec![
3897 ColumnName::from("expr"),
3898 ColumnName::from("offset"),
3899 ColumnName::from("default"),
3900 ],
3901 },
3902 exprs,
3903 );
3904 Ok((e, ValueWindowFunc::Lag))
3905 }) => AnyCompatible, 3108;
3906 },
3907 "lead" => ValueWindow {
3908 params!(AnyElement) => Operation::unary(|ecx, e| {
3910 let typ = ecx.scalar_type(&e);
3911 let e = HirScalarExpr::call_variadic(
3912 variadic::RecordCreate {
3913 field_names: vec![
3914 ColumnName::from("expr"),
3915 ColumnName::from("offset"),
3916 ColumnName::from("default"),
3917 ],
3918 },
3919 vec![
3920 e,
3921 HirScalarExpr::literal(Datum::Int32(1), SqlScalarType::Int32),
3922 HirScalarExpr::literal_null(typ),
3923 ],
3924 );
3925 Ok((e, ValueWindowFunc::Lead))
3926 }) => AnyElement, 3109;
3927 params!(AnyElement, Int32) => Operation::binary(|ecx, e, offset| {
3928 let typ = ecx.scalar_type(&e);
3929 let e = HirScalarExpr::call_variadic(
3930 variadic::RecordCreate {
3931 field_names: vec![
3932 ColumnName::from("expr"),
3933 ColumnName::from("offset"),
3934 ColumnName::from("default"),
3935 ],
3936 },
3937 vec![e, offset, HirScalarExpr::literal_null(typ)],
3938 );
3939 Ok((e, ValueWindowFunc::Lead))
3940 }) => AnyElement, 3110;
3941 params!(AnyCompatible, Int32, AnyCompatible) => Operation::variadic(|_ecx, exprs| {
3942 let e = HirScalarExpr::call_variadic(
3943 variadic::RecordCreate {
3944 field_names: vec![
3945 ColumnName::from("expr"),
3946 ColumnName::from("offset"),
3947 ColumnName::from("default"),
3948 ],
3949 },
3950 exprs,
3951 );
3952 Ok((e, ValueWindowFunc::Lead))
3953 }) => AnyCompatible, 3111;
3954 },
3955 "first_value" => ValueWindow {
3956 params!(AnyElement) => ValueWindowFunc::FirstValue => AnyElement, 3112;
3957 },
3958 "last_value" => ValueWindow {
3959 params!(AnyElement) => ValueWindowFunc::LastValue => AnyElement, 3113;
3960 },
3961
3962 "generate_series" => Table {
3964 params!(Int32, Int32, Int32) => Operation::variadic(move |_ecx, exprs| {
3965 Ok(TableFuncPlan {
3966 imp: TableFuncImpl::CallTable {
3967 func: TableFunc::GenerateSeriesInt32,
3968 exprs,
3969 },
3970 column_names: vec!["generate_series".into()],
3971 })
3972 }) => ReturnType::set_of(Int32.into()), 1066;
3973 params!(Int32, Int32) => Operation::binary(move |_ecx, start, stop| {
3974 Ok(TableFuncPlan {
3975 imp: TableFuncImpl::CallTable {
3976 func: TableFunc::GenerateSeriesInt32,
3977 exprs: vec![
3978 start, stop,
3979 HirScalarExpr::literal(Datum::Int32(1), SqlScalarType::Int32),
3980 ],
3981 },
3982 column_names: vec!["generate_series".into()],
3983 })
3984 }) => ReturnType::set_of(Int32.into()), 1067;
3985 params!(Int64, Int64, Int64) => Operation::variadic(move |_ecx, exprs| {
3986 Ok(TableFuncPlan {
3987 imp: TableFuncImpl::CallTable {
3988 func: TableFunc::GenerateSeriesInt64,
3989 exprs,
3990 },
3991 column_names: vec!["generate_series".into()],
3992 })
3993 }) => ReturnType::set_of(Int64.into()), 1068;
3994 params!(Int64, Int64) => Operation::binary(move |_ecx, start, stop| {
3995 Ok(TableFuncPlan {
3996 imp: TableFuncImpl::CallTable {
3997 func: TableFunc::GenerateSeriesInt64,
3998 exprs: vec![
3999 start, stop,
4000 HirScalarExpr::literal(Datum::Int64(1), SqlScalarType::Int64),
4001 ],
4002 },
4003 column_names: vec!["generate_series".into()],
4004 })
4005 }) => ReturnType::set_of(Int64.into()), 1069;
4006 params!(Timestamp, Timestamp, Interval) => Operation::variadic(move |_ecx, exprs| {
4007 Ok(TableFuncPlan {
4008 imp: TableFuncImpl::CallTable {
4009 func: TableFunc::GenerateSeriesTimestamp,
4010 exprs,
4011 },
4012 column_names: vec!["generate_series".into()],
4013 })
4014 }) => ReturnType::set_of(Timestamp.into()), 938;
4015 params!(TimestampTz, TimestampTz, Interval) => Operation::variadic(move |_ecx, exprs| {
4016 Ok(TableFuncPlan {
4017 imp: TableFuncImpl::CallTable {
4018 func: TableFunc::GenerateSeriesTimestampTz,
4019 exprs,
4020 },
4021 column_names: vec!["generate_series".into()],
4022 })
4023 }) => ReturnType::set_of(TimestampTz.into()), 939;
4024 },
4025
4026 "generate_subscripts" => Table {
4027 params!(ArrayAny, Int32) => Operation::variadic(move |_ecx, exprs| {
4028 Ok(TableFuncPlan {
4029 imp: TableFuncImpl::CallTable {
4030 func: TableFunc::GenerateSubscriptsArray,
4031 exprs,
4032 },
4033 column_names: vec!["generate_subscripts".into()],
4034 })
4035 }) => ReturnType::set_of(Int32.into()), 1192;
4036 },
4037
4038 "jsonb_array_elements" => Table {
4039 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
4040 Ok(TableFuncPlan {
4041 imp: TableFuncImpl::CallTable {
4042 func: TableFunc::JsonbArrayElements,
4043 exprs: vec![jsonb],
4044 },
4045 column_names: vec!["value".into()],
4046 })
4047 }) => ReturnType::set_of(Jsonb.into()), 3219;
4048 },
4049 "jsonb_array_elements_text" => Table {
4050 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
4051 Ok(TableFuncPlan {
4052 imp: TableFuncImpl::CallTable {
4053 func: TableFunc::JsonbArrayElementsStringify,
4054 exprs: vec![jsonb],
4055 },
4056 column_names: vec!["value".into()],
4057 })
4058 }) => ReturnType::set_of(String.into()), 3465;
4059 },
4060 "jsonb_each" => Table {
4061 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
4062 Ok(TableFuncPlan {
4063 imp: TableFuncImpl::CallTable {
4064 func: TableFunc::JsonbEach,
4065 exprs: vec![jsonb],
4066 },
4067 column_names: vec!["key".into(), "value".into()],
4068 })
4069 }) => ReturnType::set_of(RecordAny), 3208;
4070 },
4071 "jsonb_each_text" => Table {
4072 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
4073 Ok(TableFuncPlan {
4074 imp: TableFuncImpl::CallTable {
4075 func: TableFunc::JsonbEachStringify,
4076 exprs: vec![jsonb],
4077 },
4078 column_names: vec!["key".into(), "value".into()],
4079 })
4080 }) => ReturnType::set_of(RecordAny), 3932;
4081 },
4082 "jsonb_object_keys" => Table {
4083 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
4084 Ok(TableFuncPlan {
4085 imp: TableFuncImpl::CallTable {
4086 func: TableFunc::JsonbObjectKeys,
4087 exprs: vec![jsonb],
4088 },
4089 column_names: vec!["jsonb_object_keys".into()],
4090 })
4091 }) => ReturnType::set_of(String.into()), 3931;
4092 },
4093 "date_bin_hopping" => Table {
4097 params!(Interval, Interval, Timestamp)
4099 => experimental_sql_impl_table_func(
4100 &vars::ENABLE_DATE_BIN_HOPPING, "
4101 SELECT *
4102 FROM pg_catalog.generate_series(
4103 pg_catalog.date_bin($1, $3 + $1, '1970-01-01') - $2, $3, $1
4104 ) AS dbh(date_bin_hopping)
4105 ") => ReturnType::set_of(Timestamp.into()),
4106 oid::FUNC_MZ_DATE_BIN_HOPPING_UNIX_EPOCH_TS_OID;
4107 params!(Interval, Interval, TimestampTz)
4109 => experimental_sql_impl_table_func(
4110 &vars::ENABLE_DATE_BIN_HOPPING, "
4111 SELECT *
4112 FROM pg_catalog.generate_series(
4113 pg_catalog.date_bin($1, $3 + $1, '1970-01-01') - $2, $3, $1
4114 ) AS dbh(date_bin_hopping)
4115 ") => ReturnType::set_of(TimestampTz.into()),
4116 oid::FUNC_MZ_DATE_BIN_HOPPING_UNIX_EPOCH_TSTZ_OID;
4117 params!(Interval, Interval, Timestamp, Timestamp)
4119 => experimental_sql_impl_table_func(
4120 &vars::ENABLE_DATE_BIN_HOPPING, "
4121 SELECT *
4122 FROM pg_catalog.generate_series(
4123 pg_catalog.date_bin($1, $3 + $1, $4) - $2, $3, $1
4124 ) AS dbh(date_bin_hopping)
4125 ") => ReturnType::set_of(Timestamp.into()),
4126 oid::FUNC_MZ_DATE_BIN_HOPPING_TS_OID;
4127 params!(Interval, Interval, TimestampTz, TimestampTz)
4129 => experimental_sql_impl_table_func(
4130 &vars::ENABLE_DATE_BIN_HOPPING, "
4131 SELECT *
4132 FROM pg_catalog.generate_series(
4133 pg_catalog.date_bin($1, $3 + $1, $4) - $2, $3, $1
4134 ) AS dbh(date_bin_hopping)
4135 ") => ReturnType::set_of(TimestampTz.into()),
4136 oid::FUNC_MZ_DATE_BIN_HOPPING_TSTZ_OID;
4137 },
4138 "encode" => Scalar {
4139 params!(Bytes, String) => BinaryFunc::from(func::Encode) => String, 1946;
4140 },
4141 "decode" => Scalar {
4142 params!(String, String) => BinaryFunc::from(func::Decode) => Bytes, 1947;
4143 },
4144 "regexp_split_to_array" => Scalar {
4145 params!(String, String) => VariadicFunc::from(variadic::RegexpSplitToArray)
4146 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 2767;
4147 params!(String, String, String) => VariadicFunc::from(variadic::RegexpSplitToArray)
4148 => SqlScalarType::Array(Box::new(SqlScalarType::String)), 2768;
4149 },
4150 "regexp_split_to_table" => Table {
4151 params!(String, String) => sql_impl_table_func("
4152 SELECT unnest(regexp_split_to_array($1, $2))
4153 ") => ReturnType::set_of(String.into()), 2765;
4154 params!(String, String, String) => sql_impl_table_func("
4155 SELECT unnest(regexp_split_to_array($1, $2, $3))
4156 ") => ReturnType::set_of(String.into()), 2766;
4157 },
4158 "regexp_replace" => Scalar {
4159 params!(String, String, String)
4160 => VariadicFunc::from(variadic::RegexpReplace) => String, 2284;
4161 params!(String, String, String, String)
4162 => VariadicFunc::from(variadic::RegexpReplace) => String, 2285;
4163 },
4167 "regexp_matches" => Table {
4168 params!(String, String) => Operation::variadic(move |_ecx, exprs| {
4169 let column_names = vec!["regexp_matches".into()];
4170 Ok(TableFuncPlan {
4171 imp: TableFuncImpl::CallTable {
4172 func: TableFunc::RegexpMatches,
4173 exprs: vec![exprs[0].clone(), exprs[1].clone()],
4174 },
4175 column_names,
4176 })
4177 }) => ReturnType::set_of(
4178 SqlScalarType::Array(Box::new(SqlScalarType::String)).into(),
4179 ), 2763;
4180 params!(String, String, String) => Operation::variadic(move |_ecx, exprs| {
4181 let column_names = vec!["regexp_matches".into()];
4182 Ok(TableFuncPlan {
4183 imp: TableFuncImpl::CallTable {
4184 func: TableFunc::RegexpMatches,
4185 exprs: vec![exprs[0].clone(), exprs[1].clone(), exprs[2].clone()],
4186 },
4187 column_names,
4188 })
4189 }) => ReturnType::set_of(
4190 SqlScalarType::Array(Box::new(SqlScalarType::String)).into(),
4191 ), 2764;
4192 },
4193 "reverse" => Scalar {
4194 params!(String) => UnaryFunc::Reverse(func::Reverse) => String, 3062;
4195 }
4196 };
4197
4198 for sef_builtin in PG_CATALOG_SEF_BUILTINS.values() {
4202 builtins.insert(
4203 sef_builtin.name,
4204 Func::Scalar(vec![FuncImpl {
4205 oid: sef_builtin.oid,
4206 params: ParamList::Exact(
4207 sef_builtin
4208 .param_types
4209 .iter()
4210 .map(|t| ParamType::from(t.clone()))
4211 .collect(),
4212 ),
4213 return_type: ReturnType::scalar(ParamType::from(
4214 sef_builtin.return_type.scalar_type.clone(),
4215 )),
4216 op: Operation::variadic(|_ecx, _e| {
4217 bail_unsupported!(format!("{} in this position", sef_builtin.name))
4218 }),
4219 }]),
4220 );
4221 }
4222
4223 builtins
4224});
4225
4226pub static INFORMATION_SCHEMA_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> =
4227 LazyLock::new(|| {
4228 use ParamType::*;
4229 builtins! {
4230 "_pg_expandarray" => Table {
4231 params!(ArrayAny) => sql_impl_table_func("
4235 SELECT
4236 $1[s] AS x,
4237 s - pg_catalog.array_lower($1, 1) + 1 AS n
4238 FROM pg_catalog.generate_series(
4239 pg_catalog.array_lower($1, 1),
4240 pg_catalog.array_upper($1, 1),
4241 1) as g(s)
4242 ") => ReturnType::set_of(RecordAny), oid::FUNC_PG_EXPAND_ARRAY;
4243 }
4244 }
4245 });
4246
4247pub static MZ_CATALOG_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
4248 use ParamType::*;
4249 use SqlScalarBaseType::*;
4250 builtins! {
4251 "constant_time_eq" => Scalar {
4252 params!(Bytes, Bytes) => BinaryFunc::from(func::ConstantTimeEqBytes)
4253 => Bool, oid::FUNC_CONSTANT_TIME_EQ_BYTES_OID;
4254 params!(String, String) => BinaryFunc::from(func::ConstantTimeEqString)
4255 => Bool, oid::FUNC_CONSTANT_TIME_EQ_STRING_OID;
4256 },
4257 "avg_internal_v1" => Scalar {
4265 params!(Int64) =>
4266 Operation::nullary(|_ecx| {
4267 catalog_name_only!("avg_internal_v1")
4268 }) => Numeric,
4269 oid::FUNC_AVG_INTERNAL_V1_INT64_OID;
4270 params!(Int32) =>
4271 Operation::nullary(|_ecx| {
4272 catalog_name_only!("avg_internal_v1")
4273 }) => Numeric,
4274 oid::FUNC_AVG_INTERNAL_V1_INT32_OID;
4275 params!(Int16) =>
4276 Operation::nullary(|_ecx| {
4277 catalog_name_only!("avg_internal_v1")
4278 }) => Numeric,
4279 oid::FUNC_AVG_INTERNAL_V1_INT16_OID;
4280 params!(UInt64) =>
4281 Operation::nullary(|_ecx| {
4282 catalog_name_only!("avg_internal_v1")
4283 }) => Numeric,
4284 oid::FUNC_AVG_INTERNAL_V1_UINT64_OID;
4285 params!(UInt32) =>
4286 Operation::nullary(|_ecx| {
4287 catalog_name_only!("avg_internal_v1")
4288 }) => Numeric,
4289 oid::FUNC_AVG_INTERNAL_V1_UINT32_OID;
4290 params!(UInt16) =>
4291 Operation::nullary(|_ecx| {
4292 catalog_name_only!("avg_internal_v1")
4293 }) => Numeric,
4294 oid::FUNC_AVG_INTERNAL_V1_UINT16_OID;
4295 params!(Float32) =>
4296 Operation::nullary(|_ecx| {
4297 catalog_name_only!("avg_internal_v1")
4298 }) => Float64,
4299 oid::FUNC_AVG_INTERNAL_V1_FLOAT32_OID;
4300 params!(Float64) =>
4301 Operation::nullary(|_ecx| {
4302 catalog_name_only!("avg_internal_v1")
4303 }) => Float64,
4304 oid::FUNC_AVG_INTERNAL_V1_FLOAT64_OID;
4305 params!(Interval) =>
4306 Operation::nullary(|_ecx| {
4307 catalog_name_only!("avg_internal_v1")
4308 }) => Interval,
4309 oid::FUNC_AVG_INTERNAL_V1_INTERVAL_OID;
4310 },
4311 "csv_extract" => Table {
4312 params!(Int64, String) => Operation::binary(move |_ecx, ncols, input| {
4313 const MAX_EXTRACT_COLUMNS: i64 = 8192;
4314 const TOO_MANY_EXTRACT_COLUMNS: i64 = MAX_EXTRACT_COLUMNS + 1;
4315
4316 let ncols = match ncols.into_literal_int64() {
4317 None | Some(i64::MIN..=0) => {
4318 sql_bail!(
4319 "csv_extract number of columns \
4320 must be a positive integer literal"
4321 );
4322 },
4323 Some(ncols @ 1..=MAX_EXTRACT_COLUMNS) => ncols,
4324 Some(ncols @ TOO_MANY_EXTRACT_COLUMNS..) => {
4325 return Err(PlanError::TooManyColumns {
4326 max_num_columns: usize::try_from(MAX_EXTRACT_COLUMNS)
4327 .unwrap_or(usize::MAX),
4328 req_num_columns: usize::try_from(ncols)
4329 .unwrap_or(usize::MAX),
4330 });
4331 },
4332 };
4333 let ncols = usize::try_from(ncols).expect("known to be greater than zero");
4334
4335 let column_names = (1..=ncols).map(|i| format!("column{}", i).into()).collect();
4336 Ok(TableFuncPlan {
4337 imp: TableFuncImpl::CallTable {
4338 func: TableFunc::CsvExtract(ncols),
4339 exprs: vec![input],
4340 },
4341 column_names,
4342 })
4343 }) => ReturnType::set_of(RecordAny), oid::FUNC_CSV_EXTRACT_OID;
4344 },
4345 "concat_agg" => Aggregate {
4346 params!(Any) => Operation::unary(|_ecx, _e| {
4347 bail_unsupported!("concat_agg")
4348 }) => String, oid::FUNC_CONCAT_AGG_OID;
4349 },
4350 "crc32" => Scalar {
4351 params!(String) => UnaryFunc::Crc32String(func::Crc32String)
4352 => UInt32, oid::FUNC_CRC32_STRING_OID;
4353 params!(Bytes) => UnaryFunc::Crc32Bytes(func::Crc32Bytes)
4354 => UInt32, oid::FUNC_CRC32_BYTES_OID;
4355 },
4356 "datediff" => Scalar {
4357 params!(String, Timestamp, Timestamp)
4358 => VariadicFunc::from(variadic::DateDiffTimestamp)
4359 => Int64, oid::FUNC_DATEDIFF_TIMESTAMP;
4360 params!(String, TimestampTz, TimestampTz)
4361 => VariadicFunc::from(variadic::DateDiffTimestampTz)
4362 => Int64, oid::FUNC_DATEDIFF_TIMESTAMPTZ;
4363 params!(String, Date, Date) => VariadicFunc::from(variadic::DateDiffDate)
4364 => Int64, oid::FUNC_DATEDIFF_DATE;
4365 params!(String, Time, Time) => VariadicFunc::from(variadic::DateDiffTime)
4366 => Int64, oid::FUNC_DATEDIFF_TIME;
4367 },
4368 "has_cluster_privilege" => Scalar {
4371 params!(String, String, String) => sql_impl_func(
4372 "has_cluster_privilege(mz_internal.mz_role_oid($1), $2, $3)",
4373 ) => Bool, oid::FUNC_HAS_CLUSTER_PRIVILEGE_TEXT_TEXT_TEXT_OID;
4374 params!(Oid, String, String) => sql_impl_func(&format!("
4375 CASE
4376 -- We must first check $2 to avoid a potentially
4377 -- null error message (an error itself).
4378 WHEN $2 IS NULL
4379 THEN NULL
4380 -- Validate the cluster name to return a proper error.
4381 WHEN NOT EXISTS (
4382 SELECT name FROM mz_clusters WHERE name = $2)
4383 THEN mz_unsafe.mz_error_if_null(
4384 NULL::boolean,
4385 'error cluster \"' || $2 || '\" does not exist')
4386 -- Validate the privileges and other arguments.
4387 WHEN NOT mz_internal.mz_validate_privileges($3)
4388 OR $1 IS NULL
4389 OR $3 IS NULL
4390 OR $1 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
4391 THEN NULL
4392 ELSE COALESCE(
4393 (
4394 SELECT
4395 bool_or(
4396 mz_internal.mz_acl_item_contains_privilege(privilege, $3)
4397 )
4398 AS has_cluster_privilege
4399 FROM
4400 (
4401 SELECT
4402 unnest(privileges)
4403 FROM
4404 mz_clusters
4405 WHERE
4406 mz_clusters.name = $2
4407 )
4408 AS user_privs (privilege)
4409 LEFT JOIN mz_catalog.mz_roles ON
4410 mz_internal.mz_aclitem_grantee(privilege) = mz_roles.id
4411 WHERE
4412 mz_internal.mz_aclitem_grantee(privilege) = '{}'
4413 OR pg_has_role($1, mz_roles.oid, 'USAGE')
4414 ),
4415 false
4416 )
4417 END
4418 ", RoleId::Public))
4419 => Bool, oid::FUNC_HAS_CLUSTER_PRIVILEGE_OID_TEXT_TEXT_OID;
4420 params!(String, String) => sql_impl_func(
4421 "has_cluster_privilege(current_user, $1, $2)",
4422 ) => Bool, oid::FUNC_HAS_CLUSTER_PRIVILEGE_TEXT_TEXT_OID;
4423 },
4424 "has_connection_privilege" => Scalar {
4425 params!(String, String, String) => sql_impl_func(
4426 "has_connection_privilege(\
4427 mz_internal.mz_role_oid($1), \
4428 mz_internal.mz_connection_oid($2), $3)",
4429 ) => Bool,
4430 oid::FUNC_HAS_CONNECTION_PRIVILEGE_TEXT_TEXT_TEXT_OID;
4431 params!(String, Oid, String) => sql_impl_func(
4432 "has_connection_privilege(mz_internal.mz_role_oid($1), $2, $3)",
4433 ) => Bool,
4434 oid::FUNC_HAS_CONNECTION_PRIVILEGE_TEXT_OID_TEXT_OID;
4435 params!(Oid, String, String) => sql_impl_func(
4436 "has_connection_privilege($1, mz_internal.mz_connection_oid($2), $3)",
4437 ) => Bool,
4438 oid::FUNC_HAS_CONNECTION_PRIVILEGE_OID_TEXT_TEXT_OID;
4439 params!(Oid, Oid, String) => sql_impl_func(
4440 &privilege_fn!("has_connection_privilege", "mz_connections"),
4441 ) => Bool,
4442 oid::FUNC_HAS_CONNECTION_PRIVILEGE_OID_OID_TEXT_OID;
4443 params!(String, String) => sql_impl_func(
4444 "has_connection_privilege(current_user, $1, $2)",
4445 ) => Bool,
4446 oid::FUNC_HAS_CONNECTION_PRIVILEGE_TEXT_TEXT_OID;
4447 params!(Oid, String) => sql_impl_func(
4448 "has_connection_privilege(current_user, $1, $2)",
4449 ) => Bool,
4450 oid::FUNC_HAS_CONNECTION_PRIVILEGE_OID_TEXT_OID;
4451 },
4452 "has_role" => Scalar {
4453 params!(String, String, String)
4454 => sql_impl_func("pg_has_role($1, $2, $3)")
4455 => Bool, oid::FUNC_HAS_ROLE_TEXT_TEXT_TEXT_OID;
4456 params!(String, Oid, String)
4457 => sql_impl_func("pg_has_role($1, $2, $3)")
4458 => Bool, oid::FUNC_HAS_ROLE_TEXT_OID_TEXT_OID;
4459 params!(Oid, String, String)
4460 => sql_impl_func("pg_has_role($1, $2, $3)")
4461 => Bool, oid::FUNC_HAS_ROLE_OID_TEXT_TEXT_OID;
4462 params!(Oid, Oid, String)
4463 => sql_impl_func("pg_has_role($1, $2, $3)")
4464 => Bool, oid::FUNC_HAS_ROLE_OID_OID_TEXT_OID;
4465 params!(String, String)
4466 => sql_impl_func("pg_has_role($1, $2)")
4467 => Bool, oid::FUNC_HAS_ROLE_TEXT_TEXT_OID;
4468 params!(Oid, String)
4469 => sql_impl_func("pg_has_role($1, $2)")
4470 => Bool, oid::FUNC_HAS_ROLE_OID_TEXT_OID;
4471 },
4472 "has_secret_privilege" => Scalar {
4473 params!(String, String, String) => sql_impl_func(
4474 "has_secret_privilege(\
4475 mz_internal.mz_role_oid($1), \
4476 mz_internal.mz_secret_oid($2), $3)",
4477 ) => Bool,
4478 oid::FUNC_HAS_SECRET_PRIVILEGE_TEXT_TEXT_TEXT_OID;
4479 params!(String, Oid, String) => sql_impl_func(
4480 "has_secret_privilege(mz_internal.mz_role_oid($1), $2, $3)",
4481 ) => Bool,
4482 oid::FUNC_HAS_SECRET_PRIVILEGE_TEXT_OID_TEXT_OID;
4483 params!(Oid, String, String) => sql_impl_func(
4484 "has_secret_privilege($1, mz_internal.mz_secret_oid($2), $3)",
4485 ) => Bool,
4486 oid::FUNC_HAS_SECRET_PRIVILEGE_OID_TEXT_TEXT_OID;
4487 params!(Oid, Oid, String) => sql_impl_func(
4488 &privilege_fn!("has_secret_privilege", "mz_secrets"),
4489 ) => Bool,
4490 oid::FUNC_HAS_SECRET_PRIVILEGE_OID_OID_TEXT_OID;
4491 params!(String, String) => sql_impl_func(
4492 "has_secret_privilege(current_user, $1, $2)",
4493 ) => Bool,
4494 oid::FUNC_HAS_SECRET_PRIVILEGE_TEXT_TEXT_OID;
4495 params!(Oid, String) => sql_impl_func(
4496 "has_secret_privilege(current_user, $1, $2)",
4497 ) => Bool,
4498 oid::FUNC_HAS_SECRET_PRIVILEGE_OID_TEXT_OID;
4499 },
4500 "has_system_privilege" => Scalar {
4501 params!(String, String) => sql_impl_func(
4502 "has_system_privilege(mz_internal.mz_role_oid($1), $2)",
4503 ) => Bool, oid::FUNC_HAS_SYSTEM_PRIVILEGE_TEXT_TEXT_OID;
4504 params!(Oid, String) => sql_impl_func(&format!("
4505 CASE
4506 -- We need to validate the privileges to return a proper error before
4507 -- anything else.
4508 WHEN NOT mz_internal.mz_validate_privileges($2)
4509 OR $1 IS NULL
4510 OR $2 IS NULL
4511 OR $1 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
4512 THEN NULL
4513 ELSE COALESCE(
4514 (
4515 SELECT
4516 bool_or(
4517 mz_internal.mz_acl_item_contains_privilege(privileges, $2)
4518 )
4519 AS has_system_privilege
4520 FROM mz_catalog.mz_system_privileges
4521 LEFT JOIN mz_catalog.mz_roles ON
4522 mz_internal.mz_aclitem_grantee(privileges) = mz_roles.id
4523 WHERE
4524 mz_internal.mz_aclitem_grantee(privileges) = '{}'
4525 OR pg_has_role($1, mz_roles.oid, 'USAGE')
4526 ),
4527 false
4528 )
4529 END
4530 ", RoleId::Public))
4531 => Bool, oid::FUNC_HAS_SYSTEM_PRIVILEGE_OID_TEXT_OID;
4532 params!(String) => sql_impl_func(
4533 "has_system_privilege(current_user, $1)",
4534 ) => Bool, oid::FUNC_HAS_SYSTEM_PRIVILEGE_TEXT_OID;
4535 },
4536 "has_type_privilege" => Scalar {
4537 params!(String, String, String) => sql_impl_func(
4538 "has_type_privilege(mz_internal.mz_role_oid($1), $2::regtype::oid, $3)",
4539 ) => Bool, 3138;
4540 params!(String, Oid, String) => sql_impl_func(
4541 "has_type_privilege(mz_internal.mz_role_oid($1), $2, $3)",
4542 ) => Bool, 3139;
4543 params!(Oid, String, String) => sql_impl_func(
4544 "has_type_privilege($1, $2::regtype::oid, $3)",
4545 ) => Bool, 3140;
4546 params!(Oid, Oid, String) => sql_impl_func(
4547 &privilege_fn!("has_type_privilege", "mz_types"),
4548 ) => Bool, 3141;
4549 params!(String, String) => sql_impl_func(
4550 "has_type_privilege(current_user, $1, $2)",
4551 ) => Bool, 3142;
4552 params!(Oid, String) => sql_impl_func(
4553 "has_type_privilege(current_user, $1, $2)",
4554 ) => Bool, 3143;
4555 },
4556 "jq" => Scalar {
4557 params!(Jsonb, String) => Operation::binary(|ecx, input, program| {
4558 ecx.require_feature_flag(&vars::ENABLE_JQ)?;
4559 let Some(program) = program.into_literal_string() else {
4560 sql_bail!("jq requires a string literal as its second argument");
4561 };
4562 let program = func::JqProgram::new(&program).map_err(|e| sql_err!("jq: {e}"))?;
4563 Ok(input.call_unary(UnaryFunc::Jq(func::Jq(program))))
4564 }) => Jsonb, oid::FUNC_JQ_OID;
4565 },
4566 "kafka_murmur2" => Scalar {
4567 params!(String) => UnaryFunc::KafkaMurmur2String(func::KafkaMurmur2String)
4568 => Int32, oid::FUNC_KAFKA_MURMUR2_STRING_OID;
4569 params!(Bytes) => UnaryFunc::KafkaMurmur2Bytes(func::KafkaMurmur2Bytes)
4570 => Int32, oid::FUNC_KAFKA_MURMUR2_BYTES_OID;
4571 },
4572 "list_agg" => Aggregate {
4573 params!(Any) => Operation::unary_ordered(|ecx, e, order_by| {
4574 if let SqlScalarType::Char {.. } = ecx.scalar_type(&e) {
4575 bail_unsupported!("list_agg on char");
4576 };
4577 let e_arr = HirScalarExpr::call_variadic(
4580 variadic::ListCreate { elem_type: ecx.scalar_type(&e) },
4581 vec![e],
4582 );
4583 Ok((e_arr, AggregateFunc::ListConcat { order_by }))
4584 }) => ListAnyCompatible, oid::FUNC_LIST_AGG_OID;
4585 },
4586 "list_append" => Scalar {
4587 vec![ListAnyCompatible, ListElementAnyCompatible]
4588 => BinaryFunc::from(func::ListElementConcat)
4589 => ListAnyCompatible, oid::FUNC_LIST_APPEND_OID;
4590 },
4591 "list_cat" => Scalar {
4592 vec![ListAnyCompatible, ListAnyCompatible]
4593 => BinaryFunc::from(func::ListListConcat)
4594 => ListAnyCompatible, oid::FUNC_LIST_CAT_OID;
4595 },
4596 "list_n_layers" => Scalar {
4597 vec![ListAny] => Operation::unary(|ecx, e| {
4598 ecx.require_feature_flag(&vars::ENABLE_LIST_N_LAYERS)?;
4599 let d = ecx.scalar_type(&e).unwrap_list_n_layers();
4600 match i32::try_from(d) {
4601 Ok(d) => Ok(HirScalarExpr::literal(Datum::Int32(d), SqlScalarType::Int32)),
4602 Err(_) => sql_bail!("list has more than {} layers", i32::MAX),
4603 }
4604
4605 }) => Int32, oid::FUNC_LIST_N_LAYERS_OID;
4606 },
4607 "list_length" => Scalar {
4608 vec![ListAny] => UnaryFunc::ListLength(func::ListLength)
4609 => Int32, oid::FUNC_LIST_LENGTH_OID;
4610 },
4611 "list_length_max" => Scalar {
4612 vec![ListAny, Plain(SqlScalarType::Int64)] => Operation::binary(|ecx, lhs, rhs| {
4613 ecx.require_feature_flag(&vars::ENABLE_LIST_LENGTH_MAX)?;
4614 let max_layer = ecx.scalar_type(&lhs).unwrap_list_n_layers();
4615 Ok(lhs.call_binary(rhs, BinaryFunc::from(func::ListLengthMax { max_layer })))
4616 }) => Int32, oid::FUNC_LIST_LENGTH_MAX_OID;
4617 },
4618 "list_prepend" => Scalar {
4619 vec![ListElementAnyCompatible, ListAnyCompatible]
4620 => BinaryFunc::from(func::ElementListConcat)
4621 => ListAnyCompatible, oid::FUNC_LIST_PREPEND_OID;
4622 },
4623 "list_remove" => Scalar {
4624 vec![ListAnyCompatible, ListElementAnyCompatible] => Operation::binary(|ecx, lhs, rhs| {
4625 ecx.require_feature_flag(&vars::ENABLE_LIST_REMOVE)?;
4626 Ok(lhs.call_binary(rhs, func::ListRemove))
4627 }) => ListAnyCompatible, oid::FUNC_LIST_REMOVE_OID;
4628 },
4629 "map_agg" => Aggregate {
4630 params!(String, Any) => Operation::binary_ordered(|ecx, key, val, order_by| {
4631 let (value_type, val) = match ecx.scalar_type(&val) {
4632 SqlScalarType::Char { length } => (
4634 SqlScalarType::Char { length },
4635 val.call_unary(UnaryFunc::PadChar(func::PadChar { length })),
4636 ),
4637 typ => (typ, val),
4638 };
4639
4640 let e = HirScalarExpr::call_variadic(
4641 variadic::RecordCreate {
4642 field_names: vec![ColumnName::from("key"), ColumnName::from("val")],
4643 },
4644 vec![key, val],
4645 );
4646
4647 Ok((e, AggregateFunc::MapAgg { order_by, value_type }))
4648 }) => MapAny, oid::FUNC_MAP_AGG;
4649 },
4650 "map_build" => Scalar {
4651 params!(ListAny) => Operation::unary(|ecx, expr| {
4662 let ty = ecx.scalar_type(&expr);
4663
4664 let err = || {
4667 Err(sql_err!(
4668 "function map_build({}) does not exist",
4669 ecx.humanize_sql_scalar_type(&ty.clone(), false)
4670 ))
4671 };
4672
4673 let value_type = match &ty {
4676 SqlScalarType::List { element_type, .. } => match &**element_type {
4677 SqlScalarType::Record { fields, .. } if fields.len() == 2 => {
4678 if fields[0].1.scalar_type != SqlScalarType::String {
4679 return err();
4680 }
4681
4682 fields[1].1.scalar_type.clone()
4683 }
4684 _ => return err(),
4685 },
4686 _ => unreachable!("input guaranteed to be list"),
4687 };
4688
4689 Ok(expr.call_unary(UnaryFunc::MapBuildFromRecordList(
4690 func::MapBuildFromRecordList { value_type },
4691 )))
4692 }) => MapAny, oid::FUNC_MAP_BUILD;
4693 },
4694 "map_length" => Scalar {
4695 params![MapAny] => UnaryFunc::MapLength(func::MapLength)
4696 => Int32, oid::FUNC_MAP_LENGTH_OID;
4697 },
4698 "mz_environment_id" => Scalar {
4712 params!() => Operation::nullary(|ecx| {
4713 let env_id = ecx.catalog().config().environment_id.to_string();
4714 Ok(HirScalarExpr::literal(
4715 Datum::String(&env_id),
4716 SqlScalarType::String,
4717 ))
4718 }) => String, oid::FUNC_MZ_ENVIRONMENT_ID_OID;
4719 },
4720 "mz_aws_account_id" => Scalar {
4736 params!() => Operation::nullary(|ecx| {
4737 Ok(match &ecx.catalog().config().aws_account_id {
4738 Some(account_id) => {
4739 HirScalarExpr::literal(Datum::String(account_id), SqlScalarType::String)
4740 }
4741 None => HirScalarExpr::literal_null(SqlScalarType::String),
4742 })
4743 }) => String, oid::FUNC_MZ_AWS_ACCOUNT_ID_OID;
4744 },
4745 "mz_aws_external_id_prefix" => Scalar {
4746 params!() => Operation::nullary(|ecx| {
4747 let prefix = ecx
4748 .catalog()
4749 .config()
4750 .connection_context
4751 .aws_external_id_prefix
4752 .as_ref()
4753 .map(|p| p.to_string());
4754 Ok(match prefix {
4755 Some(prefix) => {
4756 HirScalarExpr::literal(Datum::String(&prefix), SqlScalarType::String)
4757 }
4758 None => HirScalarExpr::literal_null(SqlScalarType::String),
4759 })
4760 }) => String, oid::FUNC_MZ_AWS_EXTERNAL_ID_PREFIX_OID;
4761 },
4762 "mz_aws_connection_role_arn" => Scalar {
4763 params!() => Operation::nullary(|ecx| {
4764 Ok(match &ecx.catalog().config().connection_context.aws_connection_role_arn {
4765 Some(arn) => HirScalarExpr::literal(Datum::String(arn), SqlScalarType::String),
4766 None => HirScalarExpr::literal_null(SqlScalarType::String),
4767 })
4768 }) => String, oid::FUNC_MZ_AWS_CONNECTION_ROLE_ARN_OID;
4769 },
4770 "mz_is_superuser" => Scalar {
4771 params!() => UnmaterializableFunc::MzIsSuperuser
4772 => SqlScalarType::Bool, oid::FUNC_MZ_IS_SUPERUSER;
4773 },
4774 "mz_logical_timestamp" => Scalar {
4775 params!() => Operation::nullary(|_ecx| {
4776 sql_bail!("mz_logical_timestamp() has been renamed to mz_now()")
4777 }) => MzTimestamp, oid::FUNC_MZ_LOGICAL_TIMESTAMP_OID;
4778 },
4779 "mz_now" => Scalar {
4780 params!() => UnmaterializableFunc::MzNow => MzTimestamp, oid::FUNC_MZ_NOW_OID;
4781 },
4782 "mz_session_role_memberships" => Scalar {
4783 params!() => UnmaterializableFunc::MzSessionRoleMemberships
4784 => SqlScalarType::Array(Box::new(SqlScalarType::String)),
4785 oid::FUNC_MZ_SESSION_ROLE_MEMBERSHIPS_OID;
4786 },
4787 "mz_uptime" => Scalar {
4788 params!() => UnmaterializableFunc::MzUptime => Interval, oid::FUNC_MZ_UPTIME_OID;
4789 },
4790 "mz_version" => Scalar {
4791 params!() => UnmaterializableFunc::MzVersion => String, oid::FUNC_MZ_VERSION_OID;
4792 },
4793 "mz_version_num" => Scalar {
4794 params!() => UnmaterializableFunc::MzVersionNum => Int32, oid::FUNC_MZ_VERSION_NUM_OID;
4795 },
4796 "pretty_sql" => Scalar {
4797 params!(String, Int32) => BinaryFunc::from(func::PrettySql)
4798 => String, oid::FUNC_PRETTY_SQL;
4799 params!(String) => Operation::unary(|_ecx, s| {
4800 let w: i32 = mz_sql_pretty::DEFAULT_WIDTH.try_into().expect("must fit");
4801 let width = HirScalarExpr::literal(Datum::Int32(w), SqlScalarType::Int32);
4802 Ok(s.call_binary(width, func::PrettySql))
4803 }) => String, oid::FUNC_PRETTY_SQL_NOWIDTH;
4804 },
4805 "regexp_extract" => Table {
4806 params!(String, String) => Operation::binary(move |_ecx, regex, haystack| {
4807 let regex = match regex.into_literal_string() {
4808 None => sql_bail!(
4809 "regexp_extract requires a string \
4810 literal as its first argument"
4811 ),
4812 Some(regex) => {
4813 let opts = mz_expr::AnalyzedRegexOpts::default();
4814 mz_expr::AnalyzedRegex::new(®ex, opts)
4815 .map_err(|e| {
4816 sql_err!("analyzing regex: {}", e)
4817 })?
4818 },
4819 };
4820 let column_names = regex
4821 .capture_groups_iter()
4822 .map(|cg| {
4823 cg.name.clone().unwrap_or_else(|| format!("column{}", cg.index)).into()
4824 })
4825 .collect::<Vec<_>>();
4826 if column_names.is_empty(){
4827 sql_bail!("regexp_extract must specify at least one capture group");
4828 }
4829 Ok(TableFuncPlan {
4830 imp: TableFuncImpl::CallTable {
4831 func: TableFunc::RegexpExtract(regex),
4832 exprs: vec![haystack],
4833 },
4834 column_names,
4835 })
4836 }) => ReturnType::set_of(RecordAny), oid::FUNC_REGEXP_EXTRACT_OID;
4837 },
4838 mz_expr::REPEAT_ROW_NAME => Table {
4839 params!(Int64) => Operation::unary(move |ecx, n| {
4840 ecx.require_feature_flag(&vars::ENABLE_REPEAT_ROW)?;
4841 Ok(TableFuncPlan {
4842 imp: TableFuncImpl::CallTable {
4843 func: TableFunc::RepeatRow,
4844 exprs: vec![n],
4845 },
4846 column_names: vec![]
4847 })
4848 }) => ReturnType::none(true), oid::FUNC_REPEAT_ROW_OID;
4849 },
4850 "repeat_row_non_negative" => Table {
4851 params!(Int64) => Operation::unary(move |ecx, n| {
4852 ecx.require_feature_flag(&vars::ENABLE_REPEAT_ROW_NON_NEGATIVE)?;
4853 Ok(TableFuncPlan {
4854 imp: TableFuncImpl::CallTable {
4855 func: TableFunc::RepeatRowNonNegative,
4856 exprs: vec![n],
4857 },
4858 column_names: vec![]
4859 })
4860 }) => ReturnType::none(true), oid::FUNC_REPEAT_ROW_NON_NEGATIVE_OID;
4861 },
4862 "seahash" => Scalar {
4863 params!(String) => UnaryFunc::SeahashString(func::SeahashString)
4864 => UInt64, oid::FUNC_SEAHASH_STRING_OID;
4865 params!(Bytes) => UnaryFunc::SeahashBytes(func::SeahashBytes)
4866 => UInt64, oid::FUNC_SEAHASH_BYTES_OID;
4867 },
4868 "starts_with" => Scalar {
4869 params!(String, String) => BinaryFunc::from(func::StartsWith) => Bool, 3696;
4870 },
4871 "timezone_offset" => Scalar {
4872 params!(String, TimestampTz) => BinaryFunc::from(func::TimezoneOffset)
4873 => RecordAny, oid::FUNC_TIMEZONE_OFFSET;
4874 },
4875 "try_parse_monotonic_iso8601_timestamp" => Scalar {
4876 params!(String) => Operation::unary(move |_ecx, e| {
4877 Ok(e.call_unary(UnaryFunc::TryParseMonotonicIso8601Timestamp(
4878 func::TryParseMonotonicIso8601Timestamp,
4879 )))
4880 }) => Timestamp, oid::FUNC_TRY_PARSE_MONOTONIC_ISO8601_TIMESTAMP;
4881 },
4882 "unnest" => Table {
4883 vec![ArrayAny] => Operation::unary(move |ecx, e| {
4884 let el_typ = ecx.scalar_type(&e).unwrap_array_element_type().clone();
4885 Ok(TableFuncPlan {
4886 imp: TableFuncImpl::CallTable {
4887 func: TableFunc::UnnestArray { el_typ },
4888 exprs: vec![e],
4889 },
4890 column_names: vec!["unnest".into()],
4891 })
4892 }) =>
4893 ReturnType::set_of(AnyElement), 2331;
4896 vec![ListAny] => Operation::unary(move |ecx, e| {
4897 let el_typ = ecx.scalar_type(&e).unwrap_list_element_type().clone();
4898 Ok(TableFuncPlan {
4899 imp: TableFuncImpl::CallTable {
4900 func: TableFunc::UnnestList { el_typ },
4901 exprs: vec![e],
4902 },
4903 column_names: vec!["unnest".into()],
4904 })
4905 }) =>
4906 ReturnType::set_of(Any), oid::FUNC_UNNEST_LIST_OID;
4909 vec![MapAny] => Operation::unary(move |ecx, e| {
4910 let value_type = ecx.scalar_type(&e).unwrap_map_value_type().clone();
4911 Ok(TableFuncPlan {
4912 imp: TableFuncImpl::CallTable {
4913 func: TableFunc::UnnestMap { value_type },
4914 exprs: vec![e],
4915 },
4916 column_names: vec!["key".into(), "value".into()],
4917 })
4918 }) =>
4919 ReturnType::set_of(Any), oid::FUNC_UNNEST_MAP_OID;
4922 }
4923 }
4924});
4925
4926pub static MZ_INTERNAL_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
4927 use ParamType::*;
4928 use SqlScalarBaseType::*;
4929 builtins! {
4930 "aclitem_grantor" => Scalar {
4931 params!(AclItem) => UnaryFunc::AclItemGrantor(func::AclItemGrantor)
4932 => Oid, oid::FUNC_ACL_ITEM_GRANTOR_OID;
4933 },
4934 "aclitem_grantee" => Scalar {
4935 params!(AclItem) => UnaryFunc::AclItemGrantee(func::AclItemGrantee)
4936 => Oid, oid::FUNC_ACL_ITEM_GRANTEE_OID;
4937 },
4938 "aclitem_privileges" => Scalar {
4939 params!(AclItem) => UnaryFunc::AclItemPrivileges(func::AclItemPrivileges)
4940 => String, oid::FUNC_ACL_ITEM_PRIVILEGES_OID;
4941 },
4942 "is_rbac_enabled" => Scalar {
4943 params!() => UnmaterializableFunc::IsRbacEnabled => Bool, oid::FUNC_IS_RBAC_ENABLED_OID;
4944 },
4945 "make_mz_aclitem" => Scalar {
4946 params!(String, String, String) => VariadicFunc::from(variadic::MakeMzAclItem)
4947 => MzAclItem, oid::FUNC_MAKE_MZ_ACL_ITEM_OID;
4948 },
4949 "mz_acl_item_contains_privilege" => Scalar {
4950 params!(MzAclItem, String)
4951 => BinaryFunc::from(func::MzAclItemContainsPrivilege)
4952 => Bool, oid::FUNC_MZ_ACL_ITEM_CONTAINS_PRIVILEGE_OID;
4953 },
4954 "mz_aclexplode" => Table {
4955 params!(SqlScalarType::Array(Box::new(SqlScalarType::MzAclItem)))
4956 => Operation::unary(move |_ecx, mz_aclitems| {
4957 Ok(TableFuncPlan {
4958 imp: TableFuncImpl::CallTable {
4959 func: TableFunc::MzAclExplode,
4960 exprs: vec![mz_aclitems],
4961 },
4962 column_names: vec![
4963 "grantor".into(), "grantee".into(),
4964 "privilege_type".into(), "is_grantable".into(),
4965 ],
4966 })
4967 }) => ReturnType::set_of(RecordAny), oid::FUNC_MZ_ACL_ITEM_EXPLODE_OID;
4968 },
4969 "mz_aclitem_grantor" => Scalar {
4970 params!(MzAclItem) => UnaryFunc::MzAclItemGrantor(func::MzAclItemGrantor)
4971 => String, oid::FUNC_MZ_ACL_ITEM_GRANTOR_OID;
4972 },
4973 "mz_aclitem_grantee" => Scalar {
4974 params!(MzAclItem) => UnaryFunc::MzAclItemGrantee(func::MzAclItemGrantee)
4975 => String, oid::FUNC_MZ_ACL_ITEM_GRANTEE_OID;
4976 },
4977 "mz_aclitem_privileges" => Scalar {
4978 params!(MzAclItem) => UnaryFunc::MzAclItemPrivileges(
4979 func::MzAclItemPrivileges,
4980 ) => String, oid::FUNC_MZ_ACL_ITEM_PRIVILEGES_OID;
4981 },
4982 "mz_connection_oid" => Scalar {
4987 params!(String) => sql_impl_func("
4988 CASE
4989 WHEN $1 IS NULL THEN NULL
4990 ELSE (
4991 mz_unsafe.mz_error_if_null(
4992 (SELECT oid FROM mz_catalog.mz_objects
4993 WHERE name = $1 AND type = 'connection'),
4994 'connection \"' || $1 || '\" does not exist'
4995 )
4996 )
4997 END
4998 ") => Oid, oid::FUNC_CONNECTION_OID_OID;
4999 },
5000 "mz_format_privileges" => Scalar {
5001 params!(String) => UnaryFunc::MzFormatPrivileges(func::MzFormatPrivileges)
5002 => SqlScalarType::Array(Box::new(SqlScalarType::String)),
5003 oid::FUNC_MZ_FORMAT_PRIVILEGES_OID;
5004 },
5005 "mz_name_rank" => Table {
5006 params!(
5009 String,
5011 ParamType::Plain(SqlScalarType::Array(Box::new(SqlScalarType::String))),
5013 String,
5015 String
5017 ) =>
5018 sql_impl_table_func("
5020 -- The best ranked name is the one that belongs to the schema correlated with the lowest
5021 -- index in the search path
5022 SELECT id, name, count, min(schema_pref) OVER () = schema_pref AS best_ranked FROM (
5023 SELECT DISTINCT
5024 o.id,
5025 ARRAY[CASE WHEN s.database_id IS NULL THEN NULL ELSE d.name END, s.name, o.name]
5026 AS name,
5027 o.count,
5028 pg_catalog.array_position($2, s.name) AS schema_pref
5029 FROM
5030 (
5031 SELECT
5032 o.id,
5033 o.schema_id,
5034 o.name,
5035 count(*)
5036 FROM mz_catalog.mz_objects AS o
5037 JOIN mz_internal.mz_object_oid_alias AS a
5038 ON o.type = a.object_type
5039 WHERE o.name = CAST($3 AS pg_catalog.text) AND a.oid_alias = $4
5040 GROUP BY 1, 2, 3
5041 )
5042 AS o
5043 JOIN mz_catalog.mz_schemas AS s ON o.schema_id = s.id
5044 JOIN
5045 unnest($2) AS search_schema (name)
5046 ON search_schema.name = s.name
5047 JOIN
5048 (
5049 SELECT id, name FROM mz_catalog.mz_databases
5050 -- If the provided database does not exist, add a row for it so that it
5051 -- can still join against ambient schemas.
5052 UNION ALL
5053 SELECT '', $1 WHERE $1 NOT IN (SELECT name FROM mz_catalog.mz_databases)
5054 ) AS d
5055 ON d.id = COALESCE(s.database_id, d.id)
5056 WHERE d.name = CAST($1 AS pg_catalog.text)
5057 );
5058 ") => ReturnType::set_of(RecordAny), oid::FUNC_MZ_NAME_RANK;
5059 },
5060 "mz_resolve_object_name" => Table {
5061 params!(String, String) =>
5062 sql_impl_table_func("
5065 SELECT
5066 o.id, o.oid, o.schema_id, o.name, o.type, o.owner_id, o.privileges
5067 FROM
5068 (SELECT mz_internal.mz_normalize_object_name($2))
5069 AS normalized (n),
5070 mz_internal.mz_name_rank(
5071 COALESCE(n[1], pg_catalog.current_database()),
5072 CASE
5073 WHEN n[2] IS NULL
5074 THEN pg_catalog.current_schemas(true)
5075 ELSE
5076 ARRAY[n[2]]
5077 END,
5078 n[3],
5079 $1
5080 ) AS r,
5081 mz_catalog.mz_objects AS o
5082 WHERE r.id = o.id AND r.best_ranked;
5083 ") => ReturnType::set_of(RecordAny), oid::FUNC_MZ_RESOLVE_OBJECT_NAME;
5084 },
5085 "mz_minimal_name_qualification" => Scalar {
5097 params!(SqlScalarType::Array(Box::new(SqlScalarType::String)), String) => {
5098 sql_impl_func("(
5099 SELECT
5100 CASE
5101 WHEN $1::pg_catalog.text[] IS NULL
5102 THEN NULL
5103 -- If DB doesn't match, requires full qual
5104 WHEN $1[1] != pg_catalog.current_database()
5105 THEN $1
5106 -- If not in currently searchable schema, must be schema qualified
5107 WHEN NOT $1[2] = ANY(pg_catalog.current_schemas(true))
5108 THEN ARRAY[$1[2], $1[3]]
5109 ELSE
5110 minimal_name
5111 END
5112 FROM (
5113 -- Subquery so we return one null row in the cases where
5114 -- there are no matches.
5115 SELECT (
5116 SELECT DISTINCT
5117 CASE
5118 -- If there is only one item with this name and it's rank 1,
5119 -- it is uniquely nameable with just the final element
5120 WHEN best_ranked AND count = 1
5121 THEN ARRAY[r.name[3]]
5122 -- Otherwise, it is findable in the search path, so does not
5123 -- need database qualification
5124 ELSE
5125 ARRAY[r.name[2], r.name[3]]
5126 END AS minimal_name
5127 FROM mz_catalog.mz_objects AS o
5128 JOIN mz_internal.mz_object_oid_alias AS a
5129 ON o.type = a.object_type,
5130 -- implied lateral to put the OID alias into scope
5131 mz_internal.mz_name_rank(
5132 pg_catalog.current_database(),
5133 pg_catalog.current_schemas(true),
5134 $1[3],
5135 a.oid_alias
5136 ) AS r
5137 WHERE o.id = $2 AND r.id = $2
5138 )
5139 )
5140 )")
5141 } => SqlScalarType::Array(Box::new(SqlScalarType::String)),
5142 oid::FUNC_MZ_MINIMINAL_NAME_QUALIFICATION;
5143 },
5144 "mz_global_id_to_name" => Scalar {
5145 params!(String) => sql_impl_func("
5146 CASE
5147 WHEN $1 IS NULL THEN NULL
5148 ELSE (
5149 SELECT array_to_string(minimal_name, '.')
5150 FROM (
5151 SELECT mz_unsafe.mz_error_if_null(
5152 (
5153 -- Return the fully-qualified name
5154 SELECT DISTINCT ARRAY[qual.d, qual.s, item.name]
5155 FROM
5156 mz_catalog.mz_objects AS item
5157 JOIN
5158 (
5159 SELECT
5160 d.name AS d,
5161 s.name AS s,
5162 s.id AS schema_id
5163 FROM
5164 mz_catalog.mz_schemas AS s
5165 LEFT JOIN
5166 (SELECT id, name FROM mz_catalog.mz_databases)
5167 AS d
5168 ON s.database_id = d.id
5169 ) AS qual
5170 ON qual.schema_id = item.schema_id
5171 WHERE item.id = CAST($1 AS text)
5172 ),
5173 'global ID ' || $1 || ' does not exist'
5174 )
5175 ) AS n (fqn),
5176 LATERAL (
5177 -- Get the minimal qualification of the fully qualified name
5178 SELECT mz_internal.mz_minimal_name_qualification(fqn, $1)
5179 ) AS m (minimal_name)
5180 )
5181 END
5182 ") => String, oid::FUNC_MZ_GLOBAL_ID_TO_NAME;
5183 },
5184 "mz_normalize_object_name" => Scalar {
5185 params!(String) => sql_impl_func("
5186 (
5187 SELECT
5188 CASE
5189 WHEN $1 IS NULL OR ident IS NULL THEN NULL
5190 WHEN pg_catalog.array_length(ident, 1) > 3
5191 THEN mz_unsafe.mz_error_if_null(
5192 NULL::pg_catalog.text[],
5193 'improper relation name (too many dotted names): ' || $1
5194 )
5195 ELSE pg_catalog.array_cat(
5196 pg_catalog.array_fill(
5197 CAST(NULL AS pg_catalog.text),
5198 ARRAY[3 - pg_catalog.array_length(ident, 1)]
5199 ),
5200 ident
5201 )
5202 END
5203 FROM (
5204 SELECT pg_catalog.parse_ident($1) AS ident
5205 ) AS i
5206 )") => SqlScalarType::Array(Box::new(SqlScalarType::String)),
5207 oid::FUNC_MZ_NORMALIZE_OBJECT_NAME;
5208 },
5209 "mz_normalize_schema_name" => Scalar {
5210 params!(String) => sql_impl_func("
5211 (
5212 SELECT
5213 CASE
5214 WHEN $1 IS NULL OR ident IS NULL THEN NULL
5215 WHEN pg_catalog.array_length(ident, 1) > 2
5216 THEN mz_unsafe.mz_error_if_null(
5217 NULL::pg_catalog.text[],
5218 'improper schema name (too many dotted names): ' || $1
5219 )
5220 ELSE pg_catalog.array_cat(
5221 pg_catalog.array_fill(
5222 CAST(NULL AS pg_catalog.text),
5223 ARRAY[2 - pg_catalog.array_length(ident, 1)]
5224 ),
5225 ident
5226 )
5227 END
5228 FROM (
5229 SELECT pg_catalog.parse_ident($1) AS ident
5230 ) AS i
5231 )") => SqlScalarType::Array(Box::new(SqlScalarType::String)),
5232 oid::FUNC_MZ_NORMALIZE_SCHEMA_NAME;
5233 },
5234 "mz_render_typmod" => Scalar {
5235 params!(Oid, Int32) => BinaryFunc::from(func::MzRenderTypmod)
5236 => String, oid::FUNC_MZ_RENDER_TYPMOD_OID;
5237 },
5238 "mz_role_oid_memberships" => Scalar {
5239 params!() => UnmaterializableFunc::MzRoleOidMemberships
5240 => SqlScalarType::Map {
5241 value_type: Box::new(SqlScalarType::Array(
5242 Box::new(SqlScalarType::String),
5243 )),
5244 custom_id: None,
5245 }, oid::FUNC_MZ_ROLE_OID_MEMBERSHIPS;
5246 },
5247 "mz_database_oid" => Scalar {
5250 params!(String) => sql_impl_func("
5251 CASE
5252 WHEN $1 IS NULL THEN NULL
5253 ELSE (
5254 mz_unsafe.mz_error_if_null(
5255 (SELECT oid FROM mz_databases WHERE name = $1),
5256 'database \"' || $1 || '\" does not exist'
5257 )
5258 )
5259 END
5260 ") => Oid, oid::FUNC_DATABASE_OID_OID;
5261 },
5262 "mz_schema_oid" => Scalar {
5265 params!(String) => sql_impl_func("
5266 CASE
5267 WHEN $1 IS NULL THEN NULL
5268 ELSE
5269 mz_unsafe.mz_error_if_null(
5270 (
5271 SELECT
5272 (
5273 SELECT s.oid
5274 FROM mz_catalog.mz_schemas AS s
5275 LEFT JOIN mz_databases AS d ON s.database_id = d.id
5276 WHERE
5277 (
5278 -- Filter to only schemas in the named database or the
5279 -- current database if no database was specified.
5280 d.name = COALESCE(n[1], pg_catalog.current_database())
5281 -- Always include all ambient schemas.
5282 OR s.database_id IS NULL
5283 )
5284 AND s.name = n[2]
5285 )
5286 FROM mz_internal.mz_normalize_schema_name($1) AS n
5287 ),
5288 'schema \"' || $1 || '\" does not exist'
5289 )
5290 END
5291 ") => Oid, oid::FUNC_SCHEMA_OID_OID;
5292 },
5293 "mz_role_oid" => Scalar {
5296 params!(String) => sql_impl_func("
5297 CASE
5298 WHEN $1 IS NULL THEN NULL
5299 ELSE (
5300 mz_unsafe.mz_error_if_null(
5301 (SELECT oid FROM mz_catalog.mz_roles WHERE name = $1),
5302 'role \"' || $1 || '\" does not exist'
5303 )
5304 )
5305 END
5306 ") => Oid, oid::FUNC_ROLE_OID_OID;
5307 },
5308 "mz_secret_oid" => Scalar {
5313 params!(String) => sql_impl_func("
5314 CASE
5315 WHEN $1 IS NULL THEN NULL
5316 ELSE (
5317 mz_unsafe.mz_error_if_null(
5318 (SELECT oid FROM mz_catalog.mz_objects WHERE name = $1 AND type = 'secret'),
5319 'secret \"' || $1 || '\" does not exist'
5320 )
5321 )
5322 END
5323 ") => Oid, oid::FUNC_SECRET_OID_OID;
5324 },
5325 "mz_session_id" => Scalar {
5329 params!() => UnmaterializableFunc::MzSessionId => Uuid, oid::FUNC_MZ_SESSION_ID_OID;
5330 },
5331 "mz_type_name" => Scalar {
5332 params!(Oid) => UnaryFunc::MzTypeName(func::MzTypeName)
5333 => String, oid::FUNC_MZ_TYPE_NAME;
5334 },
5335 "mz_validate_privileges" => Scalar {
5336 params!(String) => UnaryFunc::MzValidatePrivileges(func::MzValidatePrivileges)
5337 => Bool, oid::FUNC_MZ_VALIDATE_PRIVILEGES_OID;
5338 },
5339 "mz_validate_role_privilege" => Scalar {
5340 params!(String) => UnaryFunc::MzValidateRolePrivilege(
5341 func::MzValidateRolePrivilege,
5342 ) => Bool, oid::FUNC_MZ_VALIDATE_ROLE_PRIVILEGE_OID;
5343 },
5344 "parse_catalog_acl_mode" => Scalar {
5345 params!(Jsonb) => UnaryFunc::ParseCatalogAclMode(func::ParseCatalogAclMode)
5346 => String, oid::FUNC_PARSE_CATALOG_ACL_MODE_OID;
5347 },
5348 "parse_catalog_audit_log_details" => Scalar {
5349 params!(Jsonb) => UnaryFunc::ParseCatalogAuditLogDetails(
5350 func::ParseCatalogAuditLogDetails,
5351 ) => Jsonb, oid::FUNC_PARSE_CATALOG_AUDIT_LOG_DETAILS_OID;
5352 },
5353 "parse_catalog_create_sql" => Scalar {
5354 params!(String) => UnaryFunc::ParseCatalogCreateSql(func::ParseCatalogCreateSql)
5355 => Jsonb, oid::FUNC_PARSE_CATALOG_CREATE_SQL_OID;
5356 },
5357 "parse_catalog_id" => Scalar {
5358 params!(Jsonb) => UnaryFunc::ParseCatalogId(func::ParseCatalogId)
5359 => String, oid::FUNC_PARSE_CATALOG_ID_OID;
5360 },
5361 "parse_catalog_item_references" => Scalar {
5362 params!(String) => UnaryFunc::ParseCatalogItemReferences(
5363 func::ParseCatalogItemReferences,
5364 ) => Jsonb, oid::FUNC_PARSE_CATALOG_ITEM_REFERENCES_OID;
5365 },
5366 "parse_catalog_privileges" => Scalar {
5367 params!(Jsonb) => UnaryFunc::ParseCatalogPrivileges(func::ParseCatalogPrivileges)
5368 => SqlScalarType::Array(Box::new(SqlScalarType::MzAclItem)),
5369 oid::FUNC_PARSE_CATALOG_PRIVILEGES_OID;
5370 },
5371 "parse_kafka_source_details" => Scalar {
5372 params!(String) => UnaryFunc::ParseKafkaSourceDetails(
5373 func::ParseKafkaSourceDetails,
5374 ) => Jsonb, oid::FUNC_PARSE_KAFKA_SOURCE_DETAILS_OID;
5375 },
5376 "parse_postgres_source_details" => Scalar {
5377 params!(String) => UnaryFunc::ParsePostgresSourceDetails(
5378 func::ParsePostgresSourceDetails,
5379 ) => Jsonb, oid::FUNC_PARSE_POSTGRES_SOURCE_DETAILS_OID;
5380 },
5381 "parse_source_export_details" => Scalar {
5382 params!(String) => UnaryFunc::ParseSourceExportDetails(
5383 func::ParseSourceExportDetails,
5384 ) => Jsonb, oid::FUNC_PARSE_SOURCE_EXPORT_DETAILS_OID;
5385 },
5386 "parse_connection_details" => Scalar {
5387 params!(String) => UnaryFunc::ParseConnectionDetails(
5388 func::ParseConnectionDetails,
5389 ) => Jsonb, oid::FUNC_PARSE_CONNECTION_DETAILS_OID;
5390 },
5391 "redact_sql" => Scalar {
5392 params!(String) => UnaryFunc::RedactSql(func::RedactSql)
5393 => String, oid::FUNC_REDACT_SQL_OID;
5394 }
5395 }
5396});
5397
5398pub static MZ_UNSAFE_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
5399 use ParamType::*;
5400 use SqlScalarBaseType::*;
5401 builtins! {
5402 "mz_all" => Aggregate {
5409 params!(Bool) => AggregateFunc::All => Bool, oid::FUNC_MZ_ALL_OID;
5410 },
5411 "mz_any" => Aggregate {
5412 params!(Bool) => AggregateFunc::Any => Bool, oid::FUNC_MZ_ANY_OID;
5413 },
5414 "mz_avg_promotion_internal_v1" => Scalar {
5415 params!(Float32) => Operation::identity()
5421 => Float32, oid::FUNC_MZ_AVG_PROMOTION_F32_OID_INTERNAL_V1;
5422 params!(Float64) => Operation::identity()
5423 => Float64, oid::FUNC_MZ_AVG_PROMOTION_F64_OID_INTERNAL_V1;
5424 params!(Int16) => Operation::unary(|ecx, e| {
5425 typeconv::plan_cast(
5426 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5427 )
5428 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I16_OID_INTERNAL_V1;
5429 params!(Int32) => Operation::unary(|ecx, e| {
5430 typeconv::plan_cast(
5431 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5432 )
5433 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I32_OID_INTERNAL_V1;
5434 params!(UInt16) => Operation::unary(|ecx, e| {
5435 typeconv::plan_cast(
5436 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5437 )
5438 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U16_OID_INTERNAL_V1;
5439 params!(UInt32) => Operation::unary(|ecx, e| {
5440 typeconv::plan_cast(
5441 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5442 )
5443 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U32_OID_INTERNAL_V1;
5444 params!(Interval) => Operation::identity()
5450 => Interval, oid::FUNC_MZ_AVG_PROMOTION_INTERVAL_OID_INTERNAL_V1;
5451 },
5452 "mz_avg_promotion" => Scalar {
5453 params!(Float32) => Operation::identity()
5459 => Float32, oid::FUNC_MZ_AVG_PROMOTION_F32_OID;
5460 params!(Float64) => Operation::identity()
5461 => Float64, oid::FUNC_MZ_AVG_PROMOTION_F64_OID;
5462 params!(Int16) => Operation::unary(|ecx, e| {
5463 typeconv::plan_cast(
5464 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5465 )
5466 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I16_OID;
5467 params!(Int32) => Operation::unary(|ecx, e| {
5468 typeconv::plan_cast(
5469 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5470 )
5471 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I32_OID;
5472 params!(Int64) => Operation::unary(|ecx, e| {
5473 typeconv::plan_cast(
5474 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5475 )
5476 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I64_OID;
5477 params!(UInt16) => Operation::unary(|ecx, e| {
5478 typeconv::plan_cast(
5479 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5480 )
5481 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U16_OID;
5482 params!(UInt32) => Operation::unary(|ecx, e| {
5483 typeconv::plan_cast(
5484 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5485 )
5486 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U32_OID;
5487 params!(UInt64) => Operation::unary(|ecx, e| {
5488 typeconv::plan_cast(
5489 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5490 )
5491 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U64_OID;
5492 params!(Numeric) => Operation::unary(|ecx, e| {
5493 typeconv::plan_cast(
5494 ecx, CastContext::Explicit, e, &SqlScalarType::Numeric {max_scale: None},
5495 )
5496 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_NUMERIC_OID;
5497 params!(Interval) => Operation::identity()
5501 => Interval, oid::FUNC_MZ_AVG_PROMOTION_INTERVAL_OID;
5502 },
5503 "mz_error_if_null" => Scalar {
5504 params!(Any, String) => VariadicFunc::from(variadic::ErrorIfNull)
5507 => Any, oid::FUNC_MZ_ERROR_IF_NULL_OID;
5508 },
5509 "generate_series_unoptimized" => Table {
5510 params!(Int64, Int64) => Operation::binary(move |_ecx, start, stop| {
5515 Ok(TableFuncPlan {
5516 imp: TableFuncImpl::CallTable {
5517 func: TableFunc::GenerateSeriesUnoptimized,
5518 exprs: vec![
5519 start, stop,
5520 HirScalarExpr::literal(Datum::Int64(1), SqlScalarType::Int64),
5521 ],
5522 },
5523 column_names: vec!["generate_series_unoptimized".into()],
5524 })
5525 }) => ReturnType::set_of(Int64.into()), oid::FUNC_MZ_GEN_SERIES_UNOPT_OID;
5526 params!(Int64, Int64, Int64) => Operation::variadic(move |_ecx, exprs| {
5527 Ok(TableFuncPlan {
5528 imp: TableFuncImpl::CallTable {
5529 func: TableFunc::GenerateSeriesUnoptimized,
5530 exprs,
5531 },
5532 column_names: vec!["generate_series_unoptimized".into()],
5533 })
5534 }) => ReturnType::set_of(Int64.into()), oid::FUNC_MZ_GEN_SERIES_UNOPT_STEP_OID;
5535 },
5536 "mz_sleep" => Scalar {
5537 params!(Float64) => UnaryFunc::Sleep(func::Sleep)
5538 => TimestampTz, oid::FUNC_MZ_SLEEP_OID;
5539 },
5540 "mz_panic" => Scalar {
5541 params!(String) => UnaryFunc::Panic(func::Panic) => String, oid::FUNC_MZ_PANIC_OID;
5542 }
5543 }
5544});
5545
5546fn digest(algorithm: &'static str) -> Operation<HirScalarExpr> {
5547 Operation::unary(move |_ecx, input| {
5548 let algorithm = HirScalarExpr::literal(Datum::String(algorithm), SqlScalarType::String);
5549 Ok(input.call_binary(algorithm, BinaryFunc::from(func::DigestBytes)))
5550 })
5551}
5552
5553fn array_to_string(
5554 ecx: &ExprContext,
5555 exprs: Vec<HirScalarExpr>,
5556) -> Result<HirScalarExpr, PlanError> {
5557 let elem_type = match ecx.scalar_type(&exprs[0]) {
5558 SqlScalarType::Array(elem_type) => *elem_type,
5559 _ => unreachable!("array_to_string is guaranteed to receive array as first argument"),
5560 };
5561 Ok(HirScalarExpr::call_variadic(
5562 variadic::ArrayToString { elem_type },
5563 exprs,
5564 ))
5565}
5566
5567pub static OP_IMPLS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
5569 use BinaryFunc as BF;
5570 use ParamType::*;
5571 use SqlScalarBaseType::*;
5572 builtins! {
5573 "+" => Scalar {
5596 params!(Any) => Operation::new(|ecx, exprs, _params, _order_by| {
5597 typeconv::plan_coerce(ecx, exprs.into_element(), &SqlScalarType::Float64)
5610 }) => Any, oid::OP_UNARY_PLUS_OID;
5611 params!(Int16, Int16) => BF::from(func::AddInt16) => Int16, 550;
5612 params!(Int32, Int32) => BF::from(func::AddInt32) => Int32, 551;
5613 params!(Int64, Int64) => BF::from(func::AddInt64) => Int64, 684;
5614 params!(UInt16, UInt16) => BF::from(func::AddUint16) => UInt16, oid::FUNC_ADD_UINT16;
5615 params!(UInt32, UInt32) => BF::from(func::AddUint32) => UInt32, oid::FUNC_ADD_UINT32;
5616 params!(UInt64, UInt64) => BF::from(func::AddUint64) => UInt64, oid::FUNC_ADD_UINT64;
5617 params!(Float32, Float32) => BF::from(func::AddFloat32) => Float32, 586;
5618 params!(Float64, Float64) => BF::from(func::AddFloat64) => Float64, 591;
5619 params!(Interval, Interval) => BF::from(func::AddInterval) => Interval, 1337;
5620 params!(Timestamp, Interval) => BF::from(func::AddTimestampInterval) => Timestamp, 2066;
5621 params!(Interval, Timestamp) => {
5622 Operation::binary(|_ecx, lhs, rhs| {
5623 Ok(rhs.call_binary(lhs, func::AddTimestampInterval))
5624 })
5625 } => Timestamp, 2553;
5626 params!(TimestampTz, Interval)
5627 => BF::from(func::AddTimestampTzInterval) => TimestampTz, 1327;
5628 params!(Interval, TimestampTz) => {
5629 Operation::binary(|_ecx, lhs, rhs| {
5630 Ok(rhs.call_binary(lhs, func::AddTimestampTzInterval))
5631 })
5632 } => TimestampTz, 2554;
5633 params!(Date, Interval) => BF::from(func::AddDateInterval) => Timestamp, 1076;
5634 params!(Interval, Date) => {
5635 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, func::AddDateInterval)))
5636 } => Timestamp, 2551;
5637 params!(Date, Time) => BF::from(func::AddDateTime) => Timestamp, 1360;
5638 params!(Time, Date) => {
5639 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, func::AddDateTime)))
5640 } => Timestamp, 1363;
5641 params!(Time, Interval) => BF::from(func::AddTimeInterval) => Time, 1800;
5642 params!(Interval, Time) => {
5643 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, func::AddTimeInterval)))
5644 } => Time, 1849;
5645 params!(Numeric, Numeric) => BF::from(func::AddNumeric) => Numeric, 1758;
5646 params!(RangeAny, RangeAny) => BF::from(func::RangeUnion) => RangeAny, 3898;
5647 },
5648 "-" => Scalar {
5649 params!(Int16) => UnaryFunc::NegInt16(func::NegInt16) => Int16, 559;
5650 params!(Int32) => UnaryFunc::NegInt32(func::NegInt32) => Int32, 558;
5651 params!(Int64) => UnaryFunc::NegInt64(func::NegInt64) => Int64, 484;
5652 params!(Float32) => UnaryFunc::NegFloat32(func::NegFloat32) => Float32, 584;
5653 params!(Float64) => UnaryFunc::NegFloat64(func::NegFloat64) => Float64, 585;
5654 params!(Numeric) => UnaryFunc::NegNumeric(func::NegNumeric) => Numeric, 17510;
5655 params!(Interval) => UnaryFunc::NegInterval(func::NegInterval) => Interval, 1336;
5656 params!(Int32, Int32) => BF::from(func::SubInt32) => Int32, 555;
5657 params!(Int64, Int64) => BF::from(func::SubInt64) => Int64, 685;
5658 params!(UInt16, UInt16) => BF::from(func::SubUint16) => UInt16, oid::FUNC_SUB_UINT16;
5659 params!(UInt32, UInt32) => BF::from(func::SubUint32) => UInt32, oid::FUNC_SUB_UINT32;
5660 params!(UInt64, UInt64) => BF::from(func::SubUint64) => UInt64, oid::FUNC_SUB_UINT64;
5661 params!(Float32, Float32) => BF::from(func::SubFloat32) => Float32, 587;
5662 params!(Float64, Float64) => BF::from(func::SubFloat64) => Float64, 592;
5663 params!(Numeric, Numeric) => BF::from(func::SubNumeric) => Numeric, 17590;
5664 params!(Interval, Interval) => BF::from(func::SubInterval) => Interval, 1338;
5665 params!(Timestamp, Timestamp) => BF::from(func::SubTimestamp) => Interval, 2067;
5666 params!(TimestampTz, TimestampTz) => BF::from(func::SubTimestampTz) => Interval, 1328;
5667 params!(Timestamp, Interval) => BF::from(func::SubTimestampInterval) => Timestamp, 2068;
5668 params!(TimestampTz, Interval)
5669 => BF::from(func::SubTimestampTzInterval) => TimestampTz, 1329;
5670 params!(Date, Date) => BF::from(func::SubDate) => Int32, 1099;
5671 params!(Date, Interval) => BF::from(func::SubDateInterval) => Timestamp, 1077;
5672 params!(Time, Time) => BF::from(func::SubTime) => Interval, 1399;
5673 params!(Time, Interval) => BF::from(func::SubTimeInterval) => Time, 1801;
5674 params!(Jsonb, Int64) => BF::from(func::JsonbDeleteInt64) => Jsonb, 3286;
5675 params!(Jsonb, String) => BF::from(func::JsonbDeleteString) => Jsonb, 3285;
5676 params!(RangeAny, RangeAny) => BF::from(func::RangeDifference) => RangeAny, 3899;
5677 },
5680 "*" => Scalar {
5681 params!(Int16, Int16) => BF::from(func::MulInt16) => Int16, 526;
5682 params!(Int32, Int32) => BF::from(func::MulInt32) => Int32, 514;
5683 params!(Int64, Int64) => BF::from(func::MulInt64) => Int64, 686;
5684 params!(UInt16, UInt16) => BF::from(func::MulUint16) => UInt16, oid::FUNC_MUL_UINT16;
5685 params!(UInt32, UInt32) => BF::from(func::MulUint32) => UInt32, oid::FUNC_MUL_UINT32;
5686 params!(UInt64, UInt64) => BF::from(func::MulUint64) => UInt64, oid::FUNC_MUL_UINT64;
5687 params!(Float32, Float32) => BF::from(func::MulFloat32) => Float32, 589;
5688 params!(Float64, Float64) => BF::from(func::MulFloat64) => Float64, 594;
5689 params!(Interval, Float64) => BF::from(func::MulInterval) => Interval, 1583;
5690 params!(Float64, Interval) => {
5691 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, func::MulInterval)))
5692 } => Interval, 1584;
5693 params!(Numeric, Numeric) => BF::from(func::MulNumeric) => Numeric, 1760;
5694 params!(RangeAny, RangeAny) => BF::from(func::RangeIntersection) => RangeAny, 3900;
5695 },
5696 "/" => Scalar {
5697 params!(Int16, Int16) => BF::from(func::DivInt16) => Int16, 527;
5698 params!(Int32, Int32) => BF::from(func::DivInt32) => Int32, 528;
5699 params!(Int64, Int64) => BF::from(func::DivInt64) => Int64, 687;
5700 params!(UInt16, UInt16) => BF::from(func::DivUint16) => UInt16, oid::FUNC_DIV_UINT16;
5701 params!(UInt32, UInt32) => BF::from(func::DivUint32) => UInt32, oid::FUNC_DIV_UINT32;
5702 params!(UInt64, UInt64) => BF::from(func::DivUint64) => UInt64, oid::FUNC_DIV_UINT64;
5703 params!(Float32, Float32) => BF::from(func::DivFloat32) => Float32, 588;
5704 params!(Float64, Float64) => BF::from(func::DivFloat64) => Float64, 593;
5705 params!(Interval, Float64) => BF::from(func::DivInterval) => Interval, 1585;
5706 params!(Numeric, Numeric) => BF::from(func::DivNumeric) => Numeric, 1761;
5707 },
5708 "%" => Scalar {
5709 params!(Int16, Int16) => BF::from(func::ModInt16) => Int16, 529;
5710 params!(Int32, Int32) => BF::from(func::ModInt32) => Int32, 530;
5711 params!(Int64, Int64) => BF::from(func::ModInt64) => Int64, 439;
5712 params!(UInt16, UInt16) => BF::from(func::ModUint16) => UInt16, oid::FUNC_MOD_UINT16;
5713 params!(UInt32, UInt32) => BF::from(func::ModUint32) => UInt32, oid::FUNC_MOD_UINT32;
5714 params!(UInt64, UInt64) => BF::from(func::ModUint64) => UInt64, oid::FUNC_MOD_UINT64;
5715 params!(Float32, Float32) => BF::from(func::ModFloat32) => Float32, oid::OP_MOD_F32_OID;
5716 params!(Float64, Float64) => BF::from(func::ModFloat64) => Float64, oid::OP_MOD_F64_OID;
5717 params!(Numeric, Numeric) => BF::from(func::ModNumeric) => Numeric, 1762;
5718 },
5719 "&" => Scalar {
5720 params!(Int16, Int16) => BF::from(func::BitAndInt16) => Int16, 1874;
5721 params!(Int32, Int32) => BF::from(func::BitAndInt32) => Int32, 1880;
5722 params!(Int64, Int64) => BF::from(func::BitAndInt64) => Int64, 1886;
5723 params!(UInt16, UInt16) => BF::from(func::BitAndUint16) => UInt16, oid::FUNC_AND_UINT16;
5724 params!(UInt32, UInt32) => BF::from(func::BitAndUint32) => UInt32, oid::FUNC_AND_UINT32;
5725 params!(UInt64, UInt64) => BF::from(func::BitAndUint64) => UInt64, oid::FUNC_AND_UINT64;
5726 },
5727 "|" => Scalar {
5728 params!(Int16, Int16) => BF::from(func::BitOrInt16) => Int16, 1875;
5729 params!(Int32, Int32) => BF::from(func::BitOrInt32) => Int32, 1881;
5730 params!(Int64, Int64) => BF::from(func::BitOrInt64) => Int64, 1887;
5731 params!(UInt16, UInt16) => BF::from(func::BitOrUint16) => UInt16, oid::FUNC_OR_UINT16;
5732 params!(UInt32, UInt32) => BF::from(func::BitOrUint32) => UInt32, oid::FUNC_OR_UINT32;
5733 params!(UInt64, UInt64) => BF::from(func::BitOrUint64) => UInt64, oid::FUNC_OR_UINT64;
5734 },
5735 "#" => Scalar {
5736 params!(Int16, Int16) => BF::from(func::BitXorInt16) => Int16, 1876;
5737 params!(Int32, Int32) => BF::from(func::BitXorInt32) => Int32, 1882;
5738 params!(Int64, Int64) => BF::from(func::BitXorInt64) => Int64, 1888;
5739 params!(UInt16, UInt16) => BF::from(func::BitXorUint16) => UInt16, oid::FUNC_XOR_UINT16;
5740 params!(UInt32, UInt32) => BF::from(func::BitXorUint32) => UInt32, oid::FUNC_XOR_UINT32;
5741 params!(UInt64, UInt64) => BF::from(func::BitXorUint64) => UInt64, oid::FUNC_XOR_UINT64;
5742 },
5743 "<<" => Scalar {
5744 params!(Int16, Int32) => BF::from(func::BitShiftLeftInt16) => Int16, 1878;
5745 params!(Int32, Int32) => BF::from(func::BitShiftLeftInt32) => Int32, 1884;
5746 params!(Int64, Int32) => BF::from(func::BitShiftLeftInt64) => Int64, 1890;
5747 params!(UInt16, UInt32) => BF::from(func::BitShiftLeftUint16)
5748 => UInt16, oid::FUNC_SHIFT_LEFT_UINT16;
5749 params!(UInt32, UInt32) => BF::from(func::BitShiftLeftUint32)
5750 => UInt32, oid::FUNC_SHIFT_LEFT_UINT32;
5751 params!(UInt64, UInt32) => BF::from(func::BitShiftLeftUint64)
5752 => UInt64, oid::FUNC_SHIFT_LEFT_UINT64;
5753 params!(RangeAny, RangeAny) => BF::from(func::RangeBefore) => Bool, 3893;
5754 },
5755 ">>" => Scalar {
5756 params!(Int16, Int32) => BF::from(func::BitShiftRightInt16) => Int16, 1879;
5757 params!(Int32, Int32) => BF::from(func::BitShiftRightInt32) => Int32, 1885;
5758 params!(Int64, Int32) => BF::from(func::BitShiftRightInt64) => Int64, 1891;
5759 params!(UInt16, UInt32) => BF::from(func::BitShiftRightUint16)
5760 => UInt16, oid::FUNC_SHIFT_RIGHT_UINT16;
5761 params!(UInt32, UInt32) => BF::from(func::BitShiftRightUint32)
5762 => UInt32, oid::FUNC_SHIFT_RIGHT_UINT32;
5763 params!(UInt64, UInt32) => BF::from(func::BitShiftRightUint64)
5764 => UInt64, oid::FUNC_SHIFT_RIGHT_UINT64;
5765 params!(RangeAny, RangeAny) => BF::from(func::RangeAfter) => Bool, 3894;
5766 },
5767
5768 "~~*" => Scalar {
5770 params!(String, String) => BF::from(func::IsLikeMatchCaseInsensitive) => Bool, 1627;
5771 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5772 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5773 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5774 .call_binary(rhs, BF::from(func::IsLikeMatchCaseInsensitive))
5775 )
5776 }) => Bool, 1629;
5777 },
5778 "!~~*" => Scalar {
5779 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
5780 Ok(lhs
5781 .call_binary(rhs, BF::from(func::IsLikeMatchCaseInsensitive))
5782 .call_unary(UnaryFunc::Not(func::Not)))
5783 }) => Bool, 1628;
5784 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5785 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5786 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5787 .call_binary(rhs, BF::from(func::IsLikeMatchCaseInsensitive))
5788 .call_unary(UnaryFunc::Not(func::Not))
5789 )
5790 }) => Bool, 1630;
5791 },
5792
5793
5794 "~~" => Scalar {
5796 params!(String, String) => BF::from(func::IsLikeMatchCaseSensitive) => Bool, 1209;
5797 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5798 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5799 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5800 .call_binary(rhs, BF::from(func::IsLikeMatchCaseSensitive))
5801 )
5802 }) => Bool, 1211;
5803 },
5804 "!~~" => Scalar {
5805 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
5806 Ok(lhs
5807 .call_binary(rhs, BF::from(func::IsLikeMatchCaseSensitive))
5808 .call_unary(UnaryFunc::Not(func::Not)))
5809 }) => Bool, 1210;
5810 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5811 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5812 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5813 .call_binary(rhs, BF::from(func::IsLikeMatchCaseSensitive))
5814 .call_unary(UnaryFunc::Not(func::Not))
5815 )
5816 }) => Bool, 1212;
5817 },
5818
5819 "~" => Scalar {
5821 params!(Int16) => UnaryFunc::BitNotInt16(func::BitNotInt16) => Int16, 1877;
5822 params!(Int32) => UnaryFunc::BitNotInt32(func::BitNotInt32) => Int32, 1883;
5823 params!(Int64) => UnaryFunc::BitNotInt64(func::BitNotInt64) => Int64, 1889;
5824 params!(UInt16) => UnaryFunc::BitNotUint16(func::BitNotUint16)
5825 => UInt16, oid::FUNC_BIT_NOT_UINT16_OID;
5826 params!(UInt32) => UnaryFunc::BitNotUint32(func::BitNotUint32)
5827 => UInt32, oid::FUNC_BIT_NOT_UINT32_OID;
5828 params!(UInt64) => UnaryFunc::BitNotUint64(func::BitNotUint64)
5829 => UInt64, oid::FUNC_BIT_NOT_UINT64_OID;
5830 params!(String, String)
5831 => BinaryFunc::IsRegexpMatchCaseSensitive(
5832 func::IsRegexpMatchCaseSensitive,
5833 ) => Bool, 641;
5834 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5835 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5836 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5837 .call_binary(rhs, BinaryFunc::IsRegexpMatchCaseSensitive(
5838 func::IsRegexpMatchCaseSensitive,
5839 )))
5840 }) => Bool, 1055;
5841 },
5842 "~*" => Scalar {
5843 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
5844 Ok(lhs.call_binary(
5845 rhs,
5846 BinaryFunc::IsRegexpMatchCaseInsensitive(
5847 func::IsRegexpMatchCaseInsensitive,
5848 ),
5849 ))
5850 }) => Bool, 1228;
5851 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5852 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5853 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5854 .call_binary(rhs, BinaryFunc::IsRegexpMatchCaseInsensitive(
5855 func::IsRegexpMatchCaseInsensitive,
5856 )))
5857 }) => Bool, 1234;
5858 },
5859 "!~" => Scalar {
5860 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
5861 Ok(lhs
5862 .call_binary(rhs, BinaryFunc::IsRegexpMatchCaseSensitive(
5863 func::IsRegexpMatchCaseSensitive,
5864 ))
5865 .call_unary(UnaryFunc::Not(func::Not)))
5866 }) => Bool, 642;
5867 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5868 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5869 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5870 .call_binary(rhs, BinaryFunc::IsRegexpMatchCaseSensitive(
5871 func::IsRegexpMatchCaseSensitive,
5872 ))
5873 .call_unary(UnaryFunc::Not(func::Not)))
5874 }) => Bool, 1056;
5875 },
5876 "!~*" => Scalar {
5877 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
5878 Ok(lhs
5879 .call_binary(rhs, BinaryFunc::IsRegexpMatchCaseInsensitive(
5880 func::IsRegexpMatchCaseInsensitive,
5881 ))
5882 .call_unary(UnaryFunc::Not(func::Not)))
5883 }) => Bool, 1229;
5884 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
5885 let length = ecx.scalar_type(&lhs).unwrap_char_length();
5886 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
5887 .call_binary(rhs, BinaryFunc::IsRegexpMatchCaseInsensitive(
5888 func::IsRegexpMatchCaseInsensitive,
5889 ))
5890 .call_unary(UnaryFunc::Not(func::Not)))
5891 }) => Bool, 1235;
5892 },
5893
5894 "||" => Scalar {
5896 params!(String, NonVecAny) => Operation::binary(|ecx, lhs, rhs| {
5897 let rhs = typeconv::plan_cast(
5898 ecx,
5899 CastContext::Explicit,
5900 rhs,
5901 &SqlScalarType::String,
5902 )?;
5903 Ok(lhs.call_binary(rhs, func::TextConcatBinary))
5904 }) => String, 2779;
5905 params!(NonVecAny, String) => Operation::binary(|ecx, lhs, rhs| {
5906 let lhs = typeconv::plan_cast(
5907 ecx,
5908 CastContext::Explicit,
5909 lhs,
5910 &SqlScalarType::String,
5911 )?;
5912 Ok(lhs.call_binary(rhs, func::TextConcatBinary))
5913 }) => String, 2780;
5914 params!(String, String) => BF::from(func::TextConcatBinary) => String, 654;
5915 params!(Jsonb, Jsonb) => BF::from(func::JsonbConcat) => Jsonb, 3284;
5916 params!(ArrayAnyCompatible, ArrayAnyCompatible)
5917 => BF::from(func::ArrayArrayConcat) => ArrayAnyCompatible, 375;
5918 params!(ListAnyCompatible, ListAnyCompatible)
5919 => BF::from(func::ListListConcat)
5920 => ListAnyCompatible, oid::OP_CONCAT_LIST_LIST_OID;
5921 params!(ListAnyCompatible, ListElementAnyCompatible)
5922 => BF::from(func::ListElementConcat)
5923 => ListAnyCompatible, oid::OP_CONCAT_LIST_ELEMENT_OID;
5924 params!(ListElementAnyCompatible, ListAnyCompatible)
5925 => BF::from(func::ElementListConcat)
5926 => ListAnyCompatible, oid::OP_CONCAT_ELEMENY_LIST_OID;
5927 },
5928
5929 "->" => Scalar {
5931 params!(Jsonb, Int64) => BF::from(func::JsonbGetInt64) => Jsonb, 3212;
5932 params!(Jsonb, String) => BF::from(func::JsonbGetString) => Jsonb, 3211;
5933 params!(MapAny, String) => BF::from(func::MapGetValue)
5934 => Any, oid::OP_GET_VALUE_MAP_OID;
5935 },
5936 "->>" => Scalar {
5937 params!(Jsonb, Int64) => BF::from(func::JsonbGetInt64Stringify) => String, 3481;
5938 params!(Jsonb, String) => BF::from(func::JsonbGetStringStringify) => String, 3477;
5939 },
5940 "#>" => Scalar {
5941 params!(Jsonb, SqlScalarType::Array(Box::new(SqlScalarType::String)))
5942 => BF::from(func::JsonbGetPath) => Jsonb, 3213;
5943 },
5944 "#>>" => Scalar {
5945 params!(Jsonb, SqlScalarType::Array(Box::new(SqlScalarType::String)))
5946 => BF::from(func::JsonbGetPathStringify) => String, 3206;
5947 },
5948 "@>" => Scalar {
5949 params!(Jsonb, Jsonb) => BF::from(func::JsonbContainsJsonb) => Bool, 3246;
5950 params!(Jsonb, String) => Operation::binary(|_ecx, lhs, rhs| {
5951 Ok(lhs.call_binary(
5952 rhs.call_unary(UnaryFunc::CastStringToJsonb(func::CastStringToJsonb)),
5953 BinaryFunc::from(func::JsonbContainsJsonb),
5954 ))
5955 }) => Bool, oid::OP_CONTAINS_JSONB_STRING_OID;
5956 params!(String, Jsonb) => Operation::binary(|_ecx, lhs, rhs| {
5957 Ok(lhs.call_unary(UnaryFunc::CastStringToJsonb(func::CastStringToJsonb))
5958 .call_binary(rhs, func::JsonbContainsJsonb))
5959 }) => Bool, oid::OP_CONTAINS_STRING_JSONB_OID;
5960 params!(MapAnyCompatible, MapAnyCompatible)
5961 => BF::from(func::MapContainsMap)
5962 => Bool, oid::OP_CONTAINS_MAP_MAP_OID;
5963 params!(RangeAny, AnyElement) => Operation::binary(|ecx, lhs, rhs| {
5964 let elem_type = ecx.scalar_type(&lhs).unwrap_range_element_type().clone();
5965 let f = match elem_type {
5966 SqlScalarType::Int32 => BF::from(func::RangeContainsI32),
5967 SqlScalarType::Int64 => BF::from(func::RangeContainsI64),
5968 SqlScalarType::Date => BF::from(func::RangeContainsDate),
5969 SqlScalarType::Numeric { .. } => BF::from(func::RangeContainsNumeric),
5970 SqlScalarType::Timestamp { .. } => BF::from(func::RangeContainsTimestamp),
5971 SqlScalarType::TimestampTz { .. } => BF::from(func::RangeContainsTimestampTz),
5972 _ => bail_unsupported!(format!("range element type: {elem_type:?}")),
5973 };
5974 Ok(lhs.call_binary(rhs, f))
5975 }) => Bool, 3889;
5976 params!(RangeAny, RangeAny) => Operation::binary(|_ecx, lhs, rhs| {
5977 Ok(lhs.call_binary(rhs, BF::from(func::RangeContainsRange)))
5978 }) => Bool, 3890;
5979 params!(ArrayAny, ArrayAny) => Operation::binary(|_ecx, lhs, rhs| {
5980 Ok(lhs.call_binary(rhs, BF::from(func::ArrayContainsArray)))
5981 }) => Bool, 2751;
5982 params!(ListAny, ListAny) => Operation::binary(|_ecx, lhs, rhs| {
5983 Ok(lhs.call_binary(rhs, BF::from(func::ListContainsList)))
5984 }) => Bool, oid::OP_CONTAINS_LIST_LIST_OID;
5985 },
5986 "<@" => Scalar {
5987 params!(Jsonb, Jsonb) => Operation::binary(|_ecx, lhs, rhs| {
5988 Ok(rhs.call_binary(
5989 lhs,
5990 func::JsonbContainsJsonb
5991 ))
5992 }) => Bool, 3250;
5993 params!(Jsonb, String) => Operation::binary(|_ecx, lhs, rhs| {
5994 Ok(rhs.call_unary(UnaryFunc::CastStringToJsonb(func::CastStringToJsonb))
5995 .call_binary(lhs, func::JsonbContainsJsonb))
5996 }) => Bool, oid::OP_CONTAINED_JSONB_STRING_OID;
5997 params!(String, Jsonb) => Operation::binary(|_ecx, lhs, rhs| {
5998 Ok(rhs.call_binary(
5999 lhs.call_unary(UnaryFunc::CastStringToJsonb(func::CastStringToJsonb)),
6000 func::JsonbContainsJsonb,
6001 ))
6002 }) => Bool, oid::OP_CONTAINED_STRING_JSONB_OID;
6003 params!(MapAnyCompatible, MapAnyCompatible) => Operation::binary(|_ecx, lhs, rhs| {
6004 Ok(rhs.call_binary(lhs, func::MapContainsMap))
6005 }) => Bool, oid::OP_CONTAINED_MAP_MAP_OID;
6006 params!(AnyElement, RangeAny) => Operation::binary(|ecx, lhs, rhs| {
6007 let elem_type = ecx.scalar_type(&rhs).unwrap_range_element_type().clone();
6008 let f = match elem_type {
6009 SqlScalarType::Int32 => BF::from(func::RangeContainsI32Rev),
6010 SqlScalarType::Int64 => BF::from(func::RangeContainsI64Rev),
6011 SqlScalarType::Date => BF::from(func::RangeContainsDateRev),
6012 SqlScalarType::Numeric { .. } => BF::from(func::RangeContainsNumericRev),
6013 SqlScalarType::Timestamp { .. } => BF::from(func::RangeContainsTimestampRev),
6014 SqlScalarType::TimestampTz { .. } => {
6015 BF::from(func::RangeContainsTimestampTzRev)
6016 }
6017 _ => bail_unsupported!(format!("range element type: {elem_type:?}")),
6018 };
6019 Ok(rhs.call_binary(lhs, f))
6020 }) => Bool, 3891;
6021 params!(RangeAny, RangeAny) => Operation::binary(|_ecx, lhs, rhs| {
6022 Ok(rhs.call_binary(lhs, BF::from(func::RangeContainsRangeRev)))
6023 }) => Bool, 3892;
6024 params!(ArrayAny, ArrayAny) => Operation::binary(|_ecx, lhs, rhs| {
6025 Ok(lhs.call_binary(rhs, BF::from(func::ArrayContainsArrayRev)))
6026 }) => Bool, 2752;
6027 params!(ListAny, ListAny) => Operation::binary(|_ecx, lhs, rhs| {
6028 Ok(lhs.call_binary(rhs, BF::from(func::ListContainsListRev)))
6029 }) => Bool, oid::OP_IS_CONTAINED_LIST_LIST_OID;
6030 },
6031 "?" => Scalar {
6032 params!(Jsonb, String) => BF::from(func::JsonbContainsString) => Bool, 3247;
6033 params!(MapAny, String) => BF::from(func::MapContainsKey)
6034 => Bool, oid::OP_CONTAINS_KEY_MAP_OID;
6035 },
6036 "?&" => Scalar {
6037 params!(MapAny, SqlScalarType::Array(Box::new(SqlScalarType::String)))
6038 => BF::from(func::MapContainsAllKeys)
6039 => Bool, oid::OP_CONTAINS_ALL_KEYS_MAP_OID;
6040 },
6041 "?|" => Scalar {
6042 params!(MapAny, SqlScalarType::Array(Box::new(SqlScalarType::String)))
6043 => BF::from(func::MapContainsAnyKeys)
6044 => Bool, oid::OP_CONTAINS_ANY_KEYS_MAP_OID;
6045 },
6046 "&&" => Scalar {
6047 params!(RangeAny, RangeAny) => BF::from(func::RangeOverlaps) => Bool, 3888;
6048 },
6049 "&<" => Scalar {
6050 params!(RangeAny, RangeAny) => BF::from(func::RangeOverleft) => Bool, 3895;
6051 },
6052 "&>" => Scalar {
6053 params!(RangeAny, RangeAny) => BF::from(func::RangeOverright) => Bool, 3896;
6054 },
6055 "-|-" => Scalar {
6056 params!(RangeAny, RangeAny) => BF::from(func::RangeAdjacent) => Bool, 3897;
6057 },
6058
6059 "<" => Scalar {
6061 params!(Numeric, Numeric) => BF::from(func::Lt) => Bool, 1754;
6062 params!(Bool, Bool) => BF::from(func::Lt) => Bool, 58;
6063 params!(Int16, Int16) => BF::from(func::Lt) => Bool, 95;
6064 params!(Int32, Int32) => BF::from(func::Lt) => Bool, 97;
6065 params!(Int64, Int64) => BF::from(func::Lt) => Bool, 412;
6066 params!(UInt16, UInt16) => BF::from(func::Lt) => Bool, oid::FUNC_LT_UINT16_OID;
6067 params!(UInt32, UInt32) => BF::from(func::Lt) => Bool, oid::FUNC_LT_UINT32_OID;
6068 params!(UInt64, UInt64) => BF::from(func::Lt) => Bool, oid::FUNC_LT_UINT64_OID;
6069 params!(Float32, Float32) => BF::from(func::Lt) => Bool, 622;
6070 params!(Float64, Float64) => BF::from(func::Lt) => Bool, 672;
6071 params!(Oid, Oid) => BF::from(func::Lt) => Bool, 609;
6072 params!(Date, Date) => BF::from(func::Lt) => Bool, 1095;
6073 params!(Time, Time) => BF::from(func::Lt) => Bool, 1110;
6074 params!(Timestamp, Timestamp) => BF::from(func::Lt) => Bool, 2062;
6075 params!(TimestampTz, TimestampTz) => BF::from(func::Lt) => Bool, 1322;
6076 params!(Uuid, Uuid) => BF::from(func::Lt) => Bool, 2974;
6077 params!(Interval, Interval) => BF::from(func::Lt) => Bool, 1332;
6078 params!(Bytes, Bytes) => BF::from(func::Lt) => Bool, 1957;
6079 params!(String, String) => BF::from(func::Lt) => Bool, 664;
6080 params!(Char, Char) => BF::from(func::Lt) => Bool, 1058;
6081 params!(PgLegacyChar, PgLegacyChar) => BF::from(func::Lt) => Bool, 631;
6082 params!(PgLegacyName, PgLegacyName) => BF::from(func::Lt) => Bool, 660;
6083 params!(Jsonb, Jsonb) => BF::from(func::Lt) => Bool, 3242;
6084 params!(ListAny, ListAny) => BF::from(func::Lt) => Bool, oid::FUNC_LIST_LT_OID;
6085 params!(ArrayAny, ArrayAny) => BF::from(func::Lt) => Bool, 1072;
6086 params!(RecordAny, RecordAny) => BF::from(func::Lt) => Bool, 2990;
6087 params!(MzTimestamp, MzTimestamp) => BF::from(func::Lt)
6088 => Bool, oid::FUNC_MZ_TIMESTAMP_LT_MZ_TIMESTAMP_OID;
6089 params!(RangeAny, RangeAny) => BF::from(func::Lt) => Bool, 3884;
6090 },
6091 "<=" => Scalar {
6092 params!(Numeric, Numeric) => BF::from(func::Lte) => Bool, 1755;
6093 params!(Bool, Bool) => BF::from(func::Lte) => Bool, 1694;
6094 params!(Int16, Int16) => BF::from(func::Lte) => Bool, 522;
6095 params!(Int32, Int32) => BF::from(func::Lte) => Bool, 523;
6096 params!(Int64, Int64) => BF::from(func::Lte) => Bool, 414;
6097 params!(UInt16, UInt16) => BF::from(func::Lte) => Bool, oid::FUNC_LTE_UINT16_OID;
6098 params!(UInt32, UInt32) => BF::from(func::Lte) => Bool, oid::FUNC_LTE_UINT32_OID;
6099 params!(UInt64, UInt64) => BF::from(func::Lte) => Bool, oid::FUNC_LTE_UINT64_OID;
6100 params!(Float32, Float32) => BF::from(func::Lte) => Bool, 624;
6101 params!(Float64, Float64) => BF::from(func::Lte) => Bool, 673;
6102 params!(Oid, Oid) => BF::from(func::Lte) => Bool, 611;
6103 params!(Date, Date) => BF::from(func::Lte) => Bool, 1096;
6104 params!(Time, Time) => BF::from(func::Lte) => Bool, 1111;
6105 params!(Timestamp, Timestamp) => BF::from(func::Lte) => Bool, 2063;
6106 params!(TimestampTz, TimestampTz) => BF::from(func::Lte) => Bool, 1323;
6107 params!(Uuid, Uuid) => BF::from(func::Lte) => Bool, 2976;
6108 params!(Interval, Interval) => BF::from(func::Lte) => Bool, 1333;
6109 params!(Bytes, Bytes) => BF::from(func::Lte) => Bool, 1958;
6110 params!(String, String) => BF::from(func::Lte) => Bool, 665;
6111 params!(Char, Char) => BF::from(func::Lte) => Bool, 1059;
6112 params!(PgLegacyChar, PgLegacyChar) => BF::from(func::Lte) => Bool, 632;
6113 params!(PgLegacyName, PgLegacyName) => BF::from(func::Lte) => Bool, 661;
6114 params!(Jsonb, Jsonb) => BF::from(func::Lte) => Bool, 3244;
6115 params!(ListAny, ListAny) => BF::from(func::Lte) => Bool, oid::FUNC_LIST_LTE_OID;
6116 params!(ArrayAny, ArrayAny) => BF::from(func::Lte) => Bool, 1074;
6117 params!(RecordAny, RecordAny) => BF::from(func::Lte) => Bool, 2992;
6118 params!(MzTimestamp, MzTimestamp) => BF::from(func::Lte)
6119 => Bool, oid::FUNC_MZ_TIMESTAMP_LTE_MZ_TIMESTAMP_OID;
6120 params!(RangeAny, RangeAny) => BF::from(func::Lte) => Bool, 3885;
6121 },
6122 ">" => Scalar {
6123 params!(Numeric, Numeric) => BF::from(func::Gt) => Bool, 1756;
6124 params!(Bool, Bool) => BF::from(func::Gt) => Bool, 59;
6125 params!(Int16, Int16) => BF::from(func::Gt) => Bool, 520;
6126 params!(Int32, Int32) => BF::from(func::Gt) => Bool, 521;
6127 params!(Int64, Int64) => BF::from(func::Gt) => Bool, 413;
6128 params!(UInt16, UInt16) => BF::from(func::Gt) => Bool, oid::FUNC_GT_UINT16_OID;
6129 params!(UInt32, UInt32) => BF::from(func::Gt) => Bool, oid::FUNC_GT_UINT32_OID;
6130 params!(UInt64, UInt64) => BF::from(func::Gt) => Bool, oid::FUNC_GT_UINT64_OID;
6131 params!(Float32, Float32) => BF::from(func::Gt) => Bool, 623;
6132 params!(Float64, Float64) => BF::from(func::Gt) => Bool, 674;
6133 params!(Oid, Oid) => BF::from(func::Gt) => Bool, 610;
6134 params!(Date, Date) => BF::from(func::Gt) => Bool, 1097;
6135 params!(Time, Time) => BF::from(func::Gt) => Bool, 1112;
6136 params!(Timestamp, Timestamp) => BF::from(func::Gt) => Bool, 2064;
6137 params!(TimestampTz, TimestampTz) => BF::from(func::Gt) => Bool, 1324;
6138 params!(Uuid, Uuid) => BF::from(func::Gt) => Bool, 2975;
6139 params!(Interval, Interval) => BF::from(func::Gt) => Bool, 1334;
6140 params!(Bytes, Bytes) => BF::from(func::Gt) => Bool, 1959;
6141 params!(String, String) => BF::from(func::Gt) => Bool, 666;
6142 params!(Char, Char) => BF::from(func::Gt) => Bool, 1060;
6143 params!(PgLegacyChar, PgLegacyChar) => BF::from(func::Gt) => Bool, 633;
6144 params!(PgLegacyName, PgLegacyName) => BF::from(func::Gt) => Bool, 662;
6145 params!(Jsonb, Jsonb) => BF::from(func::Gt) => Bool, 3243;
6146 params!(ListAny, ListAny) => BF::from(func::Gt) => Bool, oid::FUNC_LIST_GT_OID;
6147 params!(ArrayAny, ArrayAny) => BF::from(func::Gt) => Bool, 1073;
6148 params!(RecordAny, RecordAny) => BF::from(func::Gt) => Bool, 2991;
6149 params!(MzTimestamp, MzTimestamp) => BF::from(func::Gt)
6150 => Bool, oid::FUNC_MZ_TIMESTAMP_GT_MZ_TIMESTAMP_OID;
6151 params!(RangeAny, RangeAny) => BF::from(func::Gt) => Bool, 3887;
6152 },
6153 ">=" => Scalar {
6154 params!(Numeric, Numeric) => BF::from(func::Gte) => Bool, 1757;
6155 params!(Bool, Bool) => BF::from(func::Gte) => Bool, 1695;
6156 params!(Int16, Int16) => BF::from(func::Gte) => Bool, 524;
6157 params!(Int32, Int32) => BF::from(func::Gte) => Bool, 525;
6158 params!(Int64, Int64) => BF::from(func::Gte) => Bool, 415;
6159 params!(UInt16, UInt16) => BF::from(func::Gte) => Bool, oid::FUNC_GTE_UINT16_OID;
6160 params!(UInt32, UInt32) => BF::from(func::Gte) => Bool, oid::FUNC_GTE_UINT32_OID;
6161 params!(UInt64, UInt64) => BF::from(func::Gte) => Bool, oid::FUNC_GTE_UINT64_OID;
6162 params!(Float32, Float32) => BF::from(func::Gte) => Bool, 625;
6163 params!(Float64, Float64) => BF::from(func::Gte) => Bool, 675;
6164 params!(Oid, Oid) => BF::from(func::Gte) => Bool, 612;
6165 params!(Date, Date) => BF::from(func::Gte) => Bool, 1098;
6166 params!(Time, Time) => BF::from(func::Gte) => Bool, 1113;
6167 params!(Timestamp, Timestamp) => BF::from(func::Gte) => Bool, 2065;
6168 params!(TimestampTz, TimestampTz) => BF::from(func::Gte) => Bool, 1325;
6169 params!(Uuid, Uuid) => BF::from(func::Gte) => Bool, 2977;
6170 params!(Interval, Interval) => BF::from(func::Gte) => Bool, 1335;
6171 params!(Bytes, Bytes) => BF::from(func::Gte) => Bool, 1960;
6172 params!(String, String) => BF::from(func::Gte) => Bool, 667;
6173 params!(Char, Char) => BF::from(func::Gte) => Bool, 1061;
6174 params!(PgLegacyChar, PgLegacyChar) => BF::from(func::Gte) => Bool, 634;
6175 params!(PgLegacyName, PgLegacyName) => BF::from(func::Gte) => Bool, 663;
6176 params!(Jsonb, Jsonb) => BF::from(func::Gte) => Bool, 3245;
6177 params!(ListAny, ListAny) => BF::from(func::Gte) => Bool, oid::FUNC_LIST_GTE_OID;
6178 params!(ArrayAny, ArrayAny) => BF::from(func::Gte) => Bool, 1075;
6179 params!(RecordAny, RecordAny) => BF::from(func::Gte) => Bool, 2993;
6180 params!(MzTimestamp, MzTimestamp) => BF::from(func::Gte)
6181 => Bool, oid::FUNC_MZ_TIMESTAMP_GTE_MZ_TIMESTAMP_OID;
6182 params!(RangeAny, RangeAny) => BF::from(func::Gte) => Bool, 3886;
6183 },
6184 "=" => Scalar {
6195 params!(Numeric, Numeric) => BF::from(func::Eq) => Bool, 1752;
6196 params!(Bool, Bool) => BF::from(func::Eq) => Bool, 91;
6197 params!(Int16, Int16) => BF::from(func::Eq) => Bool, 94;
6198 params!(Int32, Int32) => BF::from(func::Eq) => Bool, 96;
6199 params!(Int64, Int64) => BF::from(func::Eq) => Bool, 410;
6200 params!(UInt16, UInt16) => BF::from(func::Eq) => Bool, oid::FUNC_EQ_UINT16_OID;
6201 params!(UInt32, UInt32) => BF::from(func::Eq) => Bool, oid::FUNC_EQ_UINT32_OID;
6202 params!(UInt64, UInt64) => BF::from(func::Eq) => Bool, oid::FUNC_EQ_UINT64_OID;
6203 params!(Float32, Float32) => BF::from(func::Eq) => Bool, 620;
6204 params!(Float64, Float64) => BF::from(func::Eq) => Bool, 670;
6205 params!(Oid, Oid) => BF::from(func::Eq) => Bool, 607;
6206 params!(Date, Date) => BF::from(func::Eq) => Bool, 1093;
6207 params!(Time, Time) => BF::from(func::Eq) => Bool, 1108;
6208 params!(Timestamp, Timestamp) => BF::from(func::Eq) => Bool, 2060;
6209 params!(TimestampTz, TimestampTz) => BF::from(func::Eq) => Bool, 1320;
6210 params!(Uuid, Uuid) => BF::from(func::Eq) => Bool, 2972;
6211 params!(Interval, Interval) => BF::from(func::Eq) => Bool, 1330;
6212 params!(Bytes, Bytes) => BF::from(func::Eq) => Bool, 1955;
6213 params!(String, String) => BF::from(func::Eq) => Bool, 98;
6214 params!(Char, Char) => BF::from(func::Eq) => Bool, 1054;
6215 params!(PgLegacyChar, PgLegacyChar) => BF::from(func::Eq) => Bool, 92;
6216 params!(PgLegacyName, PgLegacyName) => BF::from(func::Eq) => Bool, 93;
6217 params!(Jsonb, Jsonb) => BF::from(func::Eq) => Bool, 3240;
6218 params!(ListAny, ListAny) => BF::from(func::Eq) => Bool, oid::FUNC_LIST_EQ_OID;
6219 params!(ArrayAny, ArrayAny) => BF::from(func::Eq) => Bool, 1070;
6220 params!(RecordAny, RecordAny) => BF::from(func::Eq) => Bool, 2988;
6221 params!(MzTimestamp, MzTimestamp) => BF::from(func::Eq)
6222 => Bool, oid::FUNC_MZ_TIMESTAMP_EQ_MZ_TIMESTAMP_OID;
6223 params!(RangeAny, RangeAny) => BF::from(func::Eq) => Bool, 3882;
6224 params!(MzAclItem, MzAclItem) => BF::from(func::Eq)
6225 => Bool, oid::FUNC_MZ_ACL_ITEM_EQ_MZ_ACL_ITEM_OID;
6226 params!(AclItem, AclItem) => BF::from(func::Eq) => Bool, 974;
6227 },
6228 "<>" => Scalar {
6229 params!(Numeric, Numeric) => BF::from(func::NotEq) => Bool, 1753;
6230 params!(Bool, Bool) => BF::from(func::NotEq) => Bool, 85;
6231 params!(Int16, Int16) => BF::from(func::NotEq) => Bool, 519;
6232 params!(Int32, Int32) => BF::from(func::NotEq) => Bool, 518;
6233 params!(Int64, Int64) => BF::from(func::NotEq) => Bool, 411;
6234 params!(UInt16, UInt16) => BF::from(func::NotEq) => Bool, oid::FUNC_NOT_EQ_UINT16_OID;
6235 params!(UInt32, UInt32) => BF::from(func::NotEq) => Bool, oid::FUNC_NOT_EQ_UINT32_OID;
6236 params!(UInt64, UInt64) => BF::from(func::NotEq) => Bool, oid::FUNC_NOT_EQ_UINT64_OID;
6237 params!(Float32, Float32) => BF::from(func::NotEq) => Bool, 621;
6238 params!(Float64, Float64) => BF::from(func::NotEq) => Bool, 671;
6239 params!(Oid, Oid) => BF::from(func::NotEq) => Bool, 608;
6240 params!(Date, Date) => BF::from(func::NotEq) => Bool, 1094;
6241 params!(Time, Time) => BF::from(func::NotEq) => Bool, 1109;
6242 params!(Timestamp, Timestamp) => BF::from(func::NotEq) => Bool, 2061;
6243 params!(TimestampTz, TimestampTz) => BF::from(func::NotEq) => Bool, 1321;
6244 params!(Uuid, Uuid) => BF::from(func::NotEq) => Bool, 2973;
6245 params!(Interval, Interval) => BF::from(func::NotEq) => Bool, 1331;
6246 params!(Bytes, Bytes) => BF::from(func::NotEq) => Bool, 1956;
6247 params!(String, String) => BF::from(func::NotEq) => Bool, 531;
6248 params!(Char, Char) => BF::from(func::NotEq) => Bool, 1057;
6249 params!(PgLegacyChar, PgLegacyChar) => BF::from(func::NotEq) => Bool, 630;
6250 params!(PgLegacyName, PgLegacyName) => BF::from(func::NotEq) => Bool, 643;
6251 params!(Jsonb, Jsonb) => BF::from(func::NotEq) => Bool, 3241;
6252 params!(ListAny, ListAny) => BF::from(func::NotEq) => Bool, oid::FUNC_LIST_NOT_EQ_OID;
6253 params!(ArrayAny, ArrayAny) => BF::from(func::NotEq) => Bool, 1071;
6254 params!(RecordAny, RecordAny) => BF::from(func::NotEq) => Bool, 2989;
6255 params!(MzTimestamp, MzTimestamp) => BF::from(func::NotEq)
6256 => Bool, oid::FUNC_MZ_TIMESTAMP_NOT_EQ_MZ_TIMESTAMP_OID;
6257 params!(RangeAny, RangeAny) => BF::from(func::NotEq) => Bool, 3883;
6258 params!(MzAclItem, MzAclItem) => BF::from(func::NotEq)
6259 => Bool, oid::FUNC_MZ_ACL_ITEM_NOT_EQ_MZ_ACL_ITEM_OID;
6260 }
6261 }
6262});
6263
6264pub fn resolve_op(op: &str) -> Result<&'static [FuncImpl<HirScalarExpr>], PlanError> {
6266 match OP_IMPLS.get(op) {
6267 Some(Func::Scalar(impls)) => Ok(impls),
6268 Some(_) => unreachable!("all operators must be scalar functions"),
6269 None => bail_unsupported!(format!("[{}]", op)),
6279 }
6280}
6281
6282fn current_settings(
6285 name: HirScalarExpr,
6286 missing_ok: HirScalarExpr,
6287) -> Result<HirScalarExpr, PlanError> {
6288 let expr = HirScalarExpr::call_binary(
6290 HirScalarExpr::call_unmaterializable(UnmaterializableFunc::ViewableVariables),
6291 HirScalarExpr::call_unary(name, UnaryFunc::Lower(func::Lower)),
6292 func::MapGetValue,
6293 );
6294 let expr = HirScalarExpr::if_then_else(
6295 missing_ok,
6296 expr.clone(),
6297 HirScalarExpr::call_variadic(
6298 variadic::ErrorIfNull,
6299 vec![
6300 expr,
6301 HirScalarExpr::literal(
6302 Datum::String("unrecognized configuration parameter"),
6303 SqlScalarType::String,
6304 ),
6305 ],
6306 ),
6307 );
6308 Ok(expr)
6309}