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