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_ore::collections::CollectionExt;
21use mz_ore::str::StrExt;
22use mz_pgrepr::oid;
23use mz_repr::role_id::RoleId;
24use mz_repr::{ColumnName, Datum, RelationType, ScalarBaseType, ScalarType};
25
26use crate::ast::{SelectStatement, Statement};
27use crate::catalog::{CatalogType, TypeCategory, TypeReference};
28use crate::names::{self, ResolvedItemName};
29use crate::plan::error::PlanError;
30use crate::plan::hir::{
31 AggregateFunc, BinaryFunc, CoercibleScalarExpr, CoercibleScalarType, ColumnOrder,
32 HirRelationExpr, HirScalarExpr, ScalarWindowFunc, TableFunc, UnaryFunc, UnmaterializableFunc,
33 ValueWindowFunc, VariadicFunc,
34};
35use crate::plan::query::{self, ExprContext, QueryContext};
36use crate::plan::scope::Scope;
37use crate::plan::side_effecting_func::PG_CATALOG_SEF_BUILTINS;
38use crate::plan::transform_ast;
39use crate::plan::typeconv::{self, CastContext};
40use crate::session::vars::{self, ENABLE_TIME_AT_TIME_ZONE};
41
42#[derive(Clone, Copy, Debug)]
44pub enum FuncSpec<'a> {
45 Func(&'a ResolvedItemName),
47 Op(&'a str),
49}
50
51impl<'a> fmt::Display for FuncSpec<'a> {
52 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53 match self {
54 FuncSpec::Func(n) => n.fmt(f),
55 FuncSpec::Op(o) => o.fmt(f),
56 }
57 }
58}
59
60impl TypeCategory {
61 pub fn from_type(typ: &ScalarType) -> Self {
73 match typ {
75 ScalarType::Array(..) | ScalarType::Int2Vector => Self::Array,
76 ScalarType::Bool => Self::Boolean,
77 ScalarType::AclItem
78 | ScalarType::Bytes
79 | ScalarType::Jsonb
80 | ScalarType::Uuid
81 | ScalarType::MzAclItem => Self::UserDefined,
82 ScalarType::Date
83 | ScalarType::Time
84 | ScalarType::Timestamp { .. }
85 | ScalarType::TimestampTz { .. } => Self::DateTime,
86 ScalarType::Float32
87 | ScalarType::Float64
88 | ScalarType::Int16
89 | ScalarType::Int32
90 | ScalarType::Int64
91 | ScalarType::UInt16
92 | ScalarType::UInt32
93 | ScalarType::UInt64
94 | ScalarType::Oid
95 | ScalarType::RegClass
96 | ScalarType::RegProc
97 | ScalarType::RegType
98 | ScalarType::Numeric { .. } => Self::Numeric,
99 ScalarType::Interval => Self::Timespan,
100 ScalarType::List { .. } => Self::List,
101 ScalarType::PgLegacyChar
102 | ScalarType::PgLegacyName
103 | ScalarType::String
104 | ScalarType::Char { .. }
105 | ScalarType::VarChar { .. } => Self::String,
106 ScalarType::Record { custom_id, .. } => {
107 if custom_id.is_some() {
108 Self::Composite
109 } else {
110 Self::Pseudo
111 }
112 }
113 ScalarType::Map { .. } => Self::Pseudo,
114 ScalarType::MzTimestamp => Self::Numeric,
115 ScalarType::Range { .. } => Self::Range,
116 }
117 }
118
119 pub fn from_param(param: &ParamType) -> Self {
120 match param {
121 ParamType::Any
122 | ParamType::AnyElement
123 | ParamType::ArrayAny
124 | ParamType::ArrayAnyCompatible
125 | ParamType::AnyCompatible
126 | ParamType::ListAny
127 | ParamType::ListAnyCompatible
128 | ParamType::ListElementAnyCompatible
129 | ParamType::Internal
130 | ParamType::NonVecAny
131 | ParamType::NonVecAnyCompatible
132 | ParamType::MapAny
133 | ParamType::MapAnyCompatible
134 | ParamType::RecordAny => Self::Pseudo,
135 ParamType::RangeAnyCompatible | ParamType::RangeAny => Self::Range,
136 ParamType::Plain(t) => Self::from_type(t),
137 }
138 }
139
140 pub fn from_catalog_type<T>(catalog_type: &CatalogType<T>) -> Self
144 where
145 T: TypeReference,
146 {
147 match catalog_type {
149 CatalogType::Array { .. } | CatalogType::Int2Vector => Self::Array,
150 CatalogType::Bool => Self::Boolean,
151 CatalogType::AclItem
152 | CatalogType::Bytes
153 | CatalogType::Jsonb
154 | CatalogType::Uuid
155 | CatalogType::MzAclItem => Self::UserDefined,
156 CatalogType::Date
157 | CatalogType::Time
158 | CatalogType::Timestamp
159 | CatalogType::TimestampTz => Self::DateTime,
160 CatalogType::Float32
161 | CatalogType::Float64
162 | CatalogType::Int16
163 | CatalogType::Int32
164 | CatalogType::Int64
165 | CatalogType::UInt16
166 | CatalogType::UInt32
167 | CatalogType::UInt64
168 | CatalogType::Oid
169 | CatalogType::RegClass
170 | CatalogType::RegProc
171 | CatalogType::RegType
172 | CatalogType::Numeric { .. } => Self::Numeric,
173 CatalogType::Interval => Self::Timespan,
174 CatalogType::List { .. } => Self::List,
175 CatalogType::PgLegacyChar
176 | CatalogType::PgLegacyName
177 | CatalogType::String
178 | CatalogType::Char { .. }
179 | CatalogType::VarChar { .. } => Self::String,
180 CatalogType::Record { .. } => TypeCategory::Composite,
181 CatalogType::Map { .. } | CatalogType::Pseudo => Self::Pseudo,
182 CatalogType::MzTimestamp => Self::String,
183 CatalogType::Range { .. } => Self::Range,
184 }
185 }
186
187 pub fn preferred_type(&self) -> Option<ScalarType> {
195 match self {
196 Self::Array
197 | Self::BitString
198 | Self::Composite
199 | Self::Enum
200 | Self::Geometric
201 | Self::List
202 | Self::NetworkAddress
203 | Self::Pseudo
204 | Self::Range
205 | Self::Unknown
206 | Self::UserDefined => None,
207 Self::Boolean => Some(ScalarType::Bool),
208 Self::DateTime => Some(ScalarType::TimestampTz { precision: None }),
209 Self::Numeric => Some(ScalarType::Float64),
210 Self::String => Some(ScalarType::String),
211 Self::Timespan => Some(ScalarType::Interval),
212 }
213 }
214}
215
216pub struct Operation<R>(
219 pub Box<
220 dyn Fn(
221 &ExprContext,
222 Vec<CoercibleScalarExpr>,
223 &ParamList,
224 Vec<ColumnOrder>,
225 ) -> Result<R, PlanError>
226 + Send
227 + Sync,
228 >,
229);
230
231impl<R> fmt::Debug for Operation<R> {
232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233 f.debug_struct("Operation").finish()
234 }
235}
236
237impl Operation<HirScalarExpr> {
238 fn identity() -> Operation<HirScalarExpr> {
240 Operation::unary(|_ecx, e| Ok(e))
241 }
242}
243
244impl<R> Operation<R> {
245 fn new<F>(f: F) -> Operation<R>
246 where
247 F: Fn(
248 &ExprContext,
249 Vec<CoercibleScalarExpr>,
250 &ParamList,
251 Vec<ColumnOrder>,
252 ) -> Result<R, PlanError>
253 + Send
254 + Sync
255 + 'static,
256 {
257 Operation(Box::new(f))
258 }
259
260 fn nullary<F>(f: F) -> Operation<R>
262 where
263 F: Fn(&ExprContext) -> Result<R, PlanError> + Send + Sync + 'static,
264 {
265 Self::variadic(move |ecx, exprs| {
266 assert!(exprs.is_empty());
267 f(ecx)
268 })
269 }
270
271 fn unary<F>(f: F) -> Operation<R>
273 where
274 F: Fn(&ExprContext, HirScalarExpr) -> Result<R, PlanError> + Send + Sync + 'static,
275 {
276 Self::variadic(move |ecx, exprs| f(ecx, exprs.into_element()))
277 }
278
279 fn unary_ordered<F>(f: F) -> Operation<R>
281 where
282 F: Fn(&ExprContext, HirScalarExpr, Vec<ColumnOrder>) -> Result<R, PlanError>
283 + Send
284 + Sync
285 + 'static,
286 {
287 Self::new(move |ecx, cexprs, params, order_by| {
288 let exprs = coerce_args_to_types(ecx, cexprs, params)?;
289 f(ecx, exprs.into_element(), order_by)
290 })
291 }
292
293 fn binary<F>(f: F) -> Operation<R>
295 where
296 F: Fn(&ExprContext, HirScalarExpr, HirScalarExpr) -> Result<R, PlanError>
297 + Send
298 + Sync
299 + 'static,
300 {
301 Self::variadic(move |ecx, exprs| {
302 assert_eq!(exprs.len(), 2);
303 let mut exprs = exprs.into_iter();
304 let left = exprs.next().unwrap();
305 let right = exprs.next().unwrap();
306 f(ecx, left, right)
307 })
308 }
309
310 fn binary_ordered<F>(f: F) -> Operation<R>
315 where
316 F: Fn(&ExprContext, HirScalarExpr, HirScalarExpr, Vec<ColumnOrder>) -> Result<R, PlanError>
317 + Send
318 + Sync
319 + 'static,
320 {
321 Self::new(move |ecx, cexprs, params, order_by| {
322 let exprs = coerce_args_to_types(ecx, cexprs, params)?;
323 assert_eq!(exprs.len(), 2);
324 let mut exprs = exprs.into_iter();
325 let left = exprs.next().unwrap();
326 let right = exprs.next().unwrap();
327 f(ecx, left, right, order_by)
328 })
329 }
330
331 fn variadic<F>(f: F) -> Operation<R>
333 where
334 F: Fn(&ExprContext, Vec<HirScalarExpr>) -> Result<R, PlanError> + Send + Sync + 'static,
335 {
336 Self::new(move |ecx, cexprs, params, _order_by| {
337 let exprs = coerce_args_to_types(ecx, cexprs, params)?;
338 f(ecx, exprs)
339 })
340 }
341}
342
343pub fn sql_impl(
346 expr: &str,
347) -> impl Fn(&QueryContext, Vec<ScalarType>) -> Result<HirScalarExpr, PlanError> + use<> {
348 let expr = mz_sql_parser::parser::parse_expr(expr).unwrap_or_else(|e| {
349 panic!(
350 "static function definition failed to parse {}: {}",
351 expr.quoted(),
352 e,
353 )
354 });
355 move |qcx, types| {
356 let mut scx = qcx.scx.clone();
359 scx.param_types = RefCell::new(
360 types
361 .into_iter()
362 .enumerate()
363 .map(|(i, ty)| (i + 1, ty))
364 .collect(),
365 );
366 let qcx = QueryContext::root(&scx, qcx.lifetime);
367
368 let (mut expr, _) = names::resolve(qcx.scx.catalog, expr.clone())?;
369 transform_ast::transform(&scx, &mut expr)?;
371
372 let ecx = ExprContext {
373 qcx: &qcx,
374 name: "static function definition",
375 scope: &Scope::empty(),
376 relation_type: &RelationType::empty(),
377 allow_aggregates: false,
378 allow_subqueries: true,
379 allow_parameters: true,
380 allow_windows: false,
381 };
382
383 query::plan_expr(&ecx, &expr)?.type_as_any(&ecx)
385 }
386}
387
388fn sql_impl_func(expr: &str) -> Operation<HirScalarExpr> {
402 let invoke = sql_impl(expr);
403 Operation::variadic(move |ecx, args| {
404 let types = args.iter().map(|arg| ecx.scalar_type(arg)).collect();
405 let mut out = invoke(ecx.qcx, types)?;
406 out.splice_parameters(&args, 0);
407 Ok(out)
408 })
409}
410
411fn sql_impl_table_func_inner(
424 sql: &'static str,
425 feature_flag: Option<&'static vars::FeatureFlag>,
426) -> Operation<TableFuncPlan> {
427 let query = match mz_sql_parser::parser::parse_statements(sql)
428 .expect("static function definition failed to parse")
429 .expect_element(|| "static function definition must have exactly one statement")
430 .ast
431 {
432 Statement::Select(SelectStatement { query, as_of: None }) => query,
433 _ => panic!("static function definition expected SELECT statement"),
434 };
435 let invoke = move |qcx: &QueryContext, types: Vec<ScalarType>| {
436 let mut scx = qcx.scx.clone();
439 scx.param_types = RefCell::new(
440 types
441 .into_iter()
442 .enumerate()
443 .map(|(i, ty)| (i + 1, ty))
444 .collect(),
445 );
446 let mut qcx = QueryContext::root(&scx, qcx.lifetime);
447
448 let query = query.clone();
449 let (mut query, _) = names::resolve(qcx.scx.catalog, query)?;
450 transform_ast::transform(&scx, &mut query)?;
451
452 query::plan_nested_query(&mut qcx, &query)
453 };
454
455 Operation::variadic(move |ecx, args| {
456 if let Some(feature_flag) = feature_flag {
457 ecx.require_feature_flag(feature_flag)?;
458 }
459 let types = args.iter().map(|arg| ecx.scalar_type(arg)).collect();
460 let (mut expr, scope) = invoke(ecx.qcx, types)?;
461 expr.splice_parameters(&args, 0);
462 Ok(TableFuncPlan {
463 imp: TableFuncImpl::Expr(expr),
464 column_names: scope.column_names().cloned().collect(),
465 })
466 })
467}
468
469fn sql_impl_table_func(sql: &'static str) -> Operation<TableFuncPlan> {
474 sql_impl_table_func_inner(sql, None)
475}
476
477fn experimental_sql_impl_table_func(
478 feature: &'static vars::FeatureFlag,
479 sql: &'static str,
480) -> Operation<TableFuncPlan> {
481 sql_impl_table_func_inner(sql, Some(feature))
482}
483
484pub struct FuncImpl<R> {
486 pub oid: u32,
487 pub params: ParamList,
488 pub return_type: ReturnType,
489 pub op: Operation<R>,
490}
491
492#[derive(Debug)]
494pub struct FuncImplCatalogDetails {
495 pub oid: u32,
496 pub arg_typs: Vec<&'static str>,
497 pub variadic_typ: Option<&'static str>,
498 pub return_typ: Option<&'static str>,
499 pub return_is_set: bool,
500}
501
502impl<R> FuncImpl<R> {
503 pub fn details(&self) -> FuncImplCatalogDetails {
504 FuncImplCatalogDetails {
505 oid: self.oid,
506 arg_typs: self.params.arg_names(),
507 variadic_typ: self.params.variadic_name(),
508 return_typ: self.return_type.typ.as_ref().map(|t| t.name()),
509 return_is_set: self.return_type.is_set_of,
510 }
511 }
512}
513
514impl<R> fmt::Debug for FuncImpl<R> {
515 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
516 f.debug_struct("FuncImpl")
517 .field("oid", &self.oid)
518 .field("params", &self.params)
519 .field("ret", &self.return_type)
520 .field("op", &"<omitted>")
521 .finish()
522 }
523}
524
525impl From<UnmaterializableFunc> for Operation<HirScalarExpr> {
526 fn from(n: UnmaterializableFunc) -> Operation<HirScalarExpr> {
527 Operation::nullary(move |_ecx| Ok(HirScalarExpr::call_unmaterializable(n.clone())))
528 }
529}
530
531impl From<UnaryFunc> for Operation<HirScalarExpr> {
532 fn from(u: UnaryFunc) -> Operation<HirScalarExpr> {
533 Operation::unary(move |_ecx, e| Ok(e.call_unary(u.clone())))
534 }
535}
536
537impl From<BinaryFunc> for Operation<HirScalarExpr> {
538 fn from(b: BinaryFunc) -> Operation<HirScalarExpr> {
539 Operation::binary(move |_ecx, left, right| Ok(left.call_binary(right, b.clone())))
540 }
541}
542
543impl From<VariadicFunc> for Operation<HirScalarExpr> {
544 fn from(v: VariadicFunc) -> Operation<HirScalarExpr> {
545 Operation::variadic(move |_ecx, exprs| Ok(HirScalarExpr::call_variadic(v.clone(), exprs)))
546 }
547}
548
549impl From<AggregateFunc> for Operation<(HirScalarExpr, AggregateFunc)> {
550 fn from(a: AggregateFunc) -> Operation<(HirScalarExpr, AggregateFunc)> {
551 Operation::unary(move |_ecx, e| Ok((e, a.clone())))
552 }
553}
554
555impl From<ScalarWindowFunc> for Operation<ScalarWindowFunc> {
556 fn from(a: ScalarWindowFunc) -> Operation<ScalarWindowFunc> {
557 Operation::nullary(move |_ecx| Ok(a.clone()))
558 }
559}
560
561impl From<ValueWindowFunc> for Operation<(HirScalarExpr, ValueWindowFunc)> {
562 fn from(a: ValueWindowFunc) -> Operation<(HirScalarExpr, ValueWindowFunc)> {
563 Operation::unary(move |_ecx, e| Ok((e, a.clone())))
564 }
565}
566
567#[derive(Debug, Clone, Eq, PartialEq, Hash)]
568pub enum ParamList {
572 Exact(Vec<ParamType>),
573 Variadic {
574 leading: Vec<ParamType>,
575 trailing: ParamType,
576 },
577}
578
579impl ParamList {
580 fn matches_argtypes(&self, ecx: &ExprContext, typs: &[CoercibleScalarType]) -> bool {
582 if !self.validate_arg_len(typs.len()) {
583 return false;
584 }
585
586 for (i, typ) in typs.iter().enumerate() {
587 let param = &self[i];
588 if let CoercibleScalarType::Coerced(typ) = typ {
589 if !param.accepts_type(ecx, typ) {
596 return false;
597 }
598 }
599 }
600
601 PolymorphicSolution::new(ecx, typs, self).is_some()
604 }
605
606 fn validate_arg_len(&self, input_len: usize) -> bool {
608 match self {
609 Self::Exact(p) => p.len() == input_len,
610 Self::Variadic { leading, .. } => input_len > leading.len(),
611 }
612 }
613
614 fn exact_match(&self, types: &[&ScalarType]) -> bool {
617 types.iter().enumerate().all(|(i, t)| self[i] == **t)
618 }
619
620 fn arg_names(&self) -> Vec<&'static str> {
622 match self {
623 ParamList::Exact(p) => p.iter().map(|p| p.name()).collect::<Vec<_>>(),
624 ParamList::Variadic { leading, trailing } => leading
625 .iter()
626 .chain([trailing])
627 .map(|p| p.name())
628 .collect::<Vec<_>>(),
629 }
630 }
631
632 fn variadic_name(&self) -> Option<&'static str> {
634 match self {
635 ParamList::Exact(_) => None,
636 ParamList::Variadic { trailing, .. } => Some(trailing.name()),
637 }
638 }
639}
640
641impl std::ops::Index<usize> for ParamList {
642 type Output = ParamType;
643
644 fn index(&self, i: usize) -> &Self::Output {
645 match self {
646 Self::Exact(p) => &p[i],
647 Self::Variadic { leading, trailing } => leading.get(i).unwrap_or(trailing),
648 }
649 }
650}
651
652impl From<Vec<ParamType>> for ParamList {
654 fn from(p: Vec<ParamType>) -> ParamList {
655 ParamList::Exact(p)
656 }
657}
658
659#[derive(Debug, Clone, Eq, PartialEq, Hash)]
660pub enum ParamType {
673 Any,
676 AnyCompatible,
679 AnyElement,
682 ArrayAny,
685 ArrayAnyCompatible,
688 ListAny,
691 ListAnyCompatible,
694 ListElementAnyCompatible,
699 MapAny,
702 MapAnyCompatible,
705 NonVecAny,
709 NonVecAnyCompatible,
713 Plain(ScalarType),
716 RecordAny,
719 RangeAny,
722 RangeAnyCompatible,
729 Internal,
732}
733
734impl ParamType {
735 fn accepts_type(&self, ecx: &ExprContext, t: &ScalarType) -> bool {
737 use ParamType::*;
738 use ScalarType::*;
739
740 match self {
741 Any | AnyElement | AnyCompatible | ListElementAnyCompatible => true,
742 ArrayAny | ArrayAnyCompatible => matches!(t, Array(..) | Int2Vector),
743 ListAny | ListAnyCompatible => matches!(t, List { .. }),
744 MapAny | MapAnyCompatible => matches!(t, Map { .. }),
745 RangeAny | RangeAnyCompatible => matches!(t, Range { .. }),
746 NonVecAny | NonVecAnyCompatible => !t.is_vec(),
747 Internal => false,
748 Plain(to) => typeconv::can_cast(ecx, CastContext::Implicit, t, to),
749 RecordAny => matches!(t, Record { .. }),
750 }
751 }
752
753 fn is_preferred_by(&self, t: &ScalarType) -> bool {
756 if let Some(pt) = TypeCategory::from_type(t).preferred_type() {
757 *self == pt
758 } else {
759 false
760 }
761 }
762
763 fn is_near_match(&self, t: &ScalarType) -> bool {
767 match (self, t.near_match()) {
768 (ParamType::Plain(t), Some(near_match)) => t.structural_eq(near_match),
769 _ => false,
770 }
771 }
772
773 fn prefers_self(&self) -> bool {
775 if let Some(pt) = TypeCategory::from_param(self).preferred_type() {
776 *self == pt
777 } else {
778 false
779 }
780 }
781
782 fn is_polymorphic(&self) -> bool {
783 use ParamType::*;
784 match self {
785 AnyElement
786 | ArrayAny
787 | ArrayAnyCompatible
788 | AnyCompatible
789 | ListAny
790 | ListAnyCompatible
791 | ListElementAnyCompatible
792 | MapAny
793 | MapAnyCompatible
794 | NonVecAny
795 | NonVecAnyCompatible
796 | RecordAny
800 | RangeAny
801 | RangeAnyCompatible => true,
802 Any | Internal | Plain(_) => false,
803 }
804 }
805
806 fn name(&self) -> &'static str {
807 match self {
808 ParamType::Plain(t) => {
809 assert!(
810 !t.is_custom_type(),
811 "custom types cannot currently be used as parameters; use a polymorphic parameter that accepts the custom type instead"
812 );
813 let t: mz_pgrepr::Type = t.into();
814 t.catalog_name()
815 }
816 ParamType::Any => "any",
817 ParamType::AnyCompatible => "anycompatible",
818 ParamType::AnyElement => "anyelement",
819 ParamType::ArrayAny => "anyarray",
820 ParamType::ArrayAnyCompatible => "anycompatiblearray",
821 ParamType::Internal => "internal",
822 ParamType::ListAny => "list",
823 ParamType::ListAnyCompatible => "anycompatiblelist",
824 ParamType::ListElementAnyCompatible => "anycompatible",
826 ParamType::MapAny => "map",
827 ParamType::MapAnyCompatible => "anycompatiblemap",
828 ParamType::NonVecAny => "anynonarray",
829 ParamType::NonVecAnyCompatible => "anycompatiblenonarray",
830 ParamType::RecordAny => "record",
831 ParamType::RangeAny => "anyrange",
832 ParamType::RangeAnyCompatible => "anycompatiblerange",
833 }
834 }
835}
836
837impl PartialEq<ScalarType> for ParamType {
838 fn eq(&self, other: &ScalarType) -> bool {
839 match self {
840 ParamType::Plain(s) => s.base_eq(other),
841 _ => false,
843 }
844 }
845}
846
847impl PartialEq<ParamType> for ScalarType {
848 fn eq(&self, other: &ParamType) -> bool {
849 other == self
850 }
851}
852
853impl From<ScalarType> for ParamType {
854 fn from(s: ScalarType) -> ParamType {
855 ParamType::Plain(s)
856 }
857}
858
859impl From<ScalarBaseType> for ParamType {
860 fn from(s: ScalarBaseType) -> ParamType {
861 use ScalarBaseType::*;
862 let s = match s {
863 Array | List | Map | Record | Range => {
864 panic!("use polymorphic parameters rather than {:?}", s);
865 }
866 AclItem => ScalarType::AclItem,
867 Bool => ScalarType::Bool,
868 Int16 => ScalarType::Int16,
869 Int32 => ScalarType::Int32,
870 Int64 => ScalarType::Int64,
871 UInt16 => ScalarType::UInt16,
872 UInt32 => ScalarType::UInt32,
873 UInt64 => ScalarType::UInt64,
874 Float32 => ScalarType::Float32,
875 Float64 => ScalarType::Float64,
876 Numeric => ScalarType::Numeric { max_scale: None },
877 Date => ScalarType::Date,
878 Time => ScalarType::Time,
879 Timestamp => ScalarType::Timestamp { precision: None },
880 TimestampTz => ScalarType::TimestampTz { precision: None },
881 Interval => ScalarType::Interval,
882 Bytes => ScalarType::Bytes,
883 String => ScalarType::String,
884 Char => ScalarType::Char { length: None },
885 VarChar => ScalarType::VarChar { max_length: None },
886 PgLegacyChar => ScalarType::PgLegacyChar,
887 PgLegacyName => ScalarType::PgLegacyName,
888 Jsonb => ScalarType::Jsonb,
889 Uuid => ScalarType::Uuid,
890 Oid => ScalarType::Oid,
891 RegClass => ScalarType::RegClass,
892 RegProc => ScalarType::RegProc,
893 RegType => ScalarType::RegType,
894 Int2Vector => ScalarType::Int2Vector,
895 MzTimestamp => ScalarType::MzTimestamp,
896 MzAclItem => ScalarType::MzAclItem,
897 };
898 ParamType::Plain(s)
899 }
900}
901
902#[derive(Debug, Clone, Eq, PartialEq, Hash)]
903pub struct ReturnType {
904 pub typ: Option<ParamType>,
905 pub is_set_of: bool,
906}
907
908impl ReturnType {
909 fn scalar(typ: ParamType) -> ReturnType {
911 ReturnType {
912 typ: Some(typ),
913 is_set_of: false,
914 }
915 }
916
917 fn set_of(typ: ParamType) -> ReturnType {
920 ReturnType {
921 typ: Some(typ),
922 is_set_of: true,
923 }
924 }
925
926 fn none(is_set_of: bool) -> ReturnType {
928 ReturnType {
929 typ: None,
930 is_set_of,
931 }
932 }
933}
934
935impl From<ParamType> for ReturnType {
936 fn from(typ: ParamType) -> ReturnType {
937 ReturnType::scalar(typ)
938 }
939}
940
941impl From<ScalarBaseType> for ReturnType {
942 fn from(s: ScalarBaseType) -> ReturnType {
943 ParamType::from(s).into()
944 }
945}
946
947impl From<ScalarType> for ReturnType {
948 fn from(s: ScalarType) -> ReturnType {
949 ParamType::Plain(s).into()
950 }
951}
952
953#[derive(Clone, Debug)]
954pub struct Candidate<'a, R> {
956 fimpl: &'a FuncImpl<R>,
958 exact_matches: usize,
959 preferred_types: usize,
960 near_matches: usize,
961}
962
963pub fn select_impl<R>(
977 ecx: &ExprContext,
978 spec: FuncSpec,
979 impls: &[FuncImpl<R>],
980 args: Vec<CoercibleScalarExpr>,
981 order_by: Vec<ColumnOrder>,
982) -> Result<R, PlanError>
983where
984 R: fmt::Debug,
985{
986 let name = spec.to_string();
987 let ecx = &ecx.with_name(&name);
988 let mut types: Vec<_> = args.iter().map(|e| ecx.scalar_type(e)).collect();
989
990 for ty in &mut types {
996 ty.force_coerced_if_record();
997 }
998
999 let impls: Vec<_> = impls
1004 .iter()
1005 .filter(|i| i.params.matches_argtypes(ecx, &types))
1006 .collect();
1007
1008 let f = find_match(ecx, &types, impls).map_err(|candidates| {
1009 let arg_types: Vec<_> = types
1010 .into_iter()
1011 .map(|ty| match ty {
1012 CoercibleScalarType::Coerced(ty) => ecx.humanize_scalar_type(&ty, false),
1014 CoercibleScalarType::Record(_) => "record".to_string(),
1015 CoercibleScalarType::Uncoerced => "unknown".to_string(),
1016 })
1017 .collect();
1018
1019 if candidates == 0 {
1020 match spec {
1021 FuncSpec::Func(name) => PlanError::UnknownFunction {
1022 name: ecx
1023 .qcx
1024 .scx
1025 .humanize_resolved_name(name)
1026 .expect("resolved to object")
1027 .to_string(),
1028 arg_types,
1029 },
1030 FuncSpec::Op(name) => PlanError::UnknownOperator {
1031 name: name.to_string(),
1032 arg_types,
1033 },
1034 }
1035 } else {
1036 match spec {
1037 FuncSpec::Func(name) => PlanError::IndistinctFunction {
1038 name: ecx
1039 .qcx
1040 .scx
1041 .humanize_resolved_name(name)
1042 .expect("resolved to object")
1043 .to_string(),
1044 arg_types,
1045 },
1046 FuncSpec::Op(name) => PlanError::IndistinctOperator {
1047 name: name.to_string(),
1048 arg_types,
1049 },
1050 }
1051 }
1052 })?;
1053
1054 (f.op.0)(ecx, args, &f.params, order_by)
1055}
1056
1057fn find_match<'a, R: std::fmt::Debug>(
1063 ecx: &ExprContext,
1064 types: &[CoercibleScalarType],
1065 impls: Vec<&'a FuncImpl<R>>,
1066) -> Result<&'a FuncImpl<R>, usize> {
1067 let all_types_known = types.iter().all(|t| t.is_coerced());
1068
1069 if all_types_known {
1071 let known_types: Vec<_> = types.iter().filter_map(|t| t.as_coerced()).collect();
1072 let matching_impls: Vec<&FuncImpl<_>> = impls
1073 .iter()
1074 .filter(|i| i.params.exact_match(&known_types))
1075 .cloned()
1076 .collect();
1077
1078 if matching_impls.len() == 1 {
1079 return Ok(matching_impls[0]);
1080 }
1081 }
1082
1083 let mut candidates: Vec<Candidate<_>> = Vec::new();
1087 macro_rules! maybe_get_last_candidate {
1088 () => {
1089 if candidates.len() == 1 {
1090 return Ok(&candidates[0].fimpl);
1091 }
1092 };
1093 }
1094 let mut max_exact_matches = 0;
1095
1096 for fimpl in impls {
1097 let mut exact_matches = 0;
1098 let mut preferred_types = 0;
1099 let mut near_matches = 0;
1100
1101 for (i, arg_type) in types.iter().enumerate() {
1102 let param_type = &fimpl.params[i];
1103
1104 match arg_type {
1105 CoercibleScalarType::Coerced(arg_type) => {
1106 if param_type == arg_type {
1107 exact_matches += 1;
1108 }
1109 if param_type.is_preferred_by(arg_type) {
1110 preferred_types += 1;
1111 }
1112 if param_type.is_near_match(arg_type) {
1113 near_matches += 1;
1114 }
1115 }
1116 CoercibleScalarType::Record(_) | CoercibleScalarType::Uncoerced => {
1117 if param_type.prefers_self() {
1118 preferred_types += 1;
1119 }
1120 }
1121 }
1122 }
1123
1124 max_exact_matches = std::cmp::max(max_exact_matches, exact_matches);
1129 candidates.push(Candidate {
1130 fimpl,
1131 exact_matches,
1132 preferred_types,
1133 near_matches,
1134 });
1135 }
1136
1137 if candidates.is_empty() {
1138 return Err(0);
1139 }
1140
1141 maybe_get_last_candidate!();
1142
1143 candidates.retain(|c| c.exact_matches >= max_exact_matches);
1146
1147 maybe_get_last_candidate!();
1148
1149 let mut max_near_matches = 0;
1154 for c in &candidates {
1155 max_near_matches = std::cmp::max(max_near_matches, c.near_matches);
1156 }
1157 candidates.retain(|c| c.near_matches >= max_near_matches);
1158
1159 let mut max_preferred_types = 0;
1163 for c in &candidates {
1164 max_preferred_types = std::cmp::max(max_preferred_types, c.preferred_types);
1165 }
1166 candidates.retain(|c| c.preferred_types >= max_preferred_types);
1167
1168 maybe_get_last_candidate!();
1169
1170 if all_types_known {
1171 return Err(candidates.len());
1172 }
1173
1174 let mut found_known = false;
1175 let mut types_match = true;
1176 let mut common_type: Option<ScalarType> = None;
1177
1178 for (i, arg_type) in types.iter().enumerate() {
1179 let mut selected_category: Option<TypeCategory> = None;
1180 let mut categories_match = true;
1181
1182 match arg_type {
1183 CoercibleScalarType::Uncoerced | CoercibleScalarType::Record(_) => {
1187 for c in candidates.iter() {
1188 let this_category = TypeCategory::from_param(&c.fimpl.params[i]);
1189 if this_category == TypeCategory::String {
1194 selected_category = Some(TypeCategory::String);
1195 break;
1196 }
1197 match selected_category {
1198 Some(ref mut selected_category) => {
1199 categories_match =
1202 selected_category == &this_category && categories_match;
1203 }
1204 None => selected_category = Some(this_category.clone()),
1205 }
1206 }
1207
1208 if selected_category != Some(TypeCategory::String) && !categories_match {
1212 break;
1213 }
1214
1215 let selected_category = selected_category.unwrap();
1220
1221 let preferred_type = selected_category.preferred_type();
1222 let mut found_preferred_type_candidate = false;
1223 candidates.retain(|c| {
1224 if let Some(typ) = &preferred_type {
1225 found_preferred_type_candidate = c.fimpl.params[i].accepts_type(ecx, typ)
1226 || found_preferred_type_candidate;
1227 }
1228 selected_category == TypeCategory::from_param(&c.fimpl.params[i])
1229 });
1230
1231 if found_preferred_type_candidate {
1232 let preferred_type = preferred_type.unwrap();
1233 candidates.retain(|c| c.fimpl.params[i].accepts_type(ecx, &preferred_type));
1234 }
1235 }
1236 CoercibleScalarType::Coerced(typ) => {
1237 found_known = true;
1238 match common_type {
1241 Some(ref common_type) => types_match = common_type == typ && types_match,
1242 None => common_type = Some(typ.clone()),
1243 }
1244 }
1245 }
1246 }
1247
1248 maybe_get_last_candidate!();
1249
1250 if found_known && types_match {
1256 let common_type = common_type.unwrap();
1257 let common_typed: Vec<_> = types
1258 .iter()
1259 .map(|t| match t {
1260 CoercibleScalarType::Coerced(t) => CoercibleScalarType::Coerced(t.clone()),
1261 CoercibleScalarType::Uncoerced | CoercibleScalarType::Record(_) => {
1262 CoercibleScalarType::Coerced(common_type.clone())
1263 }
1264 })
1265 .collect();
1266
1267 candidates.retain(|c| c.fimpl.params.matches_argtypes(ecx, &common_typed));
1268
1269 maybe_get_last_candidate!();
1270 }
1271
1272 Err(candidates.len())
1273}
1274
1275#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
1276enum PolymorphicCompatClass {
1277 Any,
1281 BestCommonAny,
1297 BestCommonList,
1306 BestCommonMap,
1311 StructuralEq,
1320}
1321
1322impl TryFrom<&ParamType> for PolymorphicCompatClass {
1323 type Error = ();
1324 fn try_from(param: &ParamType) -> Result<PolymorphicCompatClass, Self::Error> {
1325 use ParamType::*;
1326
1327 Ok(match param {
1328 AnyElement | ArrayAny | ListAny | MapAny | NonVecAny | RangeAny => {
1329 PolymorphicCompatClass::Any
1330 }
1331 ArrayAnyCompatible | AnyCompatible | RangeAnyCompatible | NonVecAnyCompatible => {
1332 PolymorphicCompatClass::BestCommonAny
1333 }
1334 ListAnyCompatible | ListElementAnyCompatible => PolymorphicCompatClass::BestCommonList,
1335 MapAnyCompatible => PolymorphicCompatClass::BestCommonMap,
1336 RecordAny => PolymorphicCompatClass::StructuralEq,
1337 _ => return Err(()),
1338 })
1339 }
1340}
1341
1342impl PolymorphicCompatClass {
1343 fn compatible(&self, ecx: &ExprContext, from: &ScalarType, to: &ScalarType) -> bool {
1344 use PolymorphicCompatClass::*;
1345 match self {
1346 StructuralEq => from.structural_eq(to),
1347 Any => from.base_eq(to),
1348 _ => typeconv::can_cast(ecx, CastContext::Implicit, from, to),
1349 }
1350 }
1351}
1352
1353#[derive(Debug)]
1356pub(crate) struct PolymorphicSolution {
1357 compat: Option<PolymorphicCompatClass>,
1360 seen: Vec<CoercibleScalarType>,
1361 key: Option<ScalarType>,
1363}
1364
1365impl PolymorphicSolution {
1366 fn new(
1373 ecx: &ExprContext,
1374 args: &[CoercibleScalarType],
1375 params: &ParamList,
1376 ) -> Option<PolymorphicSolution> {
1377 let mut r = PolymorphicSolution {
1378 compat: None,
1379 seen: vec![],
1380 key: None,
1381 };
1382
1383 for (i, scalar_type) in args.iter().cloned().enumerate() {
1384 r.track_seen(¶ms[i], scalar_type);
1385 }
1386
1387 if !r.determine_key(ecx) { None } else { Some(r) }
1388 }
1389
1390 fn track_seen(&mut self, param: &ParamType, seen: CoercibleScalarType) {
1393 use ParamType::*;
1394
1395 self.seen.push(match param {
1396 AnyElement | AnyCompatible | ListAnyCompatible | MapAnyCompatible | NonVecAny | RecordAny => seen,
1398 MapAny => seen.map_coerced(|array| array.unwrap_map_value_type().clone()),
1399 ListAny => seen.map_coerced(|array| array.unwrap_list_element_type().clone()),
1400 ArrayAny | ArrayAnyCompatible => seen.map_coerced(|array| array.unwrap_array_element_type().clone()),
1401 RangeAny | RangeAnyCompatible => seen.map_coerced(|range| range.unwrap_range_element_type().clone()),
1402 ListElementAnyCompatible => seen.map_coerced(|el| ScalarType::List {
1403 custom_id: None,
1404 element_type: Box::new(el),
1405 }),
1406 o => {
1407 assert!(
1408 !o.is_polymorphic(),
1409 "polymorphic parameters must track types they encounter to determine polymorphic solution"
1410 );
1411 return;
1412 }
1413 });
1414
1415 let compat_class = param
1416 .try_into()
1417 .expect("already returned for non-polymorphic params");
1418
1419 match &self.compat {
1420 None => self.compat = Some(compat_class),
1421 Some(c) => {
1422 assert_eq!(
1423 c, &compat_class,
1424 "do not know how to correlate polymorphic classes {:?} and {:?}",
1425 c, &compat_class,
1426 )
1427 }
1428 };
1429 }
1430
1431 fn determine_key(&mut self, ecx: &ExprContext) -> bool {
1435 self.key = if !self.seen.iter().any(|v| v.is_coerced()) {
1436 match &self.compat {
1437 None => None,
1439 Some(t) => match t {
1444 PolymorphicCompatClass::BestCommonAny => Some(ScalarType::String),
1445 PolymorphicCompatClass::BestCommonList => Some(ScalarType::List {
1446 custom_id: None,
1447 element_type: Box::new(ScalarType::String),
1448 }),
1449 PolymorphicCompatClass::BestCommonMap => Some(ScalarType::Map {
1450 value_type: Box::new(ScalarType::String),
1451 custom_id: None,
1452 }),
1453 PolymorphicCompatClass::StructuralEq | PolymorphicCompatClass::Any => None,
1455 },
1456 }
1457 } else {
1458 let compat = self.compat.as_ref().unwrap();
1461
1462 let r = match compat {
1463 PolymorphicCompatClass::Any => {
1464 let mut s = self
1465 .seen
1466 .iter()
1467 .filter_map(|f| f.as_coerced().cloned())
1468 .collect::<Vec<_>>();
1469 let (candiate, remaining) =
1470 s.split_first().expect("have at least one non-None element");
1471 if remaining.iter().all(|r| r.base_eq(candiate)) {
1472 s.remove(0)
1473 } else {
1474 return false;
1475 }
1476 }
1477 _ => match typeconv::guess_best_common_type(ecx, &self.seen) {
1478 Ok(r) => r,
1479 Err(_) => return false,
1480 },
1481 };
1482
1483 for t in self.seen.iter() {
1485 if let CoercibleScalarType::Coerced(t) = t {
1486 if !compat.compatible(ecx, t, &r) {
1487 return false;
1488 }
1489 }
1490 }
1491 Some(r)
1492 };
1493
1494 true
1495 }
1496
1497 fn target_for_param_type(&self, param: &ParamType) -> Option<ScalarType> {
1500 use ParamType::*;
1501 assert_eq!(
1502 self.compat,
1503 Some(
1504 param
1505 .try_into()
1506 .expect("target_for_param_type only supports polymorphic parameters")
1507 ),
1508 "cannot use polymorphic solution for different compatibility classes"
1509 );
1510
1511 assert!(
1512 !matches!(param, RecordAny),
1513 "RecordAny should not be cast to a target type"
1514 );
1515
1516 match param {
1517 AnyElement | AnyCompatible | ListAnyCompatible | MapAnyCompatible | NonVecAny => {
1518 self.key.clone()
1519 }
1520 ArrayAny | ArrayAnyCompatible => self
1521 .key
1522 .as_ref()
1523 .map(|key| ScalarType::Array(Box::new(key.clone()))),
1524 ListAny => self.key.as_ref().map(|key| ScalarType::List {
1525 element_type: Box::new(key.clone()),
1526 custom_id: None,
1527 }),
1528 MapAny => self.key.as_ref().map(|key| ScalarType::Map {
1529 value_type: Box::new(key.clone()),
1530 custom_id: None,
1531 }),
1532 RangeAny | RangeAnyCompatible => self.key.as_ref().map(|key| ScalarType::Range {
1533 element_type: Box::new(key.clone()),
1534 }),
1535 ListElementAnyCompatible => self
1536 .key
1537 .as_ref()
1538 .map(|key| key.unwrap_list_element_type().clone()),
1539 _ => unreachable!(
1540 "cannot use polymorphic solution to resolve target type for param {:?}",
1541 param,
1542 ),
1543 }
1544 }
1545}
1546
1547fn coerce_args_to_types(
1548 ecx: &ExprContext,
1549 args: Vec<CoercibleScalarExpr>,
1550 params: &ParamList,
1551) -> Result<Vec<HirScalarExpr>, PlanError> {
1552 use ParamType::*;
1553
1554 let mut scalar_types: Vec<_> = args.iter().map(|e| ecx.scalar_type(e)).collect();
1555
1556 for ty in &mut scalar_types {
1558 ty.force_coerced_if_record();
1559 }
1560
1561 let polymorphic_solution = PolymorphicSolution::new(ecx, &scalar_types, params)
1562 .expect("polymorphic solution previously determined to be valid");
1563
1564 let do_convert =
1565 |arg: CoercibleScalarExpr, ty: &ScalarType| arg.cast_to(ecx, CastContext::Implicit, ty);
1566
1567 let mut res_exprs = Vec::with_capacity(args.len());
1568 for (i, cexpr) in args.into_iter().enumerate() {
1569 let expr = match ¶ms[i] {
1570 Any => match cexpr {
1571 CoercibleScalarExpr::Parameter(n) => {
1572 sql_bail!("could not determine data type of parameter ${}", n)
1573 }
1574 _ => cexpr.type_as_any(ecx)?,
1575 },
1576 RecordAny => match cexpr {
1577 CoercibleScalarExpr::LiteralString(_) => {
1578 sql_bail!("input of anonymous composite types is not implemented");
1579 }
1580 _ => cexpr.type_as_any(ecx)?,
1584 },
1585 Plain(ty) => do_convert(cexpr, ty)?,
1586 Internal => return Err(PlanError::InternalFunctionCall),
1587 p => {
1588 let target = polymorphic_solution
1589 .target_for_param_type(p)
1590 .ok_or_else(|| {
1591 PlanError::UnsolvablePolymorphicFunctionInput
1600 })?;
1601 do_convert(cexpr, &target)?
1602 }
1603 };
1604 res_exprs.push(expr);
1605 }
1606
1607 Ok(res_exprs)
1608}
1609
1610macro_rules! params {
1612 ([$($p:expr),*], $v:ident...) => { ParamList::Variadic { leading: vec![$($p.into(),)*], trailing: $v.into() } };
1613 ($v:ident...) => { ParamList::Variadic { leading: vec![], trailing: $v.into() } };
1614 ($($p:expr),*) => { ParamList::Exact(vec![$($p.into(),)*]) };
1615}
1616
1617macro_rules! impl_def {
1618 ($params:expr, $op:expr, $return_type:expr, $oid:expr) => {{
1628 FuncImpl {
1629 oid: $oid,
1630 params: $params.into(),
1631 op: $op.into(),
1632 return_type: $return_type.into(),
1633 }
1634 }};
1635}
1636
1637macro_rules! builtins {
1639 {
1640 $(
1641 $name:expr => $ty:ident {
1642 $($params:expr => $op:expr => $return_type:expr, $oid:expr;)+
1643 }
1644 ),+
1645 } => {{
1646
1647 let mut builtins = BTreeMap::new();
1648 $(
1649 let impls = vec![$(impl_def!($params, $op, $return_type, $oid)),+];
1650 let func = Func::$ty(impls);
1651 let expect_set_return = matches!(&func, Func::Table(_));
1652 for imp in func.func_impls() {
1653 assert_eq!(imp.return_is_set, expect_set_return, "wrong set return value for func with oid {}", imp.oid);
1654 }
1655 let old = builtins.insert($name, func);
1656 mz_ore::assert_none!(old, "duplicate entry in builtins list");
1657 )+
1658 builtins
1659 }};
1660}
1661
1662#[derive(Debug)]
1663pub struct TableFuncPlan {
1664 pub imp: TableFuncImpl,
1665 pub column_names: Vec<ColumnName>,
1666}
1667
1668#[derive(Debug)]
1701pub enum TableFuncImpl {
1702 CallTable {
1703 func: TableFunc,
1704 exprs: Vec<HirScalarExpr>,
1705 },
1706 Expr(HirRelationExpr),
1707}
1708
1709#[derive(Debug)]
1710pub enum Func {
1711 Scalar(Vec<FuncImpl<HirScalarExpr>>),
1712 Aggregate(Vec<FuncImpl<(HirScalarExpr, AggregateFunc)>>),
1713 Table(Vec<FuncImpl<TableFuncPlan>>),
1714 ScalarWindow(Vec<FuncImpl<ScalarWindowFunc>>),
1715 ValueWindow(Vec<FuncImpl<(HirScalarExpr, ValueWindowFunc)>>),
1716}
1717
1718impl Func {
1719 pub fn func_impls(&self) -> Vec<FuncImplCatalogDetails> {
1720 match self {
1721 Func::Scalar(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1722 Func::Aggregate(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1723 Func::Table(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1724 Func::ScalarWindow(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1725 Func::ValueWindow(impls) => impls.iter().map(|f| f.details()).collect::<Vec<_>>(),
1726 }
1727 }
1728
1729 pub fn class(&self) -> &str {
1730 match self {
1731 Func::Scalar(..) => "scalar",
1732 Func::Aggregate(..) => "aggregate",
1733 Func::Table(..) => "table",
1734 Func::ScalarWindow(..) => "window",
1735 Func::ValueWindow(..) => "window",
1736 }
1737 }
1738}
1739
1740macro_rules! catalog_name_only {
1744 ($name:expr) => {
1745 panic!(
1746 "{} should be planned away before reaching function selection",
1747 $name
1748 )
1749 };
1750}
1751
1752macro_rules! privilege_fn {
1754 ( $fn_name:expr, $catalog_tbl:expr ) => {
1755 {
1756 let fn_name = $fn_name;
1757 let catalog_tbl = $catalog_tbl;
1758 let public_role = RoleId::Public;
1759 format!(
1760 "
1761 CASE
1762 -- We need to validate the privileges to return a proper error before anything
1763 -- else.
1764 WHEN NOT mz_internal.mz_validate_privileges($3)
1765 OR $1 IS NULL
1766 OR $2 IS NULL
1767 OR $3 IS NULL
1768 OR $1 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
1769 OR $2 NOT IN (SELECT oid FROM {catalog_tbl})
1770 THEN NULL
1771 ELSE COALESCE(
1772 (
1773 SELECT
1774 bool_or(
1775 mz_internal.mz_acl_item_contains_privilege(privilege, $3)
1776 )
1777 AS {fn_name}
1778 FROM
1779 (
1780 SELECT
1781 unnest(privileges)
1782 FROM
1783 {catalog_tbl}
1784 WHERE
1785 {catalog_tbl}.oid = $2
1786 )
1787 AS user_privs (privilege)
1788 LEFT JOIN mz_catalog.mz_roles ON
1789 mz_internal.mz_aclitem_grantee(privilege) = mz_roles.id
1790 WHERE
1791 mz_internal.mz_aclitem_grantee(privilege) = '{public_role}' OR pg_has_role($1, mz_roles.oid, 'USAGE')
1792 ),
1793 false
1794 )
1795 END
1796 ",
1797 )
1798 }
1799 };
1800}
1801
1802pub static PG_CATALOG_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
1804 use ParamType::*;
1805 use ScalarBaseType::*;
1806 let mut builtins = builtins! {
1807 "abs" => Scalar {
1820 params!(Int16) => UnaryFunc::AbsInt16(func::AbsInt16) => Int16, 1398;
1821 params!(Int32) => UnaryFunc::AbsInt32(func::AbsInt32) => Int32, 1397;
1822 params!(Int64) => UnaryFunc::AbsInt64(func::AbsInt64) => Int64, 1396;
1823 params!(Numeric) => UnaryFunc::AbsNumeric(func::AbsNumeric) => Numeric, 1705;
1824 params!(Float32) => UnaryFunc::AbsFloat32(func::AbsFloat32) => Float32, 1394;
1825 params!(Float64) => UnaryFunc::AbsFloat64(func::AbsFloat64) => Float64, 1395;
1826 },
1827 "aclexplode" => Table {
1828 params!(ScalarType::Array(Box::new(ScalarType::AclItem))) => Operation::unary(move |_ecx, aclitems| {
1829 Ok(TableFuncPlan {
1830 imp: TableFuncImpl::CallTable {
1831 func: TableFunc::AclExplode,
1832 exprs: vec![aclitems],
1833 },
1834 column_names: vec!["grantor".into(), "grantee".into(), "privilege_type".into(), "is_grantable".into()],
1835 })
1836 }) => ReturnType::set_of(RecordAny), 1689;
1837 },
1838 "array_cat" => Scalar {
1839 params!(ArrayAnyCompatible, ArrayAnyCompatible) => Operation::binary(|_ecx, lhs, rhs| {
1840 Ok(lhs.call_binary(rhs, BinaryFunc::ArrayArrayConcat))
1841 }) => ArrayAnyCompatible, 383;
1842 },
1843 "array_fill" => Scalar {
1844 params!(AnyElement, ScalarType::Array(Box::new(ScalarType::Int32))) => Operation::binary(|ecx, elem, dims| {
1845 let elem_type = ecx.scalar_type(&elem);
1846
1847 let elem_type = match elem_type.array_of_self_elem_type() {
1848 Ok(elem_type) => elem_type,
1849 Err(elem_type) => bail_unsupported!(
1850 format!("array_fill on {}", ecx.humanize_scalar_type(&elem_type, false))
1852 ),
1853 };
1854
1855 Ok(HirScalarExpr::call_variadic(VariadicFunc::ArrayFill { elem_type }, vec![elem, dims]))
1856 }) => ArrayAny, 1193;
1857 params!(
1858 AnyElement,
1859 ScalarType::Array(Box::new(ScalarType::Int32)),
1860 ScalarType::Array(Box::new(ScalarType::Int32))
1861 ) => Operation::variadic(|ecx, exprs| {
1862 let elem_type = ecx.scalar_type(&exprs[0]);
1863
1864 let elem_type = match elem_type.array_of_self_elem_type() {
1865 Ok(elem_type) => elem_type,
1866 Err(elem_type) => bail_unsupported!(
1867 format!("array_fill on {}", ecx.humanize_scalar_type(&elem_type, false))
1868 ),
1869 };
1870
1871 Ok(HirScalarExpr::call_variadic(VariadicFunc::ArrayFill { elem_type }, exprs))
1872 }) => ArrayAny, 1286;
1873 },
1874 "array_length" => Scalar {
1875 params![ArrayAny, Int64] => BinaryFunc::ArrayLength => Int32, 2176;
1876 },
1877 "array_lower" => Scalar {
1878 params!(ArrayAny, Int64) => BinaryFunc::ArrayLower => Int32, 2091;
1879 },
1880 "array_position" => Scalar {
1881 params!(ArrayAnyCompatible, AnyCompatible) => VariadicFunc::ArrayPosition => Int32, 3277;
1882 params!(ArrayAnyCompatible, AnyCompatible, Int32) => VariadicFunc::ArrayPosition => Int32, 3278;
1883 },
1884 "array_remove" => Scalar {
1885 params!(ArrayAnyCompatible, AnyCompatible) => BinaryFunc::ArrayRemove => ArrayAnyCompatible, 3167;
1886 },
1887 "array_to_string" => Scalar {
1888 params!(ArrayAny, String) => Operation::variadic(array_to_string) => String, 395;
1889 params!(ArrayAny, String, String) => Operation::variadic(array_to_string) => String, 384;
1890 },
1891 "array_upper" => Scalar {
1892 params!(ArrayAny, Int64) => BinaryFunc::ArrayUpper => Int32, 2092;
1893 },
1894 "ascii" => Scalar {
1895 params!(String) => UnaryFunc::Ascii(func::Ascii) => Int32, 1620;
1896 },
1897 "avg" => Scalar {
1898 params!(Int64) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Numeric, 2100;
1899 params!(Int32) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Numeric, 2101;
1900 params!(Int16) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Numeric, 2102;
1901 params!(UInt64) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Numeric, oid::FUNC_AVG_UINT64_OID;
1902 params!(UInt32) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Numeric, oid::FUNC_AVG_UINT32_OID;
1903 params!(UInt16) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Numeric, oid::FUNC_AVG_UINT16_OID;
1904 params!(Float32) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Float64, 2104;
1905 params!(Float64) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Float64, 2105;
1906 params!(Interval) => Operation::nullary(|_ecx| catalog_name_only!("avg")) => Interval, 2106;
1907 },
1908 "bit_count" => Scalar {
1909 params!(Bytes) => UnaryFunc::BitCountBytes(func::BitCountBytes) => Int64, 6163;
1910 },
1911 "bit_length" => Scalar {
1912 params!(Bytes) => UnaryFunc::BitLengthBytes(func::BitLengthBytes) => Int32, 1810;
1913 params!(String) => UnaryFunc::BitLengthString(func::BitLengthString) => Int32, 1811;
1914 },
1915 "btrim" => Scalar {
1916 params!(String) => UnaryFunc::TrimWhitespace(func::TrimWhitespace) => String, 885;
1917 params!(String, String) => BinaryFunc::Trim => String, 884;
1918 },
1919 "cbrt" => Scalar {
1920 params!(Float64) => UnaryFunc::CbrtFloat64(func::CbrtFloat64) => Float64, 1345;
1921 },
1922 "ceil" => Scalar {
1923 params!(Float32) => UnaryFunc::CeilFloat32(func::CeilFloat32) => Float32, oid::FUNC_CEIL_F32_OID;
1924 params!(Float64) => UnaryFunc::CeilFloat64(func::CeilFloat64) => Float64, 2308;
1925 params!(Numeric) => UnaryFunc::CeilNumeric(func::CeilNumeric) => Numeric, 1711;
1926 },
1927 "ceiling" => Scalar {
1928 params!(Float32) => UnaryFunc::CeilFloat32(func::CeilFloat32) => Float32, oid::FUNC_CEILING_F32_OID;
1929 params!(Float64) => UnaryFunc::CeilFloat64(func::CeilFloat64) => Float64, 2320;
1930 params!(Numeric) => UnaryFunc::CeilNumeric(func::CeilNumeric) => Numeric, 2167;
1931 },
1932 "char_length" => Scalar {
1933 params!(String) => UnaryFunc::CharLength(func::CharLength) => Int32, 1381;
1934 },
1935 "col_description" => Scalar {
1937 params!(Oid, Int32) => sql_impl_func(
1938 "(SELECT description
1939 FROM pg_description
1940 WHERE objoid = $1 AND classoid = 'pg_class'::regclass AND objsubid = $2)"
1941 ) => String, 1216;
1942 },
1943 "concat" => Scalar {
1944 params!(Any...) => Operation::variadic(|ecx, cexprs| {
1945 if cexprs.is_empty() {
1946 sql_bail!("No function matches the given name and argument types. \
1947 You might need to add explicit type casts.")
1948 }
1949 let mut exprs = vec![];
1950 for expr in cexprs {
1951 exprs.push(match ecx.scalar_type(&expr) {
1952 ScalarType::Bool => expr.call_unary(UnaryFunc::CastBoolToStringNonstandard(func::CastBoolToStringNonstandard)),
1955 ScalarType::Char { length } => expr.call_unary(UnaryFunc::PadChar(func::PadChar { length })),
1957 _ => typeconv::to_string(ecx, expr)
1958 });
1959 }
1960 Ok(HirScalarExpr::call_variadic(VariadicFunc::Concat, exprs))
1961 }) => String, 3058;
1962 },
1963 "concat_ws" => Scalar {
1964 params!([String], Any...) => Operation::variadic(|ecx, cexprs| {
1965 if cexprs.len() < 2 {
1966 sql_bail!("No function matches the given name and argument types. \
1967 You might need to add explicit type casts.")
1968 }
1969 let mut exprs = vec![];
1970 for expr in cexprs {
1971 exprs.push(match ecx.scalar_type(&expr) {
1972 ScalarType::Bool => expr.call_unary(UnaryFunc::CastBoolToStringNonstandard(func::CastBoolToStringNonstandard)),
1975 ScalarType::Char { length } => expr.call_unary(UnaryFunc::PadChar(func::PadChar { length })),
1977 _ => typeconv::to_string(ecx, expr)
1978 });
1979 }
1980 Ok(HirScalarExpr::call_variadic(VariadicFunc::ConcatWs, exprs))
1981 }) => String, 3059;
1982 },
1983 "convert_from" => Scalar {
1984 params!(Bytes, String) => BinaryFunc::ConvertFrom => String, 1714;
1985 },
1986 "cos" => Scalar {
1987 params!(Float64) => UnaryFunc::Cos(func::Cos) => Float64, 1605;
1988 },
1989 "acos" => Scalar {
1990 params!(Float64) => UnaryFunc::Acos(func::Acos) => Float64, 1601;
1991 },
1992 "cosh" => Scalar {
1993 params!(Float64) => UnaryFunc::Cosh(func::Cosh) => Float64, 2463;
1994 },
1995 "acosh" => Scalar {
1996 params!(Float64) => UnaryFunc::Acosh(func::Acosh) => Float64, 2466;
1997 },
1998 "cot" => Scalar {
1999 params!(Float64) => UnaryFunc::Cot(func::Cot) => Float64, 1607;
2000 },
2001 "current_schema" => Scalar {
2002 params!() => UnmaterializableFunc::CurrentSchema => String, 1402;
2006 },
2007 "current_schemas" => Scalar {
2008 params!(Bool) => Operation::unary(|_ecx, e| {
2009 Ok(HirScalarExpr::if_then_else(
2010 e,
2011 HirScalarExpr::call_unmaterializable(UnmaterializableFunc::CurrentSchemasWithSystem),
2012 HirScalarExpr::call_unmaterializable(UnmaterializableFunc::CurrentSchemasWithoutSystem),
2013 ))
2014 }) => ScalarType::Array(Box::new(ScalarType::String)), 1403;
2018 },
2019 "current_database" => Scalar {
2020 params!() => UnmaterializableFunc::CurrentDatabase => String, 861;
2021 },
2022 "current_catalog" => Scalar {
2023 params!() => UnmaterializableFunc::CurrentDatabase => String, oid::FUNC_CURRENT_CATALOG;
2024 },
2025 "current_setting" => Scalar {
2026 params!(String) => Operation::unary(|_ecx, name| {
2027 current_settings(name, HirScalarExpr::literal_false())
2028 }) => ScalarType::String, 2077;
2029 params!(String, Bool) => Operation::binary(|_ecx, name, missing_ok| {
2030 current_settings(name, missing_ok)
2031 }) => ScalarType::String, 3294;
2032 },
2033 "current_timestamp" => Scalar {
2034 params!() => UnmaterializableFunc::CurrentTimestamp => TimestampTz, oid::FUNC_CURRENT_TIMESTAMP_OID;
2035 },
2036 "current_user" => Scalar {
2037 params!() => UnmaterializableFunc::CurrentUser => String, 745;
2038 },
2039 "current_role" => Scalar {
2040 params!() => UnmaterializableFunc::CurrentUser => String, oid::FUNC_CURRENT_ROLE;
2041 },
2042 "user" => Scalar {
2043 params!() => UnmaterializableFunc::CurrentUser => String, oid::FUNC_USER;
2044 },
2045 "session_user" => Scalar {
2046 params!() => UnmaterializableFunc::SessionUser => String, 746;
2047 },
2048 "chr" => Scalar {
2049 params!(Int32) => UnaryFunc::Chr(func::Chr) => String, 1621;
2050 },
2051 "date" => Scalar {
2052 params!(String) => UnaryFunc::CastStringToDate(func::CastStringToDate) => Date, oid::FUNC_DATE_FROM_TEXT;
2053 params!(Timestamp) => UnaryFunc::CastTimestampToDate(func::CastTimestampToDate) => Date, 2029;
2054 params!(TimestampTz) => UnaryFunc::CastTimestampTzToDate(func::CastTimestampTzToDate) => Date, 1178;
2055 },
2056 "date_bin" => Scalar {
2057 params!(Interval, Timestamp) => Operation::binary(|ecx, stride, source| {
2058 ecx.require_feature_flag(&vars::ENABLE_BINARY_DATE_BIN)?;
2059 Ok(stride.call_binary(source, BinaryFunc::DateBinTimestamp))
2060 }) => Timestamp, oid::FUNC_MZ_DATE_BIN_UNIX_EPOCH_TS_OID;
2061 params!(Interval, TimestampTz) => Operation::binary(|ecx, stride, source| {
2062 ecx.require_feature_flag(&vars::ENABLE_BINARY_DATE_BIN)?;
2063 Ok(stride.call_binary(source, BinaryFunc::DateBinTimestampTz))
2064 }) => TimestampTz, oid::FUNC_MZ_DATE_BIN_UNIX_EPOCH_TSTZ_OID;
2065 params!(Interval, Timestamp, Timestamp) => VariadicFunc::DateBinTimestamp => Timestamp, 6177;
2066 params!(Interval, TimestampTz, TimestampTz) => VariadicFunc::DateBinTimestampTz => TimestampTz, 6178;
2067 },
2068 "extract" => Scalar {
2069 params!(String, Interval) => BinaryFunc::ExtractInterval => Numeric, 6204;
2070 params!(String, Time) => BinaryFunc::ExtractTime => Numeric, 6200;
2071 params!(String, Timestamp) => BinaryFunc::ExtractTimestamp => Numeric, 6202;
2072 params!(String, TimestampTz) => BinaryFunc::ExtractTimestampTz => Numeric, 6203;
2073 params!(String, Date) => BinaryFunc::ExtractDate => Numeric, 6199;
2074 },
2075 "date_part" => Scalar {
2076 params!(String, Interval) => BinaryFunc::DatePartInterval => Float64, 1172;
2077 params!(String, Time) => BinaryFunc::DatePartTime => Float64, 1385;
2078 params!(String, Timestamp) => BinaryFunc::DatePartTimestamp => Float64, 2021;
2079 params!(String, TimestampTz) => BinaryFunc::DatePartTimestampTz => Float64, 1171;
2080 },
2081 "date_trunc" => Scalar {
2082 params!(String, Timestamp) => BinaryFunc::DateTruncTimestamp => Timestamp, 2020;
2083 params!(String, TimestampTz) => BinaryFunc::DateTruncTimestampTz => TimestampTz, 1217;
2084 params!(String, Interval) => BinaryFunc::DateTruncInterval => Interval, 1218;
2085 },
2086 "daterange" => Scalar {
2087 params!(Date, Date) => Operation::variadic(|_ecx, mut exprs| {
2088 exprs.push(HirScalarExpr::literal(Datum::String("[)"), ScalarType::String));
2089 Ok(HirScalarExpr::call_variadic(VariadicFunc::RangeCreate { elem_type: ScalarType::Date },
2090 exprs))
2091 }) => ScalarType::Range { element_type: Box::new(ScalarType::Date)}, 3941;
2092 params!(Date, Date, String) => Operation::variadic(|_ecx, exprs| {
2093 Ok(HirScalarExpr::call_variadic(VariadicFunc::RangeCreate { elem_type: ScalarType::Date },
2094 exprs))
2095 }) => ScalarType::Range { element_type: Box::new(ScalarType::Date)}, 3942;
2096 },
2097 "degrees" => Scalar {
2098 params!(Float64) => UnaryFunc::Degrees(func::Degrees) => Float64, 1608;
2099 },
2100 "digest" => Scalar {
2101 params!(String, String) => BinaryFunc::DigestString => Bytes, oid::FUNC_PG_DIGEST_STRING;
2102 params!(Bytes, String) => BinaryFunc::DigestBytes => Bytes, oid::FUNC_PG_DIGEST_BYTES;
2103 },
2104 "exp" => Scalar {
2105 params!(Float64) => UnaryFunc::Exp(func::Exp) => Float64, 1347;
2106 params!(Numeric) => UnaryFunc::ExpNumeric(func::ExpNumeric) => Numeric, 1732;
2107 },
2108 "floor" => Scalar {
2109 params!(Float32) => UnaryFunc::FloorFloat32(func::FloorFloat32) => Float32, oid::FUNC_FLOOR_F32_OID;
2110 params!(Float64) => UnaryFunc::FloorFloat64(func::FloorFloat64) => Float64, 2309;
2111 params!(Numeric) => UnaryFunc::FloorNumeric(func::FloorNumeric) => Numeric, 1712;
2112 },
2113 "format_type" => Scalar {
2114 params!(Oid, Int32) => sql_impl_func(
2115 "CASE
2116 WHEN $1 IS NULL THEN NULL
2117 -- timestamp and timestamptz have the typmod in
2118 -- a nonstandard location that requires special
2119 -- handling.
2120 WHEN $1 = 1114 AND $2 >= 0 THEN 'timestamp(' || $2 || ') without time zone'
2121 WHEN $1 = 1184 AND $2 >= 0 THEN 'timestamp(' || $2 || ') with time zone'
2122 ELSE coalesce((SELECT pg_catalog.concat(coalesce(mz_internal.mz_type_name($1), name), mz_internal.mz_render_typmod($1, $2)) FROM mz_catalog.mz_types WHERE oid = $1), '???')
2123 END"
2124 ) => String, 1081;
2125 },
2126 "get_bit" => Scalar {
2127 params!(Bytes, Int32) => BinaryFunc::GetBit => Int32, 723;
2128 },
2129 "get_byte" => Scalar {
2130 params!(Bytes, Int32) => BinaryFunc::GetByte => Int32, 721;
2131 },
2132 "pg_get_ruledef" => Scalar {
2133 params!(Oid) => sql_impl_func("NULL::pg_catalog.text") => String, 1573;
2134 params!(Oid, Bool) => sql_impl_func("NULL::pg_catalog.text") => String, 2504;
2135 },
2136 "has_schema_privilege" => Scalar {
2137 params!(String, String, String) => sql_impl_func("has_schema_privilege(mz_internal.mz_role_oid($1), mz_internal.mz_schema_oid($2), $3)") => Bool, 2268;
2138 params!(String, Oid, String) => sql_impl_func("has_schema_privilege(mz_internal.mz_role_oid($1), $2, $3)") => Bool, 2269;
2139 params!(Oid, String, String) => sql_impl_func("has_schema_privilege($1, mz_internal.mz_schema_oid($2), $3)") => Bool, 2270;
2140 params!(Oid, Oid, String) => sql_impl_func(&privilege_fn!("has_schema_privilege", "mz_schemas")) => Bool, 2271;
2141 params!(String, String) => sql_impl_func("has_schema_privilege(current_user, $1, $2)") => Bool, 2272;
2142 params!(Oid, String) => sql_impl_func("has_schema_privilege(current_user, $1, $2)") => Bool, 2273;
2143 },
2144 "has_database_privilege" => Scalar {
2145 params!(String, String, String) => sql_impl_func("has_database_privilege(mz_internal.mz_role_oid($1), mz_internal.mz_database_oid($2), $3)") => Bool, 2250;
2146 params!(String, Oid, String) => sql_impl_func("has_database_privilege(mz_internal.mz_role_oid($1), $2, $3)") => Bool, 2251;
2147 params!(Oid, String, String) => sql_impl_func("has_database_privilege($1, mz_internal.mz_database_oid($2), $3)") => Bool, 2252;
2148 params!(Oid, Oid, String) => sql_impl_func(&privilege_fn!("has_database_privilege", "mz_databases")) => Bool, 2253;
2149 params!(String, String) => sql_impl_func("has_database_privilege(current_user, $1, $2)") => Bool, 2254;
2150 params!(Oid, String) => sql_impl_func("has_database_privilege(current_user, $1, $2)") => Bool, 2255;
2151 },
2152 "has_table_privilege" => Scalar {
2153 params!(String, String, String) => sql_impl_func("has_table_privilege(mz_internal.mz_role_oid($1), $2::regclass::oid, $3)") => Bool, 1922;
2154 params!(String, Oid, String) => sql_impl_func("has_table_privilege(mz_internal.mz_role_oid($1), $2, $3)") => Bool, 1923;
2155 params!(Oid, String, String) => sql_impl_func("has_table_privilege($1, $2::regclass::oid, $3)") => Bool, 1924;
2156 params!(Oid, Oid, String) => sql_impl_func(&privilege_fn!("has_table_privilege", "mz_relations")) => Bool, 1925;
2157 params!(String, String) => sql_impl_func("has_table_privilege(current_user, $1, $2)") => Bool, 1926;
2158 params!(Oid, String) => sql_impl_func("has_table_privilege(current_user, $1, $2)") => Bool, 1927;
2159 },
2160 "hmac" => Scalar {
2161 params!(String, String, String) => VariadicFunc::HmacString => Bytes, oid::FUNC_PG_HMAC_STRING;
2162 params!(Bytes, Bytes, String) => VariadicFunc::HmacBytes => Bytes, oid::FUNC_PG_HMAC_BYTES;
2163 },
2164 "initcap" => Scalar {
2165 params!(String) => UnaryFunc::Initcap(func::Initcap) => String, 872;
2166 },
2167 "int4range" => Scalar {
2168 params!(Int32, Int32) => Operation::variadic(|_ecx, mut exprs| {
2169 exprs.push(HirScalarExpr::literal(Datum::String("[)"), ScalarType::String));
2170 Ok(HirScalarExpr::call_variadic(VariadicFunc::RangeCreate { elem_type: ScalarType::Int32 },
2171 exprs))
2172 }) => ScalarType::Range { element_type: Box::new(ScalarType::Int32)}, 3840;
2173 params!(Int32, Int32, String) => Operation::variadic(|_ecx, exprs| {
2174 Ok(HirScalarExpr::call_variadic(VariadicFunc::RangeCreate { elem_type: ScalarType::Int32 },
2175 exprs))
2176 }) => ScalarType::Range { element_type: Box::new(ScalarType::Int32)}, 3841;
2177 },
2178 "int8range" => Scalar {
2179 params!(Int64, Int64) => Operation::variadic(|_ecx, mut exprs| {
2180 exprs.push(HirScalarExpr::literal(Datum::String("[)"), ScalarType::String));
2181 Ok(HirScalarExpr::call_variadic(VariadicFunc::RangeCreate { elem_type: ScalarType::Int64 },
2182 exprs))
2183 }) => ScalarType::Range { element_type: Box::new(ScalarType::Int64)}, 3945;
2184 params!(Int64, Int64, String) => Operation::variadic(|_ecx, exprs| {
2185 Ok(HirScalarExpr::call_variadic(VariadicFunc::RangeCreate { elem_type: ScalarType::Int64 },
2186 exprs))
2187 }) => ScalarType::Range { element_type: Box::new(ScalarType::Int64)}, 3946;
2188 },
2189 "isempty" => Scalar {
2190 params!(RangeAny) => UnaryFunc::RangeEmpty(func::RangeEmpty) => Bool, 3850;
2191 },
2192 "jsonb_array_length" => Scalar {
2193 params!(Jsonb) => UnaryFunc::JsonbArrayLength(func::JsonbArrayLength) => Int32, 3207;
2194 },
2195 "jsonb_build_array" => Scalar {
2196 params!() => VariadicFunc::JsonbBuildArray => Jsonb, 3272;
2197 params!(Any...) => Operation::variadic(|ecx, exprs| Ok(HirScalarExpr::call_variadic(VariadicFunc::JsonbBuildArray,
2198 exprs.into_iter().map(|e| typeconv::to_jsonb(ecx, e)).collect()))) => Jsonb, 3271;
2199 },
2200 "jsonb_build_object" => Scalar {
2201 params!() => VariadicFunc::JsonbBuildObject => Jsonb, 3274;
2202 params!(Any...) => Operation::variadic(|ecx, exprs| {
2203 if exprs.len() % 2 != 0 {
2204 sql_bail!("argument list must have even number of elements")
2205 }
2206 Ok(HirScalarExpr::call_variadic(
2207 VariadicFunc::JsonbBuildObject,
2208 exprs.into_iter().tuples().map(|(key, val)| {
2209 let key = typeconv::to_string(ecx, key);
2210 let val = typeconv::to_jsonb(ecx, val);
2211 vec![key, val]
2212 }).flatten().collect()))
2213 }) => Jsonb, 3273;
2214 },
2215 "jsonb_pretty" => Scalar {
2216 params!(Jsonb) => UnaryFunc::JsonbPretty(func::JsonbPretty) => String, 3306;
2217 },
2218 "jsonb_strip_nulls" => Scalar {
2219 params!(Jsonb) => UnaryFunc::JsonbStripNulls(func::JsonbStripNulls) => Jsonb, 3262;
2220 },
2221 "jsonb_typeof" => Scalar {
2222 params!(Jsonb) => UnaryFunc::JsonbTypeof(func::JsonbTypeof) => String, 3210;
2223 },
2224 "justify_days" => Scalar {
2225 params!(Interval) => UnaryFunc::JustifyDays(func::JustifyDays) => Interval, 1295;
2226 },
2227 "justify_hours" => Scalar {
2228 params!(Interval) => UnaryFunc::JustifyHours(func::JustifyHours) => Interval, 1175;
2229 },
2230 "justify_interval" => Scalar {
2231 params!(Interval) => UnaryFunc::JustifyInterval(func::JustifyInterval) => Interval, 2711;
2232 },
2233 "left" => Scalar {
2234 params!(String, Int32) => BinaryFunc::Left => String, 3060;
2235 },
2236 "length" => Scalar {
2237 params!(Bytes) => UnaryFunc::ByteLengthBytes(func::ByteLengthBytes) => Int32, 2010;
2238 params!(String) => UnaryFunc::CharLength(func::CharLength) => Int32, 1317;
2240 params!(Bytes, String) => BinaryFunc::EncodedBytesCharLength => Int32, 1713;
2241 },
2242 "like_escape" => Scalar {
2243 params!(String, String) => BinaryFunc::LikeEscape => String, 1637;
2244 },
2245 "ln" => Scalar {
2246 params!(Float64) => UnaryFunc::Ln(func::Ln) => Float64, 1341;
2247 params!(Numeric) => UnaryFunc::LnNumeric(func::LnNumeric) => Numeric, 1734;
2248 },
2249 "log10" => Scalar {
2250 params!(Float64) => UnaryFunc::Log10(func::Log10) => Float64, 1194;
2251 params!(Numeric) => UnaryFunc::Log10Numeric(func::Log10Numeric) => Numeric, 1481;
2252 },
2253 "log" => Scalar {
2254 params!(Float64) => UnaryFunc::Log10(func::Log10) => Float64, 1340;
2255 params!(Numeric) => UnaryFunc::Log10Numeric(func::Log10Numeric) => Numeric, 1741;
2256 params!(Numeric, Numeric) => BinaryFunc::LogNumeric => Numeric, 1736;
2257 },
2258 "lower" => Scalar {
2259 params!(String) => UnaryFunc::Lower(func::Lower) => String, 870;
2260 params!(RangeAny) => UnaryFunc::RangeLower(func::RangeLower) => AnyElement, 3848;
2261 },
2262 "lower_inc" => Scalar {
2263 params!(RangeAny) => UnaryFunc::RangeLowerInc(func::RangeLowerInc) => Bool, 3851;
2264 },
2265 "lower_inf" => Scalar {
2266 params!(RangeAny) => UnaryFunc::RangeLowerInf(func::RangeLowerInf) => Bool, 3853;
2267 },
2268 "lpad" => Scalar {
2269 params!(String, Int32) => VariadicFunc::PadLeading => String, 879;
2270 params!(String, Int32, String) => VariadicFunc::PadLeading => String, 873;
2271 },
2272 "ltrim" => Scalar {
2273 params!(String) => UnaryFunc::TrimLeadingWhitespace(func::TrimLeadingWhitespace) => String, 881;
2274 params!(String, String) => BinaryFunc::TrimLeading => String, 875;
2275 },
2276 "makeaclitem" => Scalar {
2277 params!(Oid, Oid, String, Bool) => VariadicFunc::MakeAclItem => AclItem, 1365;
2278 },
2279 "make_timestamp" => Scalar {
2280 params!(Int64, Int64, Int64, Int64, Int64, Float64) => VariadicFunc::MakeTimestamp => Timestamp, 3461;
2281 },
2282 "md5" => Scalar {
2283 params!(String) => Operation::unary(move |_ecx, input| {
2284 let algorithm = HirScalarExpr::literal(Datum::String("md5"), ScalarType::String);
2285 let encoding = HirScalarExpr::literal(Datum::String("hex"), ScalarType::String);
2286 Ok(input.call_binary(algorithm, BinaryFunc::DigestString).call_binary(encoding, BinaryFunc::Encode))
2287 }) => String, 2311;
2288 params!(Bytes) => Operation::unary(move |_ecx, input| {
2289 let algorithm = HirScalarExpr::literal(Datum::String("md5"), ScalarType::String);
2290 let encoding = HirScalarExpr::literal(Datum::String("hex"), ScalarType::String);
2291 Ok(input.call_binary(algorithm, BinaryFunc::DigestBytes).call_binary(encoding, BinaryFunc::Encode))
2292 }) => String, 2321;
2293 },
2294 "mod" => Scalar {
2295 params!(Numeric, Numeric) => Operation::nullary(|_ecx| catalog_name_only!("mod")) => Numeric, 1728;
2296 params!(Int16, Int16) => Operation::nullary(|_ecx| catalog_name_only!("mod")) => Int16, 940;
2297 params!(Int32, Int32) => Operation::nullary(|_ecx| catalog_name_only!("mod")) => Int32, 941;
2298 params!(Int64, Int64) => Operation::nullary(|_ecx| catalog_name_only!("mod")) => Int64, 947;
2299 params!(UInt16, UInt16) => Operation::nullary(|_ecx| catalog_name_only!("mod")) => UInt16, oid::FUNC_MOD_UINT16_OID;
2300 params!(UInt32, UInt32) => Operation::nullary(|_ecx| catalog_name_only!("mod")) => UInt32, oid::FUNC_MOD_UINT32_OID;
2301 params!(UInt64, UInt64) => Operation::nullary(|_ecx| catalog_name_only!("mod")) => UInt64, oid::FUNC_MOD_UINT64_OID;
2302 },
2303 "now" => Scalar {
2304 params!() => UnmaterializableFunc::CurrentTimestamp => TimestampTz, 1299;
2305 },
2306 "numrange" => Scalar {
2307 params!(Numeric, Numeric) => Operation::variadic(|_ecx, mut exprs| {
2308 exprs.push(HirScalarExpr::literal(Datum::String("[)"), ScalarType::String));
2309 Ok(HirScalarExpr::call_variadic(VariadicFunc::RangeCreate { elem_type: ScalarType::Numeric { max_scale: None } },
2310 exprs))
2311 }) => ScalarType::Range { element_type: Box::new(ScalarType::Numeric { max_scale: None })}, 3844;
2312 params!(Numeric, Numeric, String) => Operation::variadic(|_ecx, exprs| {
2313 Ok(HirScalarExpr::call_variadic(VariadicFunc::RangeCreate { elem_type: ScalarType::Numeric { max_scale: None } },
2314 exprs))
2315 }) => ScalarType::Range { element_type: Box::new(ScalarType::Numeric { max_scale: None })}, 3845;
2316 },
2317 "octet_length" => Scalar {
2318 params!(Bytes) => UnaryFunc::ByteLengthBytes(func::ByteLengthBytes) => Int32, 720;
2319 params!(String) => UnaryFunc::ByteLengthString(func::ByteLengthString) => Int32, 1374;
2320 params!(Char) => Operation::unary(|ecx, e| {
2321 let length = ecx.scalar_type(&e).unwrap_char_length();
2322 Ok(e.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
2323 .call_unary(UnaryFunc::ByteLengthString(func::ByteLengthString))
2324 )
2325 }) => Int32, 1375;
2326 },
2327 "obj_description" => Scalar {
2331 params!(Oid, String) => sql_impl_func(&format!(
2332 "(SELECT description FROM pg_description
2333 WHERE objoid = $1
2334 AND classoid = (
2335 SELECT oid FROM pg_class WHERE relname = $2 AND relnamespace = {})
2336 AND objsubid = 0)",
2337 oid::SCHEMA_PG_CATALOG_OID
2338 )) => String, 1215;
2339 },
2340 "pg_column_size" => Scalar {
2341 params!(Any) => UnaryFunc::PgColumnSize(func::PgColumnSize) => Int32, 1269;
2342 },
2343 "pg_size_pretty" => Scalar {
2344 params!(Numeric) => UnaryFunc::PgSizePretty(func::PgSizePretty) => String, 3166;
2345 },
2346 "mz_row_size" => Scalar {
2347 params!(Any) => Operation::unary(|ecx, e| {
2348 let s = ecx.scalar_type(&e);
2349 if !matches!(s, ScalarType::Record{..}) {
2350 sql_bail!("mz_row_size requires a record type");
2351 }
2352 Ok(e.call_unary(UnaryFunc::MzRowSize(func::MzRowSize)))
2353 }) => Int32, oid::FUNC_MZ_ROW_SIZE;
2354 },
2355 "parse_ident" => Scalar {
2356 params!(String) => Operation::unary(|_ecx, ident| {
2357 Ok(ident.call_binary(HirScalarExpr::literal_true(), BinaryFunc::ParseIdent))
2358 }) => ScalarType::Array(Box::new(ScalarType::String)),
2359 oid::FUNC_PARSE_IDENT_DEFAULT_STRICT;
2360 params!(String, Bool) => BinaryFunc::ParseIdent
2361 => ScalarType::Array(Box::new(ScalarType::String)), 1268;
2362 },
2363 "pg_encoding_to_char" => Scalar {
2364 params!(Int64) => sql_impl_func("CASE WHEN $1 = 6 THEN 'UTF8' ELSE NULL END") => String, 1597;
2367 },
2368 "pg_backend_pid" => Scalar {
2369 params!() => UnmaterializableFunc::PgBackendPid => Int32, 2026;
2370 },
2371 "pg_get_constraintdef" => Scalar {
2377 params!(Oid) => Operation::unary(|_ecx, _oid|
2378 Ok(HirScalarExpr::literal_null(ScalarType::String))) => String, 1387;
2379 params!(Oid, Bool) => Operation::binary(|_ecx, _oid, _pretty|
2380 Ok(HirScalarExpr::literal_null(ScalarType::String))) => String, 2508;
2381 },
2382 "pg_get_indexdef" => Scalar {
2386 params!(Oid) => sql_impl_func(
2387 "(SELECT 'CREATE INDEX ' || i.name || ' ON ' || r.name || ' USING arrangement (' || (
2388 SELECT pg_catalog.string_agg(cols.col_exp, ',' ORDER BY cols.index_position)
2389 FROM (
2390 SELECT c.name AS col_exp, ic.index_position
2391 FROM mz_catalog.mz_index_columns AS ic
2392 JOIN mz_catalog.mz_indexes AS i2 ON ic.index_id = i2.id
2393 JOIN mz_catalog.mz_columns AS c ON i2.on_id = c.id AND ic.on_position = c.position
2394 WHERE ic.index_id = i.id AND ic.on_expression IS NULL
2395 UNION
2396 SELECT ic.on_expression AS col_exp, ic.index_position
2397 FROM mz_catalog.mz_index_columns AS ic
2398 WHERE ic.index_id = i.id AND ic.on_expression IS NOT NULL
2399 ) AS cols
2400 ) || ')'
2401 FROM mz_catalog.mz_indexes AS i
2402 JOIN mz_catalog.mz_relations AS r ON i.on_id = r.id
2403 WHERE i.oid = $1)"
2404 ) => String, 1643;
2405 params!(Oid, Int32, Bool) => sql_impl_func(
2408 "(SELECT CASE WHEN $2 = 0 THEN pg_catalog.pg_get_indexdef($1) ELSE
2409 (SELECT c.name
2410 FROM mz_catalog.mz_indexes AS i
2411 JOIN mz_catalog.mz_index_columns AS ic ON i.id = ic.index_id
2412 JOIN mz_catalog.mz_columns AS c ON i.on_id = c.id AND ic.on_position = c.position
2413 WHERE i.oid = $1 AND ic.on_expression IS NULL AND ic.index_position = $2
2414 UNION
2415 SELECT ic.on_expression
2416 FROM mz_catalog.mz_indexes AS i
2417 JOIN mz_catalog.mz_index_columns AS ic ON i.id = ic.index_id
2418 WHERE i.oid = $1 AND ic.on_expression IS NOT NULL AND ic.index_position = $2)
2419 END)"
2420 ) => String, 2507;
2421 },
2422 "pg_get_viewdef" => Scalar {
2425 params!(String) => sql_impl_func(
2426 "(SELECT definition FROM mz_catalog.mz_views WHERE name = $1)"
2427 ) => String, 1640;
2428 params!(Oid) => sql_impl_func(
2429 "(SELECT definition FROM mz_catalog.mz_views WHERE oid = $1)"
2430 ) => String, 1641;
2431 params!(String, Bool) => sql_impl_func(
2432 "(SELECT definition FROM mz_catalog.mz_views WHERE name = $1)"
2433 ) => String, 2505;
2434 params!(Oid, Bool) => sql_impl_func(
2435 "(SELECT definition FROM mz_catalog.mz_views WHERE oid = $1)"
2436 ) => String, 2506;
2437 params!(Oid, Int32) => sql_impl_func(
2438 "(SELECT definition FROM mz_catalog.mz_views WHERE oid = $1)"
2439 ) => String, 3159;
2440 },
2441 "pg_get_expr" => Scalar {
2449 params!(String, Oid) => Operation::binary(|_ecx, l, _r| Ok(l)) => String, 1716;
2450 params!(String, Oid, Bool) => Operation::variadic(move |_ecx, mut args| Ok(args.remove(0))) => String, 2509;
2451 },
2452 "pg_get_userbyid" => Scalar {
2453 params!(Oid) => sql_impl_func(
2454 "CASE \
2455 WHEN $1 IS NULL THEN NULL \
2456 ELSE COALESCE(\
2457 (SELECT name FROM mz_catalog.mz_roles WHERE oid = $1),\
2458 'unknown (OID=' || $1 || ')'\
2459 ) \
2460 END"
2461 ) => String, 1642;
2462 },
2463 "pg_has_role" => Scalar {
2470 params!(String, String, String) => sql_impl_func("pg_has_role(mz_internal.mz_role_oid($1), mz_internal.mz_role_oid($2), $3)") => Bool, 2705;
2471 params!(String, Oid, String) => sql_impl_func("pg_has_role(mz_internal.mz_role_oid($1), $2, $3)") => Bool, 2706;
2472 params!(Oid, String, String) => sql_impl_func("pg_has_role($1, mz_internal.mz_role_oid($2), $3)") => Bool, 2707;
2473 params!(Oid, Oid, String) => sql_impl_func(
2474 "CASE
2475 -- We need to validate the privilege to return a proper error before anything
2476 -- else.
2477 WHEN NOT mz_internal.mz_validate_role_privilege($3)
2478 OR $1 IS NULL
2479 OR $2 IS NULL
2480 OR $3 IS NULL
2481 THEN NULL
2482 WHEN $1 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
2483 OR $2 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
2484 THEN false
2485 ELSE $2::text IN (SELECT UNNEST(mz_internal.mz_role_oid_memberships() -> $1::text))
2486 END",
2487 ) => Bool, 2708;
2488 params!(String, String) => sql_impl_func("pg_has_role(current_user, $1, $2)") => Bool, 2709;
2489 params!(Oid, String) => sql_impl_func("pg_has_role(current_user, $1, $2)") => Bool, 2710;
2490 },
2491 "pg_is_in_recovery" => Scalar {
2494 params!() => Operation::nullary(|_ecx| {
2495 Ok(HirScalarExpr::literal_false())
2496 }) => Bool, 3810;
2497 },
2498 "pg_postmaster_start_time" => Scalar {
2499 params!() => UnmaterializableFunc::PgPostmasterStartTime => TimestampTz, 2560;
2500 },
2501 "pg_relation_size" => Scalar {
2502 params!(RegClass, String) => sql_impl_func("CASE WHEN $1 IS NULL OR $2 IS NULL THEN NULL ELSE -1::pg_catalog.int8 END") => Int64, 2332;
2503 params!(RegClass) => sql_impl_func("CASE WHEN $1 IS NULL THEN NULL ELSE -1::pg_catalog.int8 END") => Int64, 2325;
2504 },
2505 "pg_stat_get_numscans" => Scalar {
2506 params!(Oid) => sql_impl_func("CASE WHEN $1 IS NULL THEN NULL ELSE -1::pg_catalog.int8 END") => Int64, 1928;
2507 },
2508 "pg_table_is_visible" => Scalar {
2509 params!(Oid) => sql_impl_func(
2510 "(SELECT s.name = ANY(pg_catalog.current_schemas(true))
2511 FROM mz_catalog.mz_objects o JOIN mz_catalog.mz_schemas s ON o.schema_id = s.id
2512 WHERE o.oid = $1)"
2513 ) => Bool, 2079;
2514 },
2515 "pg_type_is_visible" => Scalar {
2516 params!(Oid) => sql_impl_func(
2517 "(SELECT s.name = ANY(pg_catalog.current_schemas(true))
2518 FROM mz_catalog.mz_types t JOIN mz_catalog.mz_schemas s ON t.schema_id = s.id
2519 WHERE t.oid = $1)"
2520 ) => Bool, 2080;
2521 },
2522 "pg_function_is_visible" => Scalar {
2523 params!(Oid) => sql_impl_func(
2524 "(SELECT s.name = ANY(pg_catalog.current_schemas(true))
2525 FROM mz_catalog.mz_functions f JOIN mz_catalog.mz_schemas s ON f.schema_id = s.id
2526 WHERE f.oid = $1)"
2527 ) => Bool, 2081;
2528 },
2529 "pg_tablespace_location" => Scalar {
2533 params!(Oid) => Operation::unary(|_ecx, _e| {
2534 Ok(HirScalarExpr::literal_null(ScalarType::String))
2535 }) => String, 3778;
2536 },
2537 "pg_typeof" => Scalar {
2538 params!(Any) => Operation::new(|ecx, exprs, params, _order_by| {
2539 let name = match ecx.scalar_type(&exprs[0]) {
2541 CoercibleScalarType::Uncoerced => "unknown".to_string(),
2542 CoercibleScalarType::Record(_) => "record".to_string(),
2543 CoercibleScalarType::Coerced(ty) => ecx.humanize_scalar_type(&ty, true),
2544 };
2545
2546 coerce_args_to_types(ecx, exprs, params)?;
2550
2551 Ok(HirScalarExpr::literal(Datum::String(&name), ScalarType::String))
2556 }) => String, 1619;
2557 },
2558 "position" => Scalar {
2559 params!(String, String) => BinaryFunc::Position => Int32, 849;
2560 },
2561 "pow" => Scalar {
2562 params!(Float64, Float64) => Operation::nullary(|_ecx| catalog_name_only!("pow")) => Float64, 1346;
2563 },
2564 "power" => Scalar {
2565 params!(Float64, Float64) => BinaryFunc::Power => Float64, 1368;
2566 params!(Numeric, Numeric) => BinaryFunc::PowerNumeric => Numeric, 2169;
2567 },
2568 "quote_ident" => Scalar {
2569 params!(String) => UnaryFunc::QuoteIdent(func::QuoteIdent) => String, 1282;
2570 },
2571 "radians" => Scalar {
2572 params!(Float64) => UnaryFunc::Radians(func::Radians) => Float64, 1609;
2573 },
2574 "repeat" => Scalar {
2575 params!(String, Int32) => BinaryFunc::RepeatString => String, 1622;
2576 },
2577 "regexp_match" => Scalar {
2578 params!(String, String) => VariadicFunc::RegexpMatch => ScalarType::Array(Box::new(ScalarType::String)), 3396;
2579 params!(String, String, String) => VariadicFunc::RegexpMatch => ScalarType::Array(Box::new(ScalarType::String)), 3397;
2580 },
2581 "replace" => Scalar {
2582 params!(String, String, String) => VariadicFunc::Replace => String, 2087;
2583 },
2584 "right" => Scalar {
2585 params!(String, Int32) => BinaryFunc::Right => String, 3061;
2586 },
2587 "round" => Scalar {
2588 params!(Float32) => UnaryFunc::RoundFloat32(func::RoundFloat32) => Float32, oid::FUNC_ROUND_F32_OID;
2589 params!(Float64) => UnaryFunc::RoundFloat64(func::RoundFloat64) => Float64, 1342;
2590 params!(Numeric) => UnaryFunc::RoundNumeric(func::RoundNumeric) => Numeric, 1708;
2591 params!(Numeric, Int32) => BinaryFunc::RoundNumeric => Numeric, 1707;
2592 },
2593 "rtrim" => Scalar {
2594 params!(String) => UnaryFunc::TrimTrailingWhitespace(func::TrimTrailingWhitespace) => String, 882;
2595 params!(String, String) => BinaryFunc::TrimTrailing => String, 876;
2596 },
2597 "sha224" => Scalar {
2598 params!(Bytes) => digest("sha224") => Bytes, 3419;
2599 },
2600 "sha256" => Scalar {
2601 params!(Bytes) => digest("sha256") => Bytes, 3420;
2602 },
2603 "sha384" => Scalar {
2604 params!(Bytes) => digest("sha384") => Bytes, 3421;
2605 },
2606 "sha512" => Scalar {
2607 params!(Bytes) => digest("sha512") => Bytes, 3422;
2608 },
2609 "sin" => Scalar {
2610 params!(Float64) => UnaryFunc::Sin(func::Sin) => Float64, 1604;
2611 },
2612 "asin" => Scalar {
2613 params!(Float64) => UnaryFunc::Asin(func::Asin) => Float64, 1600;
2614 },
2615 "sinh" => Scalar {
2616 params!(Float64) => UnaryFunc::Sinh(func::Sinh) => Float64, 2462;
2617 },
2618 "asinh" => Scalar {
2619 params!(Float64) => UnaryFunc::Asinh(func::Asinh) => Float64, 2465;
2620 },
2621 "split_part" => Scalar {
2622 params!(String, String, Int32) => VariadicFunc::SplitPart => String, 2088;
2623 },
2624 "stddev" => Scalar {
2625 params!(Float32) => Operation::nullary(|_ecx| catalog_name_only!("stddev")) => Float64, 2157;
2626 params!(Float64) => Operation::nullary(|_ecx| catalog_name_only!("stddev")) => Float64, 2158;
2627 params!(Int16) => Operation::nullary(|_ecx| catalog_name_only!("stddev")) => Numeric, 2156;
2628 params!(Int32) => Operation::nullary(|_ecx| catalog_name_only!("stddev")) => Numeric, 2155;
2629 params!(Int64) => Operation::nullary(|_ecx| catalog_name_only!("stddev")) => Numeric, 2154;
2630 params!(UInt16) => Operation::nullary(|_ecx| catalog_name_only!("stddev")) => Numeric, oid::FUNC_STDDEV_UINT16_OID;
2631 params!(UInt32) => Operation::nullary(|_ecx| catalog_name_only!("stddev")) => Numeric, oid::FUNC_STDDEV_UINT32_OID;
2632 params!(UInt64) => Operation::nullary(|_ecx| catalog_name_only!("stddev")) => Numeric, oid::FUNC_STDDEV_UINT64_OID;
2633 },
2634 "stddev_pop" => Scalar {
2635 params!(Float32) => Operation::nullary(|_ecx| catalog_name_only!("stddev_pop")) => Float64, 2727;
2636 params!(Float64) => Operation::nullary(|_ecx| catalog_name_only!("stddev_pop")) => Float64, 2728;
2637 params!(Int16) => Operation::nullary(|_ecx| catalog_name_only!("stddev_pop")) => Numeric, 2726;
2638 params!(Int32) => Operation::nullary(|_ecx| catalog_name_only!("stddev_pop")) => Numeric, 2725;
2639 params!(Int64) => Operation::nullary(|_ecx| catalog_name_only!("stddev_pop")) => Numeric, 2724;
2640 params!(UInt16) => Operation::nullary(|_ecx| catalog_name_only!("stddev_pop")) => Numeric, oid::FUNC_STDDEV_POP_UINT16_OID;
2641 params!(UInt32) => Operation::nullary(|_ecx| catalog_name_only!("stddev_pop")) => Numeric, oid::FUNC_STDDEV_POP_UINT32_OID;
2642 params!(UInt64) => Operation::nullary(|_ecx| catalog_name_only!("stddev_pop")) => Numeric, oid::FUNC_STDDEV_POP_UINT64_OID;
2643 },
2644 "stddev_samp" => Scalar {
2645 params!(Float32) => Operation::nullary(|_ecx| catalog_name_only!("stddev_samp")) => Float64, 2715;
2646 params!(Float64) => Operation::nullary(|_ecx| catalog_name_only!("stddev_samp")) => Float64, 2716;
2647 params!(Int16) => Operation::nullary(|_ecx| catalog_name_only!("stddev_samp")) => Numeric, 2714;
2648 params!(Int32) => Operation::nullary(|_ecx| catalog_name_only!("stddev_samp")) => Numeric, 2713;
2649 params!(Int64) => Operation::nullary(|_ecx| catalog_name_only!("stddev_samp")) => Numeric, 2712;
2650 params!(UInt16) => Operation::nullary(|_ecx| catalog_name_only!("stddev_samp")) => Numeric, oid::FUNC_STDDEV_SAMP_UINT16_OID;
2651 params!(UInt32) => Operation::nullary(|_ecx| catalog_name_only!("stddev_samp")) => Numeric, oid::FUNC_STDDEV_SAMP_UINT32_OID;
2652 params!(UInt64) => Operation::nullary(|_ecx| catalog_name_only!("stddev_samp")) => Numeric, oid::FUNC_STDDEV_SAMP_UINT64_OID;
2653 },
2654 "substr" => Scalar {
2655 params!(String, Int32) => VariadicFunc::Substr => String, 883;
2656 params!(String, Int32, Int32) => VariadicFunc::Substr => String, 877;
2657 },
2658 "substring" => Scalar {
2659 params!(String, Int32) => VariadicFunc::Substr => String, 937;
2660 params!(String, Int32, Int32) => VariadicFunc::Substr => String, 936;
2661 },
2662 "sqrt" => Scalar {
2663 params!(Float64) => UnaryFunc::SqrtFloat64(func::SqrtFloat64) => Float64, 1344;
2664 params!(Numeric) => UnaryFunc::SqrtNumeric(func::SqrtNumeric) => Numeric, 1730;
2665 },
2666 "tan" => Scalar {
2667 params!(Float64) => UnaryFunc::Tan(func::Tan) => Float64, 1606;
2668 },
2669 "atan" => Scalar {
2670 params!(Float64) => UnaryFunc::Atan(func::Atan) => Float64, 1602;
2671 },
2672 "tanh" => Scalar {
2673 params!(Float64) => UnaryFunc::Tanh(func::Tanh) => Float64, 2464;
2674 },
2675 "atanh" => Scalar {
2676 params!(Float64) => UnaryFunc::Atanh(func::Atanh) => Float64, 2467;
2677 },
2678 "age" => Scalar {
2679 params!(Timestamp, Timestamp) => BinaryFunc::AgeTimestamp => Interval, 2058;
2680 params!(TimestampTz, TimestampTz) => BinaryFunc::AgeTimestampTz => Interval, 1199;
2681 },
2682 "timezone" => Scalar {
2683 params!(String, Timestamp) => BinaryFunc::TimezoneTimestamp => TimestampTz, 2069;
2684 params!(String, TimestampTz) => BinaryFunc::TimezoneTimestampTz => Timestamp, 1159;
2685 params!(String, Time) => Operation::binary(|ecx, lhs, rhs| {
2687 ecx.require_feature_flag(&ENABLE_TIME_AT_TIME_ZONE)?;
2701 Ok(HirScalarExpr::call_variadic(
2702 VariadicFunc::TimezoneTime,
2703 vec![
2704 lhs,
2705 rhs,
2706 HirScalarExpr::call_unmaterializable(UnmaterializableFunc::CurrentTimestamp),
2707 ],
2708 ))
2709 }) => Time, 2037;
2710 params!(Interval, Timestamp) => BinaryFunc::TimezoneIntervalTimestamp => TimestampTz, 2070;
2711 params!(Interval, TimestampTz) => BinaryFunc::TimezoneIntervalTimestampTz => Timestamp, 1026;
2712 params!(Interval, Time) => BinaryFunc::TimezoneIntervalTime => Time, 2038;
2714 },
2715 "to_char" => Scalar {
2716 params!(Timestamp, String) => BinaryFunc::ToCharTimestamp => String, 2049;
2717 params!(TimestampTz, String) => BinaryFunc::ToCharTimestampTz => String, 1770;
2718 },
2719 "to_jsonb" => Scalar {
2730 params!(Any) => Operation::unary(|ecx, e| {
2731 let e = match ecx.scalar_type(&e) {
2733 ScalarType::Char { length } => e.call_unary(UnaryFunc::PadChar(func::PadChar { length })),
2734 _ => e,
2735 };
2736 Ok(typeconv::to_jsonb(ecx, e))
2737 }) => Jsonb, 3787;
2738 },
2739 "to_timestamp" => Scalar {
2740 params!(Float64) => UnaryFunc::ToTimestamp(func::ToTimestamp) => TimestampTz, 1158;
2741 },
2742 "translate" => Scalar {
2743 params!(String, String, String) => VariadicFunc::Translate => String, 878;
2744 },
2745 "trunc" => Scalar {
2746 params!(Float32) => UnaryFunc::TruncFloat32(func::TruncFloat32) => Float32, oid::FUNC_TRUNC_F32_OID;
2747 params!(Float64) => UnaryFunc::TruncFloat64(func::TruncFloat64) => Float64, 1343;
2748 params!(Numeric) => UnaryFunc::TruncNumeric(func::TruncNumeric) => Numeric, 1710;
2749 },
2750 "tsrange" => Scalar {
2751 params!(Timestamp, Timestamp) => Operation::variadic(|_ecx, mut exprs| {
2752 exprs.push(HirScalarExpr::literal(Datum::String("[)"), ScalarType::String));
2753 Ok(HirScalarExpr::call_variadic(VariadicFunc::RangeCreate { elem_type: ScalarType::Timestamp {precision: None}},
2754 exprs))
2755 }) => ScalarType::Range { element_type: Box::new(ScalarType::Timestamp { precision: None})}, 3933;
2756 params!(Timestamp, Timestamp, String) => Operation::variadic(|_ecx, exprs| {
2757 Ok(HirScalarExpr::call_variadic(VariadicFunc::RangeCreate { elem_type: ScalarType::Timestamp {precision: None}},
2758 exprs))
2759 }) => ScalarType::Range { element_type: Box::new(ScalarType::Timestamp { precision: None})}, 3934;
2760 },
2761 "tstzrange" => Scalar {
2762 params!(TimestampTz, TimestampTz) => Operation::variadic(|_ecx, mut exprs| {
2763 exprs.push(HirScalarExpr::literal(Datum::String("[)"), ScalarType::String));
2764 Ok(HirScalarExpr::call_variadic(VariadicFunc::RangeCreate { elem_type: ScalarType::TimestampTz {precision: None}},
2765 exprs,))
2766 }) => ScalarType::Range { element_type: Box::new(ScalarType::TimestampTz { precision: None})}, 3937;
2767 params!(TimestampTz, TimestampTz, String) => Operation::variadic(|_ecx, exprs| {
2768 Ok(HirScalarExpr::call_variadic(VariadicFunc::RangeCreate { elem_type: ScalarType::TimestampTz {precision: None}},
2769 exprs))
2770 }) => ScalarType::Range { element_type: Box::new(ScalarType::TimestampTz { precision: None})}, 3938;
2771 },
2772 "upper" => Scalar {
2773 params!(String) => UnaryFunc::Upper(func::Upper) => String, 871;
2774 params!(RangeAny) => UnaryFunc::RangeUpper(func::RangeUpper) => AnyElement, 3849;
2775 },
2776 "upper_inc" => Scalar {
2777 params!(RangeAny) => UnaryFunc::RangeUpperInc(func::RangeUpperInc) => Bool, 3852;
2778 },
2779 "upper_inf" => Scalar {
2780 params!(RangeAny) => UnaryFunc::RangeUpperInf(func::RangeUpperInf) => Bool, 3854;
2781 },
2782 "uuid_generate_v5" => Scalar {
2783 params!(Uuid, String) => BinaryFunc::UuidGenerateV5 => Uuid, oid::FUNC_PG_UUID_GENERATE_V5;
2784 },
2785 "variance" => Scalar {
2786 params!(Float32) => Operation::nullary(|_ecx| catalog_name_only!("variance")) => Float64, 2151;
2787 params!(Float64) => Operation::nullary(|_ecx| catalog_name_only!("variance")) => Float64, 2152;
2788 params!(Int16) => Operation::nullary(|_ecx| catalog_name_only!("variance")) => Numeric, 2150;
2789 params!(Int32) => Operation::nullary(|_ecx| catalog_name_only!("variance")) => Numeric, 2149;
2790 params!(Int64) => Operation::nullary(|_ecx| catalog_name_only!("variance")) => Numeric, 2148;
2791 params!(UInt16) => Operation::nullary(|_ecx| catalog_name_only!("variance")) => Numeric, oid::FUNC_VARIANCE_UINT16_OID;
2792 params!(UInt32) => Operation::nullary(|_ecx| catalog_name_only!("variance")) => Numeric, oid::FUNC_VARIANCE_UINT32_OID;
2793 params!(UInt64) => Operation::nullary(|_ecx| catalog_name_only!("variance")) => Numeric, oid::FUNC_VARIANCE_UINT64_OID;
2794 },
2795 "var_pop" => Scalar {
2796 params!(Float32) => Operation::nullary(|_ecx| catalog_name_only!("var_pop")) => Float64, 2721;
2797 params!(Float64) => Operation::nullary(|_ecx| catalog_name_only!("var_pop")) => Float64, 2722;
2798 params!(Int16) => Operation::nullary(|_ecx| catalog_name_only!("var_pop")) => Numeric, 2720;
2799 params!(Int32) => Operation::nullary(|_ecx| catalog_name_only!("var_pop")) => Numeric, 2719;
2800 params!(Int64) => Operation::nullary(|_ecx| catalog_name_only!("var_pop")) => Numeric, 2718;
2801 params!(UInt16) => Operation::nullary(|_ecx| catalog_name_only!("var_pop")) => Numeric, oid::FUNC_VAR_POP_UINT16_OID;
2802 params!(UInt32) => Operation::nullary(|_ecx| catalog_name_only!("var_pop")) => Numeric, oid::FUNC_VAR_POP_UINT32_OID;
2803 params!(UInt64) => Operation::nullary(|_ecx| catalog_name_only!("var_pop")) => Numeric, oid::FUNC_VAR_POP_UINT64_OID;
2804 },
2805 "var_samp" => Scalar {
2806 params!(Float32) => Operation::nullary(|_ecx| catalog_name_only!("var_samp")) => Float64, 2644;
2807 params!(Float64) => Operation::nullary(|_ecx| catalog_name_only!("var_samp")) => Float64, 2645;
2808 params!(Int16) => Operation::nullary(|_ecx| catalog_name_only!("var_samp")) => Numeric, 2643;
2809 params!(Int32) => Operation::nullary(|_ecx| catalog_name_only!("var_samp")) => Numeric, 2642;
2810 params!(Int64) => Operation::nullary(|_ecx| catalog_name_only!("var_samp")) => Numeric, 2641;
2811 params!(UInt16) => Operation::nullary(|_ecx| catalog_name_only!("var_samp")) => Numeric, oid::FUNC_VAR_SAMP_UINT16_OID;
2812 params!(UInt32) => Operation::nullary(|_ecx| catalog_name_only!("var_samp")) => Numeric, oid::FUNC_VAR_SAMP_UINT32_OID;
2813 params!(UInt64) => Operation::nullary(|_ecx| catalog_name_only!("var_samp")) => Numeric, oid::FUNC_VAR_SAMP_UINT64_OID;
2814 },
2815 "version" => Scalar {
2816 params!() => UnmaterializableFunc::Version => String, 89;
2817 },
2818
2819 "aclitemin" => Scalar {
2821 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("aclitemin")) => AclItem, 1031;
2822 },
2823 "any_in" => Scalar {
2824 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("any_in")) => Any, 2294;
2825 },
2826 "anyarray_in" => Scalar {
2827 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("anyarray_in")) => ArrayAny, 2296;
2828 },
2829 "anycompatible_in" => Scalar {
2830 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("anycompatible_in")) => AnyCompatible, 5086;
2831 },
2832 "anycompatiblearray_in" => Scalar {
2833 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("anycompatiblearray_in")) => ArrayAnyCompatible, 5088;
2834 },
2835 "anycompatiblenonarray_in" => Scalar {
2836 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("anycompatiblenonarray_in")) => NonVecAnyCompatible, 5092;
2837 },
2838 "anycompatiblerange_in" => Scalar {
2839 params!(String, Oid, Int32) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("anycompatiblerange_in")) => RangeAnyCompatible, 5094;
2840 },
2841 "anyelement_in" => Scalar {
2842 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("anyelement_in")) => AnyElement, 2312;
2843 },
2844 "anynonarray_in" => Scalar {
2845 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("anynonarray_in")) => NonVecAny, 2777;
2846 },
2847 "anyrange_in" => Scalar {
2848 params!(String, Oid, Int32) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("anyrange_in")) => RangeAny, 3832;
2849 },
2850 "array_in" => Scalar {
2851 params!(String, Oid, Int32) =>
2852 Operation::variadic(|_ecx, _exprs| bail_unsupported!("array_in")) => ArrayAny, 750;
2853 },
2854 "boolin" => Scalar {
2855 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("boolin")) => Bool, 1242;
2856 },
2857 "bpcharin" => Scalar {
2858 params!(String, Oid, Int32) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("bpcharin")) => Char, 1044;
2859 },
2860 "byteain" => Scalar {
2861 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("byteain")) => Bytes, 1244;
2862 },
2863 "charin" => Scalar {
2864 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("charin")) => PgLegacyChar, 1245;
2865 },
2866 "date_in" => Scalar {
2867 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("date_in")) => Date, 1084;
2868 },
2869 "float4in" => Scalar {
2870 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("float4in")) => Float32, 200;
2871 },
2872 "float8in" => Scalar {
2873 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("float8in")) => Float64, 214;
2874 },
2875 "int2in" => Scalar {
2876 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("int2in")) => Int16, 38;
2877 },
2878 "int2vectorin" => Scalar {
2879 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("int2vectorin")) => Int2Vector, 40;
2880 },
2881 "int4in" => Scalar {
2882 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("int4in")) => Int32, 42;
2883 },
2884 "int8in" => Scalar {
2885 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("int8in")) => Int64, 460;
2886 },
2887 "internal_in" => Scalar {
2888 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("internal_in")) => Internal, 2304;
2889 },
2890 "interval_in" => Scalar {
2891 params!(String, Oid, Int32) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("interval_in")) => Interval, 1160;
2892 },
2893 "jsonb_in" => Scalar {
2894 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("jsonb_in")) => Jsonb, 3806;
2895 },
2896 "namein" => Scalar {
2897 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("namein")) => PgLegacyName, 34;
2898 },
2899 "numeric_in" => Scalar {
2900 params!(String, Oid, Int32) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("numeric_in")) => Numeric, 1701;
2901 },
2902 "oidin" => Scalar {
2903 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("oidin")) => Oid, 1798;
2904 },
2905 "range_in" => Scalar {
2906 params!(String, Oid, Int32) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("range_in")) => RangeAny, 3834;
2907 },
2908 "record_in" => Scalar {
2909 params!(String, Oid, Int32) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("record_in")) => RecordAny, 2290;
2910 },
2911 "regclassin" => Scalar {
2912 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("regclassin")) => RegClass, 2218;
2913 },
2914 "regprocin" => Scalar {
2915 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("regprocin")) => RegProc, 44;
2916 },
2917 "regtypein" => Scalar {
2918 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("regtypein")) => RegType, 2220;
2919 },
2920 "textin" => Scalar {
2921 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("textin")) => String, 46;
2922 },
2923 "time_in" => Scalar {
2924 params!(String, Oid, Int32) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("time_in")) => Time, 1143;
2925 },
2926 "timestamp_in" => Scalar {
2927 params!(String, Oid, Int32) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("timestamp_in")) => Timestamp, 1312;
2928 },
2929 "timestamptz_in" => Scalar {
2930 params!(String, Oid, Int32) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("timestamptz_in")) => TimestampTz, 1150;
2931 },
2932 "varcharin" => Scalar {
2933 params!(String, Oid, Int32) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("varcharin")) => VarChar, 1046;
2934 },
2935 "uuid_in" => Scalar {
2936 params!(String) => Operation::variadic(|_ecx, _exprs| bail_unsupported!("uuid_in")) => Uuid, 2952;
2937 },
2938 "boolrecv" => Scalar {
2939 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("boolrecv")) => Bool, 2436;
2940 },
2941 "textrecv" => Scalar {
2942 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("textrecv")) => String, 2414;
2943 },
2944 "anyarray_recv" => Scalar {
2945 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("anyarray_recv")) => ArrayAny, 2502;
2946 },
2947 "bytearecv" => Scalar {
2948 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("bytearecv")) => Bytes, 2412;
2949 },
2950 "bpcharrecv" => Scalar {
2951 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("bpcharrecv")) => Char, 2430;
2952 },
2953 "charrecv" => Scalar {
2954 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("charrecv")) => PgLegacyChar, 2434;
2955 },
2956 "date_recv" => Scalar {
2957 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("date_recv")) => Date, 2468;
2958 },
2959 "float4recv" => Scalar {
2960 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("float4recv")) => Float32, 2424;
2961 },
2962 "float8recv" => Scalar {
2963 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("float8recv")) => Float64, 2426;
2964 },
2965 "int4recv" => Scalar {
2966 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("int4recv")) => Int32, 2406;
2967 },
2968 "int8recv" => Scalar {
2969 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("int8recv")) => Int64, 2408;
2970 },
2971 "interval_recv" => Scalar {
2972 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("interval_recv")) => Interval, 2478;
2973 },
2974 "jsonb_recv" => Scalar {
2975 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("jsonb_recv")) => Jsonb, 3805;
2976 },
2977 "namerecv" => Scalar {
2978 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("namerecv")) => PgLegacyName, 2422;
2979 },
2980 "numeric_recv" => Scalar {
2981 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("numeric_recv")) => Numeric, 2460;
2982 },
2983 "oidrecv" => Scalar {
2984 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("oidrecv")) => Oid, 2418;
2985 },
2986 "record_recv" => Scalar {
2987 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("recordrerecord_recvcv")) => RecordAny, 2402;
2988 },
2989 "regclassrecv" => Scalar {
2990 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("regclassrecv")) => RegClass, 2452;
2991 },
2992 "regprocrecv" => Scalar {
2993 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("regprocrecv")) => RegProc, 2444;
2994 },
2995 "regtyperecv" => Scalar {
2996 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("regtyperecv")) => RegType, 2454;
2997 },
2998 "int2recv" => Scalar {
2999 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("int2recv")) => Int16, 2404;
3000 },
3001 "time_recv" => Scalar {
3002 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("time_recv")) => Time, 2470;
3003 },
3004 "timestamp_recv" => Scalar {
3005 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("timestamp_recv")) => Timestamp, 2474;
3006 },
3007 "timestamptz_recv" => Scalar {
3008 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("timestamptz_recv")) => TimestampTz, 2476;
3009 },
3010 "uuid_recv" => Scalar {
3011 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("uuid_recv")) => Uuid, 2961;
3012 },
3013 "varcharrecv" => Scalar {
3014 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("varcharrecv")) => VarChar, 2432;
3015 },
3016 "int2vectorrecv" => Scalar {
3017 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("int2vectorrecv")) => Int2Vector, 2410;
3018 },
3019 "anycompatiblearray_recv" => Scalar {
3020 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("anycompatiblearray_recv")) => ArrayAnyCompatible, 5090;
3021 },
3022 "array_recv" => Scalar {
3023 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("array_recv")) => ArrayAny, 2400;
3024 },
3025 "range_recv" => Scalar {
3026 params!(Internal) => Operation::nullary(|_ecx| catalog_name_only!("range_recv")) => RangeAny, 3836;
3027 },
3028
3029
3030 "array_agg" => Aggregate {
3032 params!(NonVecAny) => Operation::unary_ordered(|ecx, e, order_by| {
3033 let elem_type = ecx.scalar_type(&e);
3034
3035 let elem_type = match elem_type.array_of_self_elem_type() {
3036 Ok(elem_type) => elem_type,
3037 Err(elem_type) => bail_unsupported!(
3038 format!("array_agg on {}", ecx.humanize_scalar_type(&elem_type, false))
3039 ),
3040 };
3041
3042 let e_arr = HirScalarExpr::call_variadic(
3045 VariadicFunc::ArrayCreate { elem_type },
3046 vec![e],
3047 );
3048 Ok((e_arr, AggregateFunc::ArrayConcat { order_by }))
3049 }) => ArrayAny, 2335;
3050 params!(ArrayAny) => Operation::unary(|_ecx, _e| bail_unsupported!("array_agg on arrays")) => ArrayAny, 4053;
3051 },
3052 "bool_and" => Aggregate {
3053 params!(Bool) => Operation::nullary(|_ecx| catalog_name_only!("bool_and")) => Bool, 2517;
3054 },
3055 "bool_or" => Aggregate {
3056 params!(Bool) => Operation::nullary(|_ecx| catalog_name_only!("bool_or")) => Bool, 2518;
3057 },
3058 "count" => Aggregate {
3059 params!() => Operation::nullary(|_ecx| {
3060 Ok((HirScalarExpr::literal_true(), AggregateFunc::Count))
3064 }) => Int64, 2803;
3065 params!(Any) => AggregateFunc::Count => Int64, 2147;
3066 },
3067 "max" => Aggregate {
3068 params!(Bool) => AggregateFunc::MaxBool => Bool, oid::FUNC_MAX_BOOL_OID;
3069 params!(Int16) => AggregateFunc::MaxInt16 => Int16, 2117;
3070 params!(Int32) => AggregateFunc::MaxInt32 => Int32, 2116;
3071 params!(Int64) => AggregateFunc::MaxInt64 => Int64, 2115;
3072 params!(UInt16) => AggregateFunc::MaxUInt16 => UInt16, oid::FUNC_MAX_UINT16_OID;
3073 params!(UInt32) => AggregateFunc::MaxUInt32 => UInt32, oid::FUNC_MAX_UINT32_OID;
3074 params!(UInt64) => AggregateFunc::MaxUInt64 => UInt64, oid::FUNC_MAX_UINT64_OID;
3075 params!(MzTimestamp) => AggregateFunc::MaxMzTimestamp => MzTimestamp, oid::FUNC_MAX_MZ_TIMESTAMP_OID;
3076 params!(Float32) => AggregateFunc::MaxFloat32 => Float32, 2119;
3077 params!(Float64) => AggregateFunc::MaxFloat64 => Float64, 2120;
3078 params!(String) => AggregateFunc::MaxString => String, 2129;
3079 params!(Char) => AggregateFunc::MaxString => Char, 2244;
3081 params!(Date) => AggregateFunc::MaxDate => Date, 2122;
3082 params!(Timestamp) => AggregateFunc::MaxTimestamp => Timestamp, 2126;
3083 params!(TimestampTz) => AggregateFunc::MaxTimestampTz => TimestampTz, 2127;
3084 params!(Numeric) => AggregateFunc::MaxNumeric => Numeric, oid::FUNC_MAX_NUMERIC_OID;
3085 params!(Interval) => AggregateFunc::MaxInterval => Interval, 2128;
3086 params!(Time) => AggregateFunc::MaxTime => Time, 2123;
3087 },
3088 "min" => Aggregate {
3089 params!(Bool) => AggregateFunc::MinBool => Bool, oid::FUNC_MIN_BOOL_OID;
3090 params!(Int16) => AggregateFunc::MinInt16 => Int16, 2133;
3091 params!(Int32) => AggregateFunc::MinInt32 => Int32, 2132;
3092 params!(Int64) => AggregateFunc::MinInt64 => Int64, 2131;
3093 params!(UInt16) => AggregateFunc::MinUInt16 => UInt16, oid::FUNC_MIN_UINT16_OID;
3094 params!(UInt32) => AggregateFunc::MinUInt32 => UInt32, oid::FUNC_MIN_UINT32_OID;
3095 params!(UInt64) => AggregateFunc::MinUInt64 => UInt64, oid::FUNC_MIN_UINT64_OID;
3096 params!(MzTimestamp) => AggregateFunc::MinMzTimestamp => MzTimestamp, oid::FUNC_MIN_MZ_TIMESTAMP_OID;
3097 params!(Float32) => AggregateFunc::MinFloat32 => Float32, 2135;
3098 params!(Float64) => AggregateFunc::MinFloat64 => Float64, 2136;
3099 params!(String) => AggregateFunc::MinString => String, 2145;
3100 params!(Char) => AggregateFunc::MinString => Char, 2245;
3102 params!(Date) => AggregateFunc::MinDate => Date, 2138;
3103 params!(Timestamp) => AggregateFunc::MinTimestamp => Timestamp, 2142;
3104 params!(TimestampTz) => AggregateFunc::MinTimestampTz => TimestampTz, 2143;
3105 params!(Numeric) => AggregateFunc::MinNumeric => Numeric, oid::FUNC_MIN_NUMERIC_OID;
3106 params!(Interval) => AggregateFunc::MinInterval => Interval, 2144;
3107 params!(Time) => AggregateFunc::MinTime => Time, 2139;
3108 },
3109 "jsonb_agg" => Aggregate {
3110 params!(Any) => Operation::unary_ordered(|ecx, e, order_by| {
3111 let e = match ecx.scalar_type(&e) {
3113 ScalarType::Char { length } => e.call_unary(UnaryFunc::PadChar(func::PadChar { length })),
3114 _ => e,
3115 };
3116 let json_null = HirScalarExpr::literal(Datum::JsonNull, ScalarType::Jsonb);
3122 let e = HirScalarExpr::call_variadic(
3123 VariadicFunc::Coalesce,
3124 vec![typeconv::to_jsonb(ecx, e), json_null],
3125 );
3126 Ok((e, AggregateFunc::JsonbAgg { order_by }))
3127 }) => Jsonb, 3267;
3128 },
3129 "jsonb_object_agg" => Aggregate {
3130 params!(Any, Any) => Operation::binary_ordered(|ecx, key, val, order_by| {
3131 let key = match ecx.scalar_type(&key) {
3133 ScalarType::Char { length } => key.call_unary(UnaryFunc::PadChar(func::PadChar { length })),
3134 _ => key,
3135 };
3136 let val = match ecx.scalar_type(&val) {
3137 ScalarType::Char { length } => val.call_unary(UnaryFunc::PadChar(func::PadChar { length })),
3138 _ => val,
3139 };
3140
3141 let json_null = HirScalarExpr::literal(Datum::JsonNull, ScalarType::Jsonb);
3142 let key = typeconv::to_string(ecx, key);
3143 let val = HirScalarExpr::call_variadic(
3150 VariadicFunc::Coalesce,
3151 vec![typeconv::to_jsonb(ecx, val), json_null],
3152 );
3153 let e = HirScalarExpr::call_variadic(
3154 VariadicFunc::RecordCreate {
3155 field_names: vec![ColumnName::from("key"), ColumnName::from("val")],
3156 },
3157 vec![key, val],
3158 );
3159 Ok((e, AggregateFunc::JsonbObjectAgg { order_by }))
3160 }) => Jsonb, 3270;
3161 },
3162 "string_agg" => Aggregate {
3163 params!(String, String) => Operation::binary_ordered(|_ecx, value, sep, order_by| {
3164 let e = HirScalarExpr::call_variadic(
3165 VariadicFunc::RecordCreate {
3166 field_names: vec![ColumnName::from("value"), ColumnName::from("sep")],
3167 },
3168 vec![value, sep],
3169 );
3170 Ok((e, AggregateFunc::StringAgg { order_by }))
3171 }) => String, 3538;
3172 params!(Bytes, Bytes) => Operation::binary(|_ecx, _l, _r| bail_unsupported!("string_agg on BYTEA")) => Bytes, 3545;
3173 },
3174 "string_to_array" => Scalar {
3175 params!(String, String) => VariadicFunc::StringToArray => ScalarType::Array(Box::new(ScalarType::String)), 376;
3176 params!(String, String, String) => VariadicFunc::StringToArray => ScalarType::Array(Box::new(ScalarType::String)), 394;
3177 },
3178 "sum" => Aggregate {
3179 params!(Int16) => AggregateFunc::SumInt16 => Int64, 2109;
3180 params!(Int32) => AggregateFunc::SumInt32 => Int64, 2108;
3181 params!(Int64) => AggregateFunc::SumInt64 => Numeric, 2107;
3182 params!(UInt16) => AggregateFunc::SumUInt16 => UInt64, oid::FUNC_SUM_UINT16_OID;
3183 params!(UInt32) => AggregateFunc::SumUInt32 => UInt64, oid::FUNC_SUM_UINT32_OID;
3184 params!(UInt64) => AggregateFunc::SumUInt64 => Numeric, oid::FUNC_SUM_UINT64_OID;
3185 params!(Float32) => AggregateFunc::SumFloat32 => Float32, 2110;
3186 params!(Float64) => AggregateFunc::SumFloat64 => Float64, 2111;
3187 params!(Numeric) => AggregateFunc::SumNumeric => Numeric, 2114;
3188 params!(Interval) => Operation::unary(|_ecx, _e| {
3189 bail_unsupported!("sum(interval)");
3194 }) => Interval, 2113;
3195 },
3196
3197 "row_number" => ScalarWindow {
3199 params!() => ScalarWindowFunc::RowNumber => Int64, 3100;
3200 },
3201 "rank" => ScalarWindow {
3202 params!() => ScalarWindowFunc::Rank => Int64, 3101;
3203 },
3204 "dense_rank" => ScalarWindow {
3205 params!() => ScalarWindowFunc::DenseRank => Int64, 3102;
3206 },
3207 "lag" => ValueWindow {
3208 params!(AnyElement) => Operation::unary(|ecx, e| {
3210 let typ = ecx.scalar_type(&e);
3211 let e = HirScalarExpr::call_variadic(
3212 VariadicFunc::RecordCreate {
3213 field_names: vec![ColumnName::from("expr"), ColumnName::from("offset"), ColumnName::from("default")],
3214 },
3215 vec![e, HirScalarExpr::literal(Datum::Int32(1), ScalarType::Int32), HirScalarExpr::literal_null(typ)],
3216 );
3217 Ok((e, ValueWindowFunc::Lag))
3218 }) => AnyElement, 3106;
3219 params!(AnyElement, Int32) => Operation::binary(|ecx, e, offset| {
3220 let typ = ecx.scalar_type(&e);
3221 let e = HirScalarExpr::call_variadic(
3222 VariadicFunc::RecordCreate {
3223 field_names: vec![ColumnName::from("expr"), ColumnName::from("offset"), ColumnName::from("default")],
3224 },
3225 vec![e, offset, HirScalarExpr::literal_null(typ)],
3226 );
3227 Ok((e, ValueWindowFunc::Lag))
3228 }) => AnyElement, 3107;
3229 params!(AnyCompatible, Int32, AnyCompatible) => Operation::variadic(|_ecx, exprs| {
3230 let e = HirScalarExpr::call_variadic(
3231 VariadicFunc::RecordCreate {
3232 field_names: vec![ColumnName::from("expr"), ColumnName::from("offset"), ColumnName::from("default")],
3233 },
3234 exprs,
3235 );
3236 Ok((e, ValueWindowFunc::Lag))
3237 }) => AnyCompatible, 3108;
3238 },
3239 "lead" => ValueWindow {
3240 params!(AnyElement) => Operation::unary(|ecx, e| {
3242 let typ = ecx.scalar_type(&e);
3243 let e = HirScalarExpr::call_variadic(
3244 VariadicFunc::RecordCreate {
3245 field_names: vec![ColumnName::from("expr"), ColumnName::from("offset"), ColumnName::from("default")],
3246 },
3247 vec![e, HirScalarExpr::literal(Datum::Int32(1), ScalarType::Int32), HirScalarExpr::literal_null(typ)],
3248 );
3249 Ok((e, ValueWindowFunc::Lead))
3250 }) => AnyElement, 3109;
3251 params!(AnyElement, Int32) => Operation::binary(|ecx, e, offset| {
3252 let typ = ecx.scalar_type(&e);
3253 let e = HirScalarExpr::call_variadic(
3254 VariadicFunc::RecordCreate {
3255 field_names: vec![ColumnName::from("expr"), ColumnName::from("offset"), ColumnName::from("default")],
3256 },
3257 vec![e, offset, HirScalarExpr::literal_null(typ)],
3258 );
3259 Ok((e, ValueWindowFunc::Lead))
3260 }) => AnyElement, 3110;
3261 params!(AnyCompatible, Int32, AnyCompatible) => Operation::variadic(|_ecx, exprs| {
3262 let e = HirScalarExpr::call_variadic(
3263 VariadicFunc::RecordCreate {
3264 field_names: vec![ColumnName::from("expr"), ColumnName::from("offset"), ColumnName::from("default")],
3265 },
3266 exprs,
3267 );
3268 Ok((e, ValueWindowFunc::Lead))
3269 }) => AnyCompatible, 3111;
3270 },
3271 "first_value" => ValueWindow {
3272 params!(AnyElement) => ValueWindowFunc::FirstValue => AnyElement, 3112;
3273 },
3274 "last_value" => ValueWindow {
3275 params!(AnyElement) => ValueWindowFunc::LastValue => AnyElement, 3113;
3276 },
3277
3278 "generate_series" => Table {
3280 params!(Int32, Int32, Int32) => Operation::variadic(move |_ecx, exprs| {
3281 Ok(TableFuncPlan {
3282 imp: TableFuncImpl::CallTable {
3283 func: TableFunc::GenerateSeriesInt32,
3284 exprs,
3285 },
3286 column_names: vec!["generate_series".into()],
3287 })
3288 }) => ReturnType::set_of(Int32.into()), 1066;
3289 params!(Int32, Int32) => Operation::binary(move |_ecx, start, stop| {
3290 Ok(TableFuncPlan {
3291 imp: TableFuncImpl::CallTable {
3292 func: TableFunc::GenerateSeriesInt32,
3293 exprs: vec![start, stop, HirScalarExpr::literal(Datum::Int32(1), ScalarType::Int32)],
3294 },
3295 column_names: vec!["generate_series".into()],
3296 })
3297 }) => ReturnType::set_of(Int32.into()), 1067;
3298 params!(Int64, Int64, Int64) => Operation::variadic(move |_ecx, exprs| {
3299 Ok(TableFuncPlan {
3300 imp: TableFuncImpl::CallTable {
3301 func: TableFunc::GenerateSeriesInt64,
3302 exprs,
3303 },
3304 column_names: vec!["generate_series".into()],
3305 })
3306 }) => ReturnType::set_of(Int64.into()), 1068;
3307 params!(Int64, Int64) => Operation::binary(move |_ecx, start, stop| {
3308 Ok(TableFuncPlan {
3309 imp: TableFuncImpl::CallTable {
3310 func: TableFunc::GenerateSeriesInt64,
3311 exprs: vec![start, stop, HirScalarExpr::literal(Datum::Int64(1), ScalarType::Int64)],
3312 },
3313 column_names: vec!["generate_series".into()],
3314 })
3315 }) => ReturnType::set_of(Int64.into()), 1069;
3316 params!(Timestamp, Timestamp, Interval) => Operation::variadic(move |_ecx, exprs| {
3317 Ok(TableFuncPlan {
3318 imp: TableFuncImpl::CallTable {
3319 func: TableFunc::GenerateSeriesTimestamp,
3320 exprs,
3321 },
3322 column_names: vec!["generate_series".into()],
3323 })
3324 }) => ReturnType::set_of(Timestamp.into()), 938;
3325 params!(TimestampTz, TimestampTz, Interval) => Operation::variadic(move |_ecx, exprs| {
3326 Ok(TableFuncPlan {
3327 imp: TableFuncImpl::CallTable {
3328 func: TableFunc::GenerateSeriesTimestampTz,
3329 exprs,
3330 },
3331 column_names: vec!["generate_series".into()],
3332 })
3333 }) => ReturnType::set_of(TimestampTz.into()), 939;
3334 },
3335
3336 "generate_subscripts" => Table {
3337 params!(ArrayAny, Int32) => Operation::variadic(move |_ecx, exprs| {
3338 Ok(TableFuncPlan {
3339 imp: TableFuncImpl::CallTable {
3340 func: TableFunc::GenerateSubscriptsArray,
3341 exprs,
3342 },
3343 column_names: vec!["generate_subscripts".into()],
3344 })
3345 }) => ReturnType::set_of(Int32.into()), 1192;
3346 },
3347
3348 "jsonb_array_elements" => Table {
3349 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
3350 Ok(TableFuncPlan {
3351 imp: TableFuncImpl::CallTable {
3352 func: TableFunc::JsonbArrayElements { stringify: false },
3353 exprs: vec![jsonb],
3354 },
3355 column_names: vec!["value".into()],
3356 })
3357 }) => ReturnType::set_of(Jsonb.into()), 3219;
3358 },
3359 "jsonb_array_elements_text" => Table {
3360 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
3361 Ok(TableFuncPlan {
3362 imp: TableFuncImpl::CallTable {
3363 func: TableFunc::JsonbArrayElements { stringify: true },
3364 exprs: vec![jsonb],
3365 },
3366 column_names: vec!["value".into()],
3367 })
3368 }) => ReturnType::set_of(String.into()), 3465;
3369 },
3370 "jsonb_each" => Table {
3371 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
3372 Ok(TableFuncPlan {
3373 imp: TableFuncImpl::CallTable {
3374 func: TableFunc::JsonbEach { stringify: false },
3375 exprs: vec![jsonb],
3376 },
3377 column_names: vec!["key".into(), "value".into()],
3378 })
3379 }) => ReturnType::set_of(RecordAny), 3208;
3380 },
3381 "jsonb_each_text" => Table {
3382 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
3383 Ok(TableFuncPlan {
3384 imp: TableFuncImpl::CallTable {
3385 func: TableFunc::JsonbEach { stringify: true },
3386 exprs: vec![jsonb],
3387 },
3388 column_names: vec!["key".into(), "value".into()],
3389 })
3390 }) => ReturnType::set_of(RecordAny), 3932;
3391 },
3392 "jsonb_object_keys" => Table {
3393 params!(Jsonb) => Operation::unary(move |_ecx, jsonb| {
3394 Ok(TableFuncPlan {
3395 imp: TableFuncImpl::CallTable {
3396 func: TableFunc::JsonbObjectKeys,
3397 exprs: vec![jsonb],
3398 },
3399 column_names: vec!["jsonb_object_keys".into()],
3400 })
3401 }) => ReturnType::set_of(String.into()), 3931;
3402 },
3403 "date_bin_hopping" => Table {
3407 params!(Interval, Interval, Timestamp) => experimental_sql_impl_table_func(&vars::ENABLE_DATE_BIN_HOPPING, "
3409 SELECT *
3410 FROM pg_catalog.generate_series(
3411 pg_catalog.date_bin($1, $3 + $1, '1970-01-01') - $2, $3, $1
3412 ) AS dbh(date_bin_hopping)
3413 ") => ReturnType::set_of(Timestamp.into()), oid::FUNC_MZ_DATE_BIN_HOPPING_UNIX_EPOCH_TS_OID;
3414 params!(Interval, Interval, TimestampTz) => experimental_sql_impl_table_func(&vars::ENABLE_DATE_BIN_HOPPING, "
3416 SELECT *
3417 FROM pg_catalog.generate_series(
3418 pg_catalog.date_bin($1, $3 + $1, '1970-01-01') - $2, $3, $1
3419 ) AS dbh(date_bin_hopping)
3420 ") => ReturnType::set_of(TimestampTz.into()), oid::FUNC_MZ_DATE_BIN_HOPPING_UNIX_EPOCH_TSTZ_OID;
3421 params!(Interval, Interval, Timestamp, Timestamp) => experimental_sql_impl_table_func(&vars::ENABLE_DATE_BIN_HOPPING, "
3423 SELECT *
3424 FROM pg_catalog.generate_series(
3425 pg_catalog.date_bin($1, $3 + $1, $4) - $2, $3, $1
3426 ) AS dbh(date_bin_hopping)
3427 ") => ReturnType::set_of(Timestamp.into()), oid::FUNC_MZ_DATE_BIN_HOPPING_TS_OID;
3428 params!(Interval, Interval, TimestampTz, TimestampTz) => experimental_sql_impl_table_func(&vars::ENABLE_DATE_BIN_HOPPING, "
3430 SELECT *
3431 FROM pg_catalog.generate_series(
3432 pg_catalog.date_bin($1, $3 + $1, $4) - $2, $3, $1
3433 ) AS dbh(date_bin_hopping)
3434 ") => ReturnType::set_of(TimestampTz.into()), oid::FUNC_MZ_DATE_BIN_HOPPING_TSTZ_OID;
3435 },
3436 "encode" => Scalar {
3437 params!(Bytes, String) => BinaryFunc::Encode => String, 1946;
3438 },
3439 "decode" => Scalar {
3440 params!(String, String) => BinaryFunc::Decode => Bytes, 1947;
3441 },
3442 "regexp_split_to_array" => Scalar {
3443 params!(String, String) => VariadicFunc::RegexpSplitToArray => ScalarType::Array(Box::new(ScalarType::String)), 2767;
3444 params!(String, String, String) => VariadicFunc::RegexpSplitToArray => ScalarType::Array(Box::new(ScalarType::String)), 2768;
3445 },
3446 "regexp_split_to_table" => Table {
3447 params!(String, String) => sql_impl_table_func("
3448 SELECT unnest(regexp_split_to_array($1, $2))
3449 ") => ReturnType::set_of(String.into()), 2765;
3450 params!(String, String, String) => sql_impl_table_func("
3451 SELECT unnest(regexp_split_to_array($1, $2, $3))
3452 ") => ReturnType::set_of(String.into()), 2766;
3453 },
3454 "regexp_replace" => Scalar {
3455 params!(String, String, String) => VariadicFunc::RegexpReplace => String, 2284;
3456 params!(String, String, String, String) => VariadicFunc::RegexpReplace => String, 2285;
3457 },
3460 "regexp_matches" => Table {
3461 params!(String, String) => Operation::variadic(move |_ecx, exprs| {
3462 let column_names = vec!["regexp_matches".into()];
3463 Ok(TableFuncPlan {
3464 imp: TableFuncImpl::CallTable {
3465 func: TableFunc::RegexpMatches,
3466 exprs: vec![exprs[0].clone(), exprs[1].clone()],
3467 },
3468 column_names,
3469 })
3470 }) => ReturnType::set_of(ScalarType::Array(Box::new(ScalarType::String)).into()), 2763;
3471 params!(String, String, String) => Operation::variadic(move |_ecx, exprs| {
3472 let column_names = vec!["regexp_matches".into()];
3473 Ok(TableFuncPlan {
3474 imp: TableFuncImpl::CallTable {
3475 func: TableFunc::RegexpMatches,
3476 exprs: vec![exprs[0].clone(), exprs[1].clone(), exprs[2].clone()],
3477 },
3478 column_names,
3479 })
3480 }) => ReturnType::set_of(ScalarType::Array(Box::new(ScalarType::String)).into()), 2764;
3481 },
3482 "reverse" => Scalar {
3483 params!(String) => UnaryFunc::Reverse(func::Reverse) => String, 3062;
3484 }
3485 };
3486
3487 for sef_builtin in PG_CATALOG_SEF_BUILTINS.values() {
3491 builtins.insert(
3492 sef_builtin.name,
3493 Func::Scalar(vec![FuncImpl {
3494 oid: sef_builtin.oid,
3495 params: ParamList::Exact(
3496 sef_builtin
3497 .param_types
3498 .iter()
3499 .map(|t| ParamType::from(t.clone()))
3500 .collect(),
3501 ),
3502 return_type: ReturnType::scalar(ParamType::from(
3503 sef_builtin.return_type.scalar_type.clone(),
3504 )),
3505 op: Operation::variadic(|_ecx, _e| {
3506 bail_unsupported!(format!("{} in this position", sef_builtin.name))
3507 }),
3508 }]),
3509 );
3510 }
3511
3512 builtins
3513});
3514
3515pub static INFORMATION_SCHEMA_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> =
3516 LazyLock::new(|| {
3517 use ParamType::*;
3518 builtins! {
3519 "_pg_expandarray" => Table {
3520 params!(ArrayAny) => sql_impl_table_func("
3522 SELECT
3523 $1[s] AS x,
3524 s - pg_catalog.array_lower($1, 1) + 1 AS n
3525 FROM pg_catalog.generate_series(
3526 pg_catalog.array_lower($1, 1),
3527 pg_catalog.array_upper($1, 1),
3528 1) as g(s)
3529 ") => ReturnType::set_of(RecordAny), oid::FUNC_PG_EXPAND_ARRAY;
3530 }
3531 }
3532 });
3533
3534pub static MZ_CATALOG_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
3535 use ParamType::*;
3536 use ScalarBaseType::*;
3537 builtins! {
3538 "constant_time_eq" => Scalar {
3539 params!(Bytes, Bytes) => BinaryFunc::ConstantTimeEqBytes => Bool, oid::FUNC_CONSTANT_TIME_EQ_BYTES_OID;
3540 params!(String, String) => BinaryFunc::ConstantTimeEqString => Bool, oid::FUNC_CONSTANT_TIME_EQ_STRING_OID;
3541 },
3542 "avg_internal_v1" => Scalar {
3550 params!(Int64) => Operation::nullary(|_ecx| catalog_name_only!("avg_internal_v1")) => Numeric, oid::FUNC_AVG_INTERNAL_V1_INT64_OID;
3551 params!(Int32) => Operation::nullary(|_ecx| catalog_name_only!("avg_internal_v1")) => Numeric, oid::FUNC_AVG_INTERNAL_V1_INT32_OID;
3552 params!(Int16) => Operation::nullary(|_ecx| catalog_name_only!("avg_internal_v1")) => Numeric, oid::FUNC_AVG_INTERNAL_V1_INT16_OID;
3553 params!(UInt64) => Operation::nullary(|_ecx| catalog_name_only!("avg_internal_v1")) => Numeric, oid::FUNC_AVG_INTERNAL_V1_UINT64_OID;
3554 params!(UInt32) => Operation::nullary(|_ecx| catalog_name_only!("avg_internal_v1")) => Numeric, oid::FUNC_AVG_INTERNAL_V1_UINT32_OID;
3555 params!(UInt16) => Operation::nullary(|_ecx| catalog_name_only!("avg_internal_v1")) => Numeric, oid::FUNC_AVG_INTERNAL_V1_UINT16_OID;
3556 params!(Float32) => Operation::nullary(|_ecx| catalog_name_only!("avg_internal_v1")) => Float64, oid::FUNC_AVG_INTERNAL_V1_FLOAT32_OID;
3557 params!(Float64) => Operation::nullary(|_ecx| catalog_name_only!("avg_internal_v1")) => Float64, oid::FUNC_AVG_INTERNAL_V1_FLOAT64_OID;
3558 params!(Interval) => Operation::nullary(|_ecx| catalog_name_only!("avg_internal_v1")) => Interval, oid::FUNC_AVG_INTERNAL_V1_INTERVAL_OID;
3559 },
3560 "csv_extract" => Table {
3561 params!(Int64, String) => Operation::binary(move |_ecx, ncols, input| {
3562 const MAX_EXTRACT_COLUMNS: i64 = 8192;
3563 const TOO_MANY_EXTRACT_COLUMNS: i64 = MAX_EXTRACT_COLUMNS + 1;
3564
3565 let ncols = match ncols.into_literal_int64() {
3566 None | Some(i64::MIN..=0) => {
3567 sql_bail!("csv_extract number of columns must be a positive integer literal");
3568 },
3569 Some(ncols @ 1..=MAX_EXTRACT_COLUMNS) => ncols,
3570 Some(ncols @ TOO_MANY_EXTRACT_COLUMNS..) => {
3571 return Err(PlanError::TooManyColumns {
3572 max_num_columns: usize::try_from(MAX_EXTRACT_COLUMNS).unwrap_or(usize::MAX),
3573 req_num_columns: usize::try_from(ncols).unwrap_or(usize::MAX),
3574 });
3575 },
3576 };
3577 let ncols = usize::try_from(ncols).expect("known to be greater than zero");
3578
3579 let column_names = (1..=ncols).map(|i| format!("column{}", i).into()).collect();
3580 Ok(TableFuncPlan {
3581 imp: TableFuncImpl::CallTable {
3582 func: TableFunc::CsvExtract(ncols),
3583 exprs: vec![input],
3584 },
3585 column_names,
3586 })
3587 }) => ReturnType::set_of(RecordAny), oid::FUNC_CSV_EXTRACT_OID;
3588 },
3589 "concat_agg" => Aggregate {
3590 params!(Any) => Operation::unary(|_ecx, _e| bail_unsupported!("concat_agg")) => String, oid::FUNC_CONCAT_AGG_OID;
3591 },
3592 "crc32" => Scalar {
3593 params!(String) => UnaryFunc::Crc32String(func::Crc32String) => UInt32, oid::FUNC_CRC32_STRING_OID;
3594 params!(Bytes) => UnaryFunc::Crc32Bytes(func::Crc32Bytes) => UInt32, oid::FUNC_CRC32_BYTES_OID;
3595 },
3596 "datediff" => Scalar {
3597 params!(String, Timestamp, Timestamp) => VariadicFunc::DateDiffTimestamp => Int64, oid::FUNC_DATEDIFF_TIMESTAMP;
3598 params!(String, TimestampTz, TimestampTz) => VariadicFunc::DateDiffTimestampTz => Int64, oid::FUNC_DATEDIFF_TIMESTAMPTZ;
3599 params!(String, Date, Date) => VariadicFunc::DateDiffDate => Int64, oid::FUNC_DATEDIFF_DATE;
3600 params!(String, Time, Time) => VariadicFunc::DateDiffTime => Int64, oid::FUNC_DATEDIFF_TIME;
3601 },
3602 "has_cluster_privilege" => Scalar {
3605 params!(String, String, String) => sql_impl_func("has_cluster_privilege(mz_internal.mz_role_oid($1), $2, $3)") => Bool, oid::FUNC_HAS_CLUSTER_PRIVILEGE_TEXT_TEXT_TEXT_OID;
3606 params!(Oid, String, String) => sql_impl_func(&format!("
3607 CASE
3608 -- We must first check $2 to avoid a potentially null error message (an error itself).
3609 WHEN $2 IS NULL
3610 THEN NULL
3611 -- Validate the cluster name in order to return a proper error.
3612 WHEN NOT EXISTS (SELECT name FROM mz_clusters WHERE name = $2)
3613 THEN mz_unsafe.mz_error_if_null(NULL::boolean, 'error cluster \"' || $2 || '\" does not exist')
3614 -- Validate the privileges and other arguments.
3615 WHEN NOT mz_internal.mz_validate_privileges($3)
3616 OR $1 IS NULL
3617 OR $3 IS NULL
3618 OR $1 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
3619 THEN NULL
3620 ELSE COALESCE(
3621 (
3622 SELECT
3623 bool_or(
3624 mz_internal.mz_acl_item_contains_privilege(privilege, $3)
3625 )
3626 AS has_cluster_privilege
3627 FROM
3628 (
3629 SELECT
3630 unnest(privileges)
3631 FROM
3632 mz_clusters
3633 WHERE
3634 mz_clusters.name = $2
3635 )
3636 AS user_privs (privilege)
3637 LEFT JOIN mz_catalog.mz_roles ON
3638 mz_internal.mz_aclitem_grantee(privilege) = mz_roles.id
3639 WHERE
3640 mz_internal.mz_aclitem_grantee(privilege) = '{}' OR pg_has_role($1, mz_roles.oid, 'USAGE')
3641 ),
3642 false
3643 )
3644 END
3645 ", RoleId::Public)) => Bool, oid::FUNC_HAS_CLUSTER_PRIVILEGE_OID_TEXT_TEXT_OID;
3646 params!(String, String) => sql_impl_func("has_cluster_privilege(current_user, $1, $2)") => Bool, oid::FUNC_HAS_CLUSTER_PRIVILEGE_TEXT_TEXT_OID;
3647 },
3648 "has_connection_privilege" => Scalar {
3649 params!(String, String, String) => sql_impl_func("has_connection_privilege(mz_internal.mz_role_oid($1), mz_internal.mz_connection_oid($2), $3)") => Bool, oid::FUNC_HAS_CONNECTION_PRIVILEGE_TEXT_TEXT_TEXT_OID;
3650 params!(String, Oid, String) => sql_impl_func("has_connection_privilege(mz_internal.mz_role_oid($1), $2, $3)") => Bool, oid::FUNC_HAS_CONNECTION_PRIVILEGE_TEXT_OID_TEXT_OID;
3651 params!(Oid, String, String) => sql_impl_func("has_connection_privilege($1, mz_internal.mz_connection_oid($2), $3)") => Bool, oid::FUNC_HAS_CONNECTION_PRIVILEGE_OID_TEXT_TEXT_OID;
3652 params!(Oid, Oid, String) => sql_impl_func(&privilege_fn!("has_connection_privilege", "mz_connections")) => Bool, oid::FUNC_HAS_CONNECTION_PRIVILEGE_OID_OID_TEXT_OID;
3653 params!(String, String) => sql_impl_func("has_connection_privilege(current_user, $1, $2)") => Bool, oid::FUNC_HAS_CONNECTION_PRIVILEGE_TEXT_TEXT_OID;
3654 params!(Oid, String) => sql_impl_func("has_connection_privilege(current_user, $1, $2)") => Bool, oid::FUNC_HAS_CONNECTION_PRIVILEGE_OID_TEXT_OID;
3655 },
3656 "has_role" => Scalar {
3657 params!(String, String, String) => sql_impl_func("pg_has_role($1, $2, $3)") => Bool, oid::FUNC_HAS_ROLE_TEXT_TEXT_TEXT_OID;
3658 params!(String, Oid, String) => sql_impl_func("pg_has_role($1, $2, $3)") => Bool, oid::FUNC_HAS_ROLE_TEXT_OID_TEXT_OID;
3659 params!(Oid, String, String) => sql_impl_func("pg_has_role($1, $2, $3)") => Bool, oid::FUNC_HAS_ROLE_OID_TEXT_TEXT_OID;
3660 params!(Oid, Oid, String) => sql_impl_func("pg_has_role($1, $2, $3)") => Bool, oid::FUNC_HAS_ROLE_OID_OID_TEXT_OID;
3661 params!(String, String) => sql_impl_func("pg_has_role($1, $2)") => Bool, oid::FUNC_HAS_ROLE_TEXT_TEXT_OID;
3662 params!(Oid, String) => sql_impl_func("pg_has_role($1, $2)") => Bool, oid::FUNC_HAS_ROLE_OID_TEXT_OID;
3663 },
3664 "has_secret_privilege" => Scalar {
3665 params!(String, String, String) => sql_impl_func("has_secret_privilege(mz_internal.mz_role_oid($1), mz_internal.mz_secret_oid($2), $3)") => Bool, oid::FUNC_HAS_SECRET_PRIVILEGE_TEXT_TEXT_TEXT_OID;
3666 params!(String, Oid, String) => sql_impl_func("has_secret_privilege(mz_internal.mz_role_oid($1), $2, $3)") => Bool, oid::FUNC_HAS_SECRET_PRIVILEGE_TEXT_OID_TEXT_OID;
3667 params!(Oid, String, String) => sql_impl_func("has_secret_privilege($1, mz_internal.mz_secret_oid($2), $3)") => Bool, oid::FUNC_HAS_SECRET_PRIVILEGE_OID_TEXT_TEXT_OID;
3668 params!(Oid, Oid, String) => sql_impl_func(&privilege_fn!("has_secret_privilege", "mz_secrets")) => Bool, oid::FUNC_HAS_SECRET_PRIVILEGE_OID_OID_TEXT_OID;
3669 params!(String, String) => sql_impl_func("has_secret_privilege(current_user, $1, $2)") => Bool, oid::FUNC_HAS_SECRET_PRIVILEGE_TEXT_TEXT_OID;
3670 params!(Oid, String) => sql_impl_func("has_secret_privilege(current_user, $1, $2)") => Bool, oid::FUNC_HAS_SECRET_PRIVILEGE_OID_TEXT_OID;
3671 },
3672 "has_system_privilege" => Scalar {
3673 params!(String, String) => sql_impl_func("has_system_privilege(mz_internal.mz_role_oid($1), $2)") => Bool, oid::FUNC_HAS_SYSTEM_PRIVILEGE_TEXT_TEXT_OID;
3674 params!(Oid, String) => sql_impl_func(&format!("
3675 CASE
3676 -- We need to validate the privileges to return a proper error before
3677 -- anything else.
3678 WHEN NOT mz_internal.mz_validate_privileges($2)
3679 OR $1 IS NULL
3680 OR $2 IS NULL
3681 OR $1 NOT IN (SELECT oid FROM mz_catalog.mz_roles)
3682 THEN NULL
3683 ELSE COALESCE(
3684 (
3685 SELECT
3686 bool_or(
3687 mz_internal.mz_acl_item_contains_privilege(privileges, $2)
3688 )
3689 AS has_system_privilege
3690 FROM mz_catalog.mz_system_privileges
3691 LEFT JOIN mz_catalog.mz_roles ON
3692 mz_internal.mz_aclitem_grantee(privileges) = mz_roles.id
3693 WHERE
3694 mz_internal.mz_aclitem_grantee(privileges) = '{}' OR pg_has_role($1, mz_roles.oid, 'USAGE')
3695 ),
3696 false
3697 )
3698 END
3699 ", RoleId::Public)) => Bool, oid::FUNC_HAS_SYSTEM_PRIVILEGE_OID_TEXT_OID;
3700 params!(String) => sql_impl_func("has_system_privilege(current_user, $1)") => Bool, oid::FUNC_HAS_SYSTEM_PRIVILEGE_TEXT_OID;
3701 },
3702 "has_type_privilege" => Scalar {
3703 params!(String, String, String) => sql_impl_func("has_type_privilege(mz_internal.mz_role_oid($1), $2::regtype::oid, $3)") => Bool, 3138;
3704 params!(String, Oid, String) => sql_impl_func("has_type_privilege(mz_internal.mz_role_oid($1), $2, $3)") => Bool, 3139;
3705 params!(Oid, String, String) => sql_impl_func("has_type_privilege($1, $2::regtype::oid, $3)") => Bool, 3140;
3706 params!(Oid, Oid, String) => sql_impl_func(&privilege_fn!("has_type_privilege", "mz_types")) => Bool, 3141;
3707 params!(String, String) => sql_impl_func("has_type_privilege(current_user, $1, $2)") => Bool, 3142;
3708 params!(Oid, String) => sql_impl_func("has_type_privilege(current_user, $1, $2)") => Bool, 3143;
3709 },
3710 "kafka_murmur2" => Scalar {
3711 params!(String) => UnaryFunc::KafkaMurmur2String(func::KafkaMurmur2String) => Int32, oid::FUNC_KAFKA_MURMUR2_STRING_OID;
3712 params!(Bytes) => UnaryFunc::KafkaMurmur2Bytes(func::KafkaMurmur2Bytes) => Int32, oid::FUNC_KAFKA_MURMUR2_BYTES_OID;
3713 },
3714 "list_agg" => Aggregate {
3715 params!(Any) => Operation::unary_ordered(|ecx, e, order_by| {
3716 if let ScalarType::Char {.. } = ecx.scalar_type(&e) {
3717 bail_unsupported!("list_agg on char");
3718 };
3719 let e_arr = HirScalarExpr::call_variadic(
3722 VariadicFunc::ListCreate { elem_type: ecx.scalar_type(&e) },
3723 vec![e],
3724 );
3725 Ok((e_arr, AggregateFunc::ListConcat { order_by }))
3726 }) => ListAnyCompatible, oid::FUNC_LIST_AGG_OID;
3727 },
3728 "list_append" => Scalar {
3729 vec![ListAnyCompatible, ListElementAnyCompatible] => BinaryFunc::ListElementConcat => ListAnyCompatible, oid::FUNC_LIST_APPEND_OID;
3730 },
3731 "list_cat" => Scalar {
3732 vec![ListAnyCompatible, ListAnyCompatible] => BinaryFunc::ListListConcat => ListAnyCompatible, oid::FUNC_LIST_CAT_OID;
3733 },
3734 "list_n_layers" => Scalar {
3735 vec![ListAny] => Operation::unary(|ecx, e| {
3736 ecx.require_feature_flag(&crate::session::vars::ENABLE_LIST_N_LAYERS)?;
3737 let d = ecx.scalar_type(&e).unwrap_list_n_layers();
3738 match i32::try_from(d) {
3739 Ok(d) => Ok(HirScalarExpr::literal(Datum::Int32(d), ScalarType::Int32)),
3740 Err(_) => sql_bail!("list has more than {} layers", i32::MAX),
3741 }
3742
3743 }) => Int32, oid::FUNC_LIST_N_LAYERS_OID;
3744 },
3745 "list_length" => Scalar {
3746 vec![ListAny] => UnaryFunc::ListLength(func::ListLength) => Int32, oid::FUNC_LIST_LENGTH_OID;
3747 },
3748 "list_length_max" => Scalar {
3749 vec![ListAny, Plain(ScalarType::Int64)] => Operation::binary(|ecx, lhs, rhs| {
3750 ecx.require_feature_flag(&crate::session::vars::ENABLE_LIST_LENGTH_MAX)?;
3751 let max_layer = ecx.scalar_type(&lhs).unwrap_list_n_layers();
3752 Ok(lhs.call_binary(rhs, BinaryFunc::ListLengthMax { max_layer }))
3753 }) => Int32, oid::FUNC_LIST_LENGTH_MAX_OID;
3754 },
3755 "list_prepend" => Scalar {
3756 vec![ListElementAnyCompatible, ListAnyCompatible] => BinaryFunc::ElementListConcat => ListAnyCompatible, oid::FUNC_LIST_PREPEND_OID;
3757 },
3758 "list_remove" => Scalar {
3759 vec![ListAnyCompatible, ListElementAnyCompatible] => Operation::binary(|ecx, lhs, rhs| {
3760 ecx.require_feature_flag(&crate::session::vars::ENABLE_LIST_REMOVE)?;
3761 Ok(lhs.call_binary(rhs, BinaryFunc::ListRemove))
3762 }) => ListAnyCompatible, oid::FUNC_LIST_REMOVE_OID;
3763 },
3764 "map_agg" => Aggregate {
3765 params!(String, Any) => Operation::binary_ordered(|ecx, key, val, order_by| {
3766 let (value_type, val) = match ecx.scalar_type(&val) {
3767 ScalarType::Char { length } => (ScalarType::Char { length }, val.call_unary(UnaryFunc::PadChar(func::PadChar { length }))),
3769 typ => (typ, val),
3770 };
3771
3772 let e = HirScalarExpr::call_variadic(
3773 VariadicFunc::RecordCreate {
3774 field_names: vec![ColumnName::from("key"), ColumnName::from("val")],
3775 },
3776 vec![key, val],
3777 );
3778
3779 Ok((e, AggregateFunc::MapAgg { order_by, value_type }))
3780 }) => MapAny, oid::FUNC_MAP_AGG;
3781 },
3782 "map_build" => Scalar {
3783 params!(ListAny) => Operation::unary(|ecx, expr| {
3794 let ty = ecx.scalar_type(&expr);
3795
3796 let err = || {
3799 Err(sql_err!(
3800 "function map_build({}) does not exist",
3801 ecx.humanize_scalar_type(&ty.clone(), false)
3802 ))
3803 };
3804
3805 let value_type = match &ty {
3808 ScalarType::List { element_type, .. } => match &**element_type {
3809 ScalarType::Record { fields, .. } if fields.len() == 2 => {
3810 if fields[0].1.scalar_type != ScalarType::String {
3811 return err();
3812 }
3813
3814 fields[1].1.scalar_type.clone()
3815 }
3816 _ => return err(),
3817 },
3818 _ => unreachable!("input guaranteed to be list"),
3819 };
3820
3821 Ok(expr.call_unary(UnaryFunc::MapBuildFromRecordList(
3822 func::MapBuildFromRecordList { value_type },
3823 )))
3824 }) => MapAny, oid::FUNC_MAP_BUILD;
3825 },
3826 "map_length" => Scalar {
3827 params![MapAny] => UnaryFunc::MapLength(func::MapLength) => Int32, oid::FUNC_MAP_LENGTH_OID;
3828 },
3829 "mz_environment_id" => Scalar {
3830 params!() => UnmaterializableFunc::MzEnvironmentId => String, oid::FUNC_MZ_ENVIRONMENT_ID_OID;
3831 },
3832 "mz_is_superuser" => Scalar {
3833 params!() => UnmaterializableFunc::MzIsSuperuser => ScalarType::Bool, oid::FUNC_MZ_IS_SUPERUSER;
3834 },
3835 "mz_logical_timestamp" => Scalar {
3836 params!() => Operation::nullary(|_ecx| sql_bail!("mz_logical_timestamp() has been renamed to mz_now()")) => MzTimestamp, oid::FUNC_MZ_LOGICAL_TIMESTAMP_OID;
3837 },
3838 "mz_now" => Scalar {
3839 params!() => UnmaterializableFunc::MzNow => MzTimestamp, oid::FUNC_MZ_NOW_OID;
3840 },
3841 "mz_uptime" => Scalar {
3842 params!() => UnmaterializableFunc::MzUptime => Interval, oid::FUNC_MZ_UPTIME_OID;
3843 },
3844 "mz_version" => Scalar {
3845 params!() => UnmaterializableFunc::MzVersion => String, oid::FUNC_MZ_VERSION_OID;
3846 },
3847 "mz_version_num" => Scalar {
3848 params!() => UnmaterializableFunc::MzVersionNum => Int32, oid::FUNC_MZ_VERSION_NUM_OID;
3849 },
3850 "pretty_sql" => Scalar {
3851 params!(String, Int32) => BinaryFunc::PrettySql => String, oid::FUNC_PRETTY_SQL;
3852 params!(String) => Operation::unary(|_ecx, s| {
3853 let width = HirScalarExpr::literal(Datum::Int32(mz_sql_pretty::DEFAULT_WIDTH.try_into().expect("must fit")), ScalarType::Int32);
3854 Ok(s.call_binary(width, BinaryFunc::PrettySql))
3855 }) => String, oid::FUNC_PRETTY_SQL_NOWIDTH;
3856 },
3857 "regexp_extract" => Table {
3858 params!(String, String) => Operation::binary(move |_ecx, regex, haystack| {
3859 let regex = match regex.into_literal_string() {
3860 None => sql_bail!("regexp_extract requires a string literal as its first argument"),
3861 Some(regex) => mz_expr::AnalyzedRegex::new(®ex, mz_expr::AnalyzedRegexOpts::default()).map_err(|e| sql_err!("analyzing regex: {}", e))?,
3862 };
3863 let column_names = regex
3864 .capture_groups_iter()
3865 .map(|cg| {
3866 cg.name.clone().unwrap_or_else(|| format!("column{}", cg.index)).into()
3867 })
3868 .collect::<Vec<_>>();
3869 if column_names.is_empty(){
3870 sql_bail!("regexp_extract must specify at least one capture group");
3871 }
3872 Ok(TableFuncPlan {
3873 imp: TableFuncImpl::CallTable {
3874 func: TableFunc::RegexpExtract(regex),
3875 exprs: vec![haystack],
3876 },
3877 column_names,
3878 })
3879 }) => ReturnType::set_of(RecordAny), oid::FUNC_REGEXP_EXTRACT_OID;
3880 },
3881 "repeat_row" => Table {
3882 params!(Int64) => Operation::unary(move |ecx, n| {
3883 ecx.require_feature_flag(&crate::session::vars::ENABLE_REPEAT_ROW)?;
3884 Ok(TableFuncPlan {
3885 imp: TableFuncImpl::CallTable {
3886 func: TableFunc::Repeat,
3887 exprs: vec![n],
3888 },
3889 column_names: vec![]
3890 })
3891 }) => ReturnType::none(true), oid::FUNC_REPEAT_OID;
3892 },
3893 "seahash" => Scalar {
3894 params!(String) => UnaryFunc::SeahashString(func::SeahashString) => UInt32, oid::FUNC_SEAHASH_STRING_OID;
3895 params!(Bytes) => UnaryFunc::SeahashBytes(func::SeahashBytes) => UInt32, oid::FUNC_SEAHASH_BYTES_OID;
3896 },
3897 "starts_with" => Scalar {
3898 params!(String, String) => BinaryFunc::StartsWith => Bool, 3696;
3899 },
3900 "timezone_offset" => Scalar {
3901 params!(String, TimestampTz) => BinaryFunc::TimezoneOffset => RecordAny, oid::FUNC_TIMEZONE_OFFSET;
3902 },
3903 "try_parse_monotonic_iso8601_timestamp" => Scalar {
3904 params!(String) => Operation::unary(move |_ecx, e| {
3905 Ok(e.call_unary(UnaryFunc::TryParseMonotonicIso8601Timestamp(func::TryParseMonotonicIso8601Timestamp)))
3906 }) => Timestamp, oid::FUNC_TRY_PARSE_MONOTONIC_ISO8601_TIMESTAMP;
3907 },
3908 "unnest" => Table {
3909 vec![ArrayAny] => Operation::unary(move |ecx, e| {
3910 let el_typ = ecx.scalar_type(&e).unwrap_array_element_type().clone();
3911 Ok(TableFuncPlan {
3912 imp: TableFuncImpl::CallTable {
3913 func: TableFunc::UnnestArray { el_typ },
3914 exprs: vec![e],
3915 },
3916 column_names: vec!["unnest".into()],
3917 })
3918 }) =>
3919 ReturnType::set_of(AnyElement), 2331;
3921 vec![ListAny] => Operation::unary(move |ecx, e| {
3922 let el_typ = ecx.scalar_type(&e).unwrap_list_element_type().clone();
3923 Ok(TableFuncPlan {
3924 imp: TableFuncImpl::CallTable {
3925 func: TableFunc::UnnestList { el_typ },
3926 exprs: vec![e],
3927 },
3928 column_names: vec!["unnest".into()],
3929 })
3930 }) =>
3931 ReturnType::set_of(Any), oid::FUNC_UNNEST_LIST_OID;
3933 vec![MapAny] => Operation::unary(move |ecx, e| {
3934 let value_type = ecx.scalar_type(&e).unwrap_map_value_type().clone();
3935 Ok(TableFuncPlan {
3936 imp: TableFuncImpl::CallTable {
3937 func: TableFunc::UnnestMap { value_type },
3938 exprs: vec![e],
3939 },
3940 column_names: vec!["key".into(), "value".into()],
3941 })
3942 }) =>
3943 ReturnType::set_of(Any), oid::FUNC_UNNEST_MAP_OID;
3945 }
3946 }
3947});
3948
3949pub static MZ_INTERNAL_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
3950 use ParamType::*;
3951 use ScalarBaseType::*;
3952 builtins! {
3953 "aclitem_grantor" => Scalar {
3954 params!(AclItem) => UnaryFunc::AclItemGrantor(func::AclItemGrantor) => Oid, oid::FUNC_ACL_ITEM_GRANTOR_OID;
3955 },
3956 "aclitem_grantee" => Scalar {
3957 params!(AclItem) => UnaryFunc::AclItemGrantee(func::AclItemGrantee) => Oid, oid::FUNC_ACL_ITEM_GRANTEE_OID;
3958 },
3959 "aclitem_privileges" => Scalar {
3960 params!(AclItem) => UnaryFunc::AclItemPrivileges(func::AclItemPrivileges) => String, oid::FUNC_ACL_ITEM_PRIVILEGES_OID;
3961 },
3962 "is_rbac_enabled" => Scalar {
3963 params!() => UnmaterializableFunc::IsRbacEnabled => Bool, oid::FUNC_IS_RBAC_ENABLED_OID;
3964 },
3965 "make_mz_aclitem" => Scalar {
3966 params!(String, String, String) => VariadicFunc::MakeMzAclItem => MzAclItem, oid::FUNC_MAKE_MZ_ACL_ITEM_OID;
3967 },
3968 "mz_acl_item_contains_privilege" => Scalar {
3969 params!(MzAclItem, String) => BinaryFunc::MzAclItemContainsPrivilege => Bool, oid::FUNC_MZ_ACL_ITEM_CONTAINS_PRIVILEGE_OID;
3970 },
3971 "mz_aclexplode" => Table {
3972 params!(ScalarType::Array(Box::new(ScalarType::MzAclItem))) => Operation::unary(move |_ecx, mz_aclitems| {
3973 Ok(TableFuncPlan {
3974 imp: TableFuncImpl::CallTable {
3975 func: TableFunc::MzAclExplode,
3976 exprs: vec![mz_aclitems],
3977 },
3978 column_names: vec!["grantor".into(), "grantee".into(), "privilege_type".into(), "is_grantable".into()],
3979 })
3980 }) => ReturnType::set_of(RecordAny), oid::FUNC_MZ_ACL_ITEM_EXPLODE_OID;
3981 },
3982 "mz_aclitem_grantor" => Scalar {
3983 params!(MzAclItem) => UnaryFunc::MzAclItemGrantor(func::MzAclItemGrantor) => String, oid::FUNC_MZ_ACL_ITEM_GRANTOR_OID;
3984 },
3985 "mz_aclitem_grantee" => Scalar {
3986 params!(MzAclItem) => UnaryFunc::MzAclItemGrantee(func::MzAclItemGrantee) => String, oid::FUNC_MZ_ACL_ITEM_GRANTEE_OID;
3987 },
3988 "mz_aclitem_privileges" => Scalar {
3989 params!(MzAclItem) => UnaryFunc::MzAclItemPrivileges(func::MzAclItemPrivileges) => String, oid::FUNC_MZ_ACL_ITEM_PRIVILEGES_OID;
3990 },
3991 "mz_connection_oid" => Scalar {
3996 params!(String) => sql_impl_func("
3997 CASE
3998 WHEN $1 IS NULL THEN NULL
3999 ELSE (
4000 mz_unsafe.mz_error_if_null(
4001 (SELECT oid FROM mz_catalog.mz_objects WHERE name = $1 AND type = 'connection'),
4002 'connection \"' || $1 || '\" does not exist'
4003 )
4004 )
4005 END
4006 ") => Oid, oid::FUNC_CONNECTION_OID_OID;
4007 },
4008 "mz_format_privileges" => Scalar {
4009 params!(String) => UnaryFunc::MzFormatPrivileges(func::MzFormatPrivileges) => ScalarType::Array(Box::new(ScalarType::String)), oid::FUNC_MZ_FORMAT_PRIVILEGES_OID;
4010 },
4011 "mz_name_rank" => Table {
4012 params!(
4015 String,
4017 ParamType::Plain(ScalarType::Array(Box::new(ScalarType::String))),
4019 String,
4021 String
4023 ) =>
4024 sql_impl_table_func("
4026 -- The best ranked name is the one that belongs to the schema correlated with the lowest
4027 -- index in the search path
4028 SELECT id, name, count, min(schema_pref) OVER () = schema_pref AS best_ranked FROM (
4029 SELECT DISTINCT
4030 o.id,
4031 ARRAY[CASE WHEN s.database_id IS NULL THEN NULL ELSE d.name END, s.name, o.name]
4032 AS name,
4033 o.count,
4034 pg_catalog.array_position($2, s.name) AS schema_pref
4035 FROM
4036 (
4037 SELECT
4038 o.id,
4039 o.schema_id,
4040 o.name,
4041 count(*)
4042 FROM mz_catalog.mz_objects AS o
4043 JOIN mz_internal.mz_object_oid_alias AS a
4044 ON o.type = a.object_type
4045 WHERE o.name = CAST($3 AS pg_catalog.text) AND a.oid_alias = $4
4046 GROUP BY 1, 2, 3
4047 )
4048 AS o
4049 JOIN mz_catalog.mz_schemas AS s ON o.schema_id = s.id
4050 JOIN
4051 unnest($2) AS search_schema (name)
4052 ON search_schema.name = s.name
4053 JOIN
4054 (
4055 SELECT id, name FROM mz_catalog.mz_databases
4056 -- If the provided database does not exist, add a row for it so that it
4057 -- can still join against ambient schemas.
4058 UNION ALL
4059 SELECT '', $1 WHERE $1 NOT IN (SELECT name FROM mz_catalog.mz_databases)
4060 ) AS d
4061 ON d.id = COALESCE(s.database_id, d.id)
4062 WHERE d.name = CAST($1 AS pg_catalog.text)
4063 );
4064 ") => ReturnType::set_of(RecordAny), oid::FUNC_MZ_NAME_RANK;
4065 },
4066 "mz_resolve_object_name" => Table {
4067 params!(String, String) =>
4068 sql_impl_table_func("
4071 SELECT
4072 o.id, o.oid, o.schema_id, o.name, o.type, o.owner_id, o.privileges
4073 FROM
4074 (SELECT mz_internal.mz_normalize_object_name($2))
4075 AS normalized (n),
4076 mz_internal.mz_name_rank(
4077 COALESCE(n[1], pg_catalog.current_database()),
4078 CASE
4079 WHEN n[2] IS NULL
4080 THEN pg_catalog.current_schemas(true)
4081 ELSE
4082 ARRAY[n[2]]
4083 END,
4084 n[3],
4085 $1
4086 ) AS r,
4087 mz_catalog.mz_objects AS o
4088 WHERE r.id = o.id AND r.best_ranked;
4089 ") => ReturnType::set_of(RecordAny), oid::FUNC_MZ_RESOLVE_OBJECT_NAME;
4090 },
4091 "mz_minimal_name_qualification" => Scalar {
4103 params!(ScalarType::Array(Box::new(ScalarType::String)), String) => {
4104 sql_impl_func("(
4105 SELECT
4106 CASE
4107 WHEN $1::pg_catalog.text[] IS NULL
4108 THEN NULL
4109 -- If DB doesn't match, requires full qual
4110 WHEN $1[1] != pg_catalog.current_database()
4111 THEN $1
4112 -- If not in currently searchable schema, must be schema qualified
4113 WHEN NOT $1[2] = ANY(pg_catalog.current_schemas(true))
4114 THEN ARRAY[$1[2], $1[3]]
4115 ELSE
4116 minimal_name
4117 END
4118 FROM (
4119 -- Subquery so we return one null row in the cases where
4120 -- there are no matches.
4121 SELECT (
4122 SELECT DISTINCT
4123 CASE
4124 -- If there is only one item with this name and it's rank 1,
4125 -- it is uniquely nameable with just the final element
4126 WHEN best_ranked AND count = 1
4127 THEN ARRAY[r.name[3]]
4128 -- Otherwise, it is findable in the search path, so does not
4129 -- need database qualification
4130 ELSE
4131 ARRAY[r.name[2], r.name[3]]
4132 END AS minimal_name
4133 FROM mz_catalog.mz_objects AS o
4134 JOIN mz_internal.mz_object_oid_alias AS a
4135 ON o.type = a.object_type,
4136 -- implied lateral to put the OID alias into scope
4137 mz_internal.mz_name_rank(
4138 pg_catalog.current_database(),
4139 pg_catalog.current_schemas(true),
4140 $1[3],
4141 a.oid_alias
4142 ) AS r
4143 WHERE o.id = $2 AND r.id = $2
4144 )
4145 )
4146 )")
4147 } => ScalarType::Array(Box::new(ScalarType::String)), oid::FUNC_MZ_MINIMINAL_NAME_QUALIFICATION;
4148 },
4149 "mz_global_id_to_name" => Scalar {
4150 params!(String) => sql_impl_func("
4151 CASE
4152 WHEN $1 IS NULL THEN NULL
4153 ELSE (
4154 SELECT array_to_string(minimal_name, '.')
4155 FROM (
4156 SELECT mz_unsafe.mz_error_if_null(
4157 (
4158 -- Return the fully-qualified name
4159 SELECT DISTINCT ARRAY[qual.d, qual.s, item.name]
4160 FROM
4161 mz_catalog.mz_objects AS item
4162 JOIN
4163 (
4164 SELECT
4165 d.name AS d,
4166 s.name AS s,
4167 s.id AS schema_id
4168 FROM
4169 mz_catalog.mz_schemas AS s
4170 LEFT JOIN
4171 (SELECT id, name FROM mz_catalog.mz_databases)
4172 AS d
4173 ON s.database_id = d.id
4174 ) AS qual
4175 ON qual.schema_id = item.schema_id
4176 WHERE item.id = CAST($1 AS text)
4177 ),
4178 'global ID ' || $1 || ' does not exist'
4179 )
4180 ) AS n (fqn),
4181 LATERAL (
4182 -- Get the minimal qualification of the fully qualified name
4183 SELECT mz_internal.mz_minimal_name_qualification(fqn, $1)
4184 ) AS m (minimal_name)
4185 )
4186 END
4187 ") => String, oid::FUNC_MZ_GLOBAL_ID_TO_NAME;
4188 },
4189 "mz_normalize_object_name" => Scalar {
4190 params!(String) => sql_impl_func("
4191 (
4192 SELECT
4193 CASE
4194 WHEN $1 IS NULL THEN NULL
4195 WHEN pg_catalog.array_length(ident, 1) > 3
4196 THEN mz_unsafe.mz_error_if_null(
4197 NULL::pg_catalog.text[],
4198 'improper relation name (too many dotted names): ' || $1
4199 )
4200 ELSE pg_catalog.array_cat(
4201 pg_catalog.array_fill(
4202 CAST(NULL AS pg_catalog.text),
4203 ARRAY[3 - pg_catalog.array_length(ident, 1)]
4204 ),
4205 ident
4206 )
4207 END
4208 FROM (
4209 SELECT pg_catalog.parse_ident($1) AS ident
4210 ) AS i
4211 )") => ScalarType::Array(Box::new(ScalarType::String)), oid::FUNC_MZ_NORMALIZE_OBJECT_NAME;
4212 },
4213 "mz_normalize_schema_name" => Scalar {
4214 params!(String) => sql_impl_func("
4215 (
4216 SELECT
4217 CASE
4218 WHEN $1 IS NULL THEN NULL
4219 WHEN pg_catalog.array_length(ident, 1) > 2
4220 THEN mz_unsafe.mz_error_if_null(
4221 NULL::pg_catalog.text[],
4222 'improper schema name (too many dotted names): ' || $1
4223 )
4224 ELSE pg_catalog.array_cat(
4225 pg_catalog.array_fill(
4226 CAST(NULL AS pg_catalog.text),
4227 ARRAY[2 - pg_catalog.array_length(ident, 1)]
4228 ),
4229 ident
4230 )
4231 END
4232 FROM (
4233 SELECT pg_catalog.parse_ident($1) AS ident
4234 ) AS i
4235 )") => ScalarType::Array(Box::new(ScalarType::String)), oid::FUNC_MZ_NORMALIZE_SCHEMA_NAME;
4236 },
4237 "mz_render_typmod" => Scalar {
4238 params!(Oid, Int32) => BinaryFunc::MzRenderTypmod => String, oid::FUNC_MZ_RENDER_TYPMOD_OID;
4239 },
4240 "mz_role_oid_memberships" => Scalar {
4241 params!() => UnmaterializableFunc::MzRoleOidMemberships => ScalarType::Map{ value_type: Box::new(ScalarType::Array(Box::new(ScalarType::String))), custom_id: None }, oid::FUNC_MZ_ROLE_OID_MEMBERSHIPS;
4242 },
4243 "mz_database_oid" => Scalar {
4245 params!(String) => sql_impl_func("
4246 CASE
4247 WHEN $1 IS NULL THEN NULL
4248 ELSE (
4249 mz_unsafe.mz_error_if_null(
4250 (SELECT oid FROM mz_databases WHERE name = $1),
4251 'database \"' || $1 || '\" does not exist'
4252 )
4253 )
4254 END
4255 ") => Oid, oid::FUNC_DATABASE_OID_OID;
4256 },
4257 "mz_schema_oid" => Scalar {
4259 params!(String) => sql_impl_func("
4260 CASE
4261 WHEN $1 IS NULL THEN NULL
4262 ELSE
4263 mz_unsafe.mz_error_if_null(
4264 (
4265 SELECT
4266 (
4267 SELECT s.oid
4268 FROM mz_catalog.mz_schemas AS s
4269 LEFT JOIN mz_databases AS d ON s.database_id = d.id
4270 WHERE
4271 (
4272 -- Filter to only schemas in the named database or the
4273 -- current database if no database was specified.
4274 d.name = COALESCE(n[1], pg_catalog.current_database())
4275 -- Always include all ambient schemas.
4276 OR s.database_id IS NULL
4277 )
4278 AND s.name = n[2]
4279 )
4280 FROM mz_internal.mz_normalize_schema_name($1) AS n
4281 ),
4282 'schema \"' || $1 || '\" does not exist'
4283 )
4284 END
4285 ") => Oid, oid::FUNC_SCHEMA_OID_OID;
4286 },
4287 "mz_role_oid" => Scalar {
4289 params!(String) => sql_impl_func("
4290 CASE
4291 WHEN $1 IS NULL THEN NULL
4292 ELSE (
4293 mz_unsafe.mz_error_if_null(
4294 (SELECT oid FROM mz_catalog.mz_roles WHERE name = $1),
4295 'role \"' || $1 || '\" does not exist'
4296 )
4297 )
4298 END
4299 ") => Oid, oid::FUNC_ROLE_OID_OID;
4300 },
4301 "mz_secret_oid" => Scalar {
4306 params!(String) => sql_impl_func("
4307 CASE
4308 WHEN $1 IS NULL THEN NULL
4309 ELSE (
4310 mz_unsafe.mz_error_if_null(
4311 (SELECT oid FROM mz_catalog.mz_objects WHERE name = $1 AND type = 'secret'),
4312 'secret \"' || $1 || '\" does not exist'
4313 )
4314 )
4315 END
4316 ") => Oid, oid::FUNC_SECRET_OID_OID;
4317 },
4318 "mz_session_id" => Scalar {
4322 params!() => UnmaterializableFunc::MzSessionId => Uuid, oid::FUNC_MZ_SESSION_ID_OID;
4323 },
4324 "mz_type_name" => Scalar {
4325 params!(Oid) => UnaryFunc::MzTypeName(func::MzTypeName) => String, oid::FUNC_MZ_TYPE_NAME;
4326 },
4327 "mz_validate_privileges" => Scalar {
4328 params!(String) => UnaryFunc::MzValidatePrivileges(func::MzValidatePrivileges) => Bool, oid::FUNC_MZ_VALIDATE_PRIVILEGES_OID;
4329 },
4330 "mz_validate_role_privilege" => Scalar {
4331 params!(String) => UnaryFunc::MzValidateRolePrivilege(func::MzValidateRolePrivilege) => Bool, oid::FUNC_MZ_VALIDATE_ROLE_PRIVILEGE_OID;
4332 }
4333 }
4334});
4335
4336pub static MZ_UNSAFE_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
4337 use ParamType::*;
4338 use ScalarBaseType::*;
4339 builtins! {
4340 "mz_all" => Aggregate {
4341 params!(Any) => AggregateFunc::All => Bool, oid::FUNC_MZ_ALL_OID;
4342 },
4343 "mz_any" => Aggregate {
4344 params!(Any) => AggregateFunc::Any => Bool, oid::FUNC_MZ_ANY_OID;
4345 },
4346 "mz_avg_promotion_internal_v1" => Scalar {
4347 params!(Float32) => Operation::identity() => Float32, oid::FUNC_MZ_AVG_PROMOTION_F32_OID_INTERNAL_V1;
4353 params!(Float64) => Operation::identity() => Float64, oid::FUNC_MZ_AVG_PROMOTION_F64_OID_INTERNAL_V1;
4354 params!(Int16) => Operation::unary(|ecx, e| {
4355 typeconv::plan_cast(
4356 ecx, CastContext::Explicit, e, &ScalarType::Numeric {max_scale: None},
4357 )
4358 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I16_OID_INTERNAL_V1;
4359 params!(Int32) => Operation::unary(|ecx, e| {
4360 typeconv::plan_cast(
4361 ecx, CastContext::Explicit, e, &ScalarType::Numeric {max_scale: None},
4362 )
4363 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I32_OID_INTERNAL_V1;
4364 params!(UInt16) => Operation::unary(|ecx, e| {
4365 typeconv::plan_cast(
4366 ecx, CastContext::Explicit, e, &ScalarType::Numeric {max_scale: None},
4367 )
4368 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U16_OID_INTERNAL_V1;
4369 params!(UInt32) => Operation::unary(|ecx, e| {
4370 typeconv::plan_cast(
4371 ecx, CastContext::Explicit, e, &ScalarType::Numeric {max_scale: None},
4372 )
4373 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U32_OID_INTERNAL_V1;
4374 },
4375 "mz_avg_promotion" => Scalar {
4376 params!(Float32) => Operation::identity() => Float32, oid::FUNC_MZ_AVG_PROMOTION_F32_OID;
4382 params!(Float64) => Operation::identity() => Float64, oid::FUNC_MZ_AVG_PROMOTION_F64_OID;
4383 params!(Int16) => Operation::unary(|ecx, e| {
4384 typeconv::plan_cast(
4385 ecx, CastContext::Explicit, e, &ScalarType::Numeric {max_scale: None},
4386 )
4387 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I16_OID;
4388 params!(Int32) => Operation::unary(|ecx, e| {
4389 typeconv::plan_cast(
4390 ecx, CastContext::Explicit, e, &ScalarType::Numeric {max_scale: None},
4391 )
4392 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I32_OID;
4393 params!(Int64) => Operation::unary(|ecx, e| {
4394 typeconv::plan_cast(
4395 ecx, CastContext::Explicit, e, &ScalarType::Numeric {max_scale: None},
4396 )
4397 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_I64_OID;
4398 params!(UInt16) => Operation::unary(|ecx, e| {
4399 typeconv::plan_cast(
4400 ecx, CastContext::Explicit, e, &ScalarType::Numeric {max_scale: None},
4401 )
4402 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U16_OID;
4403 params!(UInt32) => Operation::unary(|ecx, e| {
4404 typeconv::plan_cast(
4405 ecx, CastContext::Explicit, e, &ScalarType::Numeric {max_scale: None},
4406 )
4407 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U32_OID;
4408 params!(UInt64) => Operation::unary(|ecx, e| {
4409 typeconv::plan_cast(
4410 ecx, CastContext::Explicit, e, &ScalarType::Numeric {max_scale: None},
4411 )
4412 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_U64_OID;
4413 params!(Numeric) => Operation::unary(|ecx, e| {
4414 typeconv::plan_cast(
4415 ecx, CastContext::Explicit, e, &ScalarType::Numeric {max_scale: None},
4416 )
4417 }) => Numeric, oid::FUNC_MZ_AVG_PROMOTION_NUMERIC_OID;
4418 },
4419 "mz_error_if_null" => Scalar {
4420 params!(Any, String) => VariadicFunc::ErrorIfNull => Any, oid::FUNC_MZ_ERROR_IF_NULL_OID;
4423 },
4424 "mz_sleep" => Scalar {
4425 params!(Float64) => UnaryFunc::Sleep(func::Sleep) => TimestampTz, oid::FUNC_MZ_SLEEP_OID;
4426 },
4427 "mz_panic" => Scalar {
4428 params!(String) => UnaryFunc::Panic(func::Panic) => String, oid::FUNC_MZ_PANIC_OID;
4429 }
4430 }
4431});
4432
4433fn digest(algorithm: &'static str) -> Operation<HirScalarExpr> {
4434 Operation::unary(move |_ecx, input| {
4435 let algorithm = HirScalarExpr::literal(Datum::String(algorithm), ScalarType::String);
4436 Ok(input.call_binary(algorithm, BinaryFunc::DigestBytes))
4437 })
4438}
4439
4440fn array_to_string(
4441 ecx: &ExprContext,
4442 exprs: Vec<HirScalarExpr>,
4443) -> Result<HirScalarExpr, PlanError> {
4444 let elem_type = match ecx.scalar_type(&exprs[0]) {
4445 ScalarType::Array(elem_type) => *elem_type,
4446 _ => unreachable!("array_to_string is guaranteed to receive array as first argument"),
4447 };
4448 Ok(HirScalarExpr::call_variadic(
4449 VariadicFunc::ArrayToString { elem_type },
4450 exprs,
4451 ))
4452}
4453
4454pub static OP_IMPLS: LazyLock<BTreeMap<&'static str, Func>> = LazyLock::new(|| {
4456 use BinaryFunc::*;
4457 use ParamType::*;
4458 use ScalarBaseType::*;
4459 builtins! {
4460 "+" => Scalar {
4483 params!(Any) => Operation::new(|ecx, exprs, _params, _order_by| {
4484 typeconv::plan_coerce(ecx, exprs.into_element(), &ScalarType::Float64)
4497 }) => Any, oid::OP_UNARY_PLUS_OID;
4498 params!(Int16, Int16) => AddInt16 => Int16, 550;
4499 params!(Int32, Int32) => AddInt32 => Int32, 551;
4500 params!(Int64, Int64) => AddInt64 => Int64, 684;
4501 params!(UInt16, UInt16) => AddUInt16 => UInt16, oid::FUNC_ADD_UINT16;
4502 params!(UInt32, UInt32) => AddUInt32 => UInt32, oid::FUNC_ADD_UINT32;
4503 params!(UInt64, UInt64) => AddUInt64 => UInt64, oid::FUNC_ADD_UINT64;
4504 params!(Float32, Float32) => AddFloat32 => Float32, 586;
4505 params!(Float64, Float64) => AddFloat64 => Float64, 591;
4506 params!(Interval, Interval) => AddInterval => Interval, 1337;
4507 params!(Timestamp, Interval) => AddTimestampInterval => Timestamp, 2066;
4508 params!(Interval, Timestamp) => {
4509 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, AddTimestampInterval)))
4510 } => Timestamp, 2553;
4511 params!(TimestampTz, Interval) => AddTimestampTzInterval => TimestampTz, 1327;
4512 params!(Interval, TimestampTz) => {
4513 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, AddTimestampTzInterval)))
4514 } => TimestampTz, 2554;
4515 params!(Date, Interval) => AddDateInterval => Timestamp, 1076;
4516 params!(Interval, Date) => {
4517 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, AddDateInterval)))
4518 } => Timestamp, 2551;
4519 params!(Date, Time) => AddDateTime => Timestamp, 1360;
4520 params!(Time, Date) => {
4521 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, AddDateTime)))
4522 } => Timestamp, 1363;
4523 params!(Time, Interval) => AddTimeInterval => Time, 1800;
4524 params!(Interval, Time) => {
4525 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, AddTimeInterval)))
4526 } => Time, 1849;
4527 params!(Numeric, Numeric) => AddNumeric => Numeric, 1758;
4528 params!(RangeAny, RangeAny) => RangeUnion => RangeAny, 3898;
4529 },
4530 "-" => Scalar {
4531 params!(Int16) => UnaryFunc::NegInt16(func::NegInt16) => Int16, 559;
4532 params!(Int32) => UnaryFunc::NegInt32(func::NegInt32) => Int32, 558;
4533 params!(Int64) => UnaryFunc::NegInt64(func::NegInt64) => Int64, 484;
4534 params!(Float32) => UnaryFunc::NegFloat32(func::NegFloat32) => Float32, 584;
4535 params!(Float64) => UnaryFunc::NegFloat64(func::NegFloat64) => Float64, 585;
4536 params!(Numeric) => UnaryFunc::NegNumeric(func::NegNumeric) => Numeric, 17510;
4537 params!(Interval) => UnaryFunc::NegInterval(func::NegInterval) => Interval, 1336;
4538 params!(Int32, Int32) => SubInt32 => Int32, 555;
4539 params!(Int64, Int64) => SubInt64 => Int64, 685;
4540 params!(UInt16, UInt16) => SubUInt16 => UInt16, oid::FUNC_SUB_UINT16;
4541 params!(UInt32, UInt32) => SubUInt32 => UInt32, oid::FUNC_SUB_UINT32;
4542 params!(UInt64, UInt64) => SubUInt64 => UInt64, oid::FUNC_SUB_UINT64;
4543 params!(Float32, Float32) => SubFloat32 => Float32, 587;
4544 params!(Float64, Float64) => SubFloat64 => Float64, 592;
4545 params!(Numeric, Numeric) => SubNumeric => Numeric, 17590;
4546 params!(Interval, Interval) => SubInterval => Interval, 1338;
4547 params!(Timestamp, Timestamp) => SubTimestamp => Interval, 2067;
4548 params!(TimestampTz, TimestampTz) => SubTimestampTz => Interval, 1328;
4549 params!(Timestamp, Interval) => SubTimestampInterval => Timestamp, 2068;
4550 params!(TimestampTz, Interval) => SubTimestampTzInterval => TimestampTz, 1329;
4551 params!(Date, Date) => SubDate => Int32, 1099;
4552 params!(Date, Interval) => SubDateInterval => Timestamp, 1077;
4553 params!(Time, Time) => SubTime => Interval, 1399;
4554 params!(Time, Interval) => SubTimeInterval => Time, 1801;
4555 params!(Jsonb, Int64) => JsonbDeleteInt64 => Jsonb, 3286;
4556 params!(Jsonb, String) => JsonbDeleteString => Jsonb, 3285;
4557 params!(RangeAny, RangeAny) => RangeDifference => RangeAny, 3899;
4558 },
4561 "*" => Scalar {
4562 params!(Int16, Int16) => MulInt16 => Int16, 526;
4563 params!(Int32, Int32) => MulInt32 => Int32, 514;
4564 params!(Int64, Int64) => MulInt64 => Int64, 686;
4565 params!(UInt16, UInt16) => MulUInt16 => UInt16, oid::FUNC_MUL_UINT16;
4566 params!(UInt32, UInt32) => MulUInt32 => UInt32, oid::FUNC_MUL_UINT32;
4567 params!(UInt64, UInt64) => MulUInt64 => UInt64, oid::FUNC_MUL_UINT64;
4568 params!(Float32, Float32) => MulFloat32 => Float32, 589;
4569 params!(Float64, Float64) => MulFloat64 => Float64, 594;
4570 params!(Interval, Float64) => MulInterval => Interval, 1583;
4571 params!(Float64, Interval) => {
4572 Operation::binary(|_ecx, lhs, rhs| Ok(rhs.call_binary(lhs, MulInterval)))
4573 } => Interval, 1584;
4574 params!(Numeric, Numeric) => MulNumeric => Numeric, 1760;
4575 params!(RangeAny, RangeAny) => RangeIntersection => RangeAny, 3900;
4576 },
4577 "/" => Scalar {
4578 params!(Int16, Int16) => DivInt16 => Int16, 527;
4579 params!(Int32, Int32) => DivInt32 => Int32, 528;
4580 params!(Int64, Int64) => DivInt64 => Int64, 687;
4581 params!(UInt16, UInt16) => DivUInt16 => UInt16, oid::FUNC_DIV_UINT16;
4582 params!(UInt32, UInt32) => DivUInt32 => UInt32, oid::FUNC_DIV_UINT32;
4583 params!(UInt64, UInt64) => DivUInt64 => UInt64, oid::FUNC_DIV_UINT64;
4584 params!(Float32, Float32) => DivFloat32 => Float32, 588;
4585 params!(Float64, Float64) => DivFloat64 => Float64, 593;
4586 params!(Interval, Float64) => DivInterval => Interval, 1585;
4587 params!(Numeric, Numeric) => DivNumeric => Numeric, 1761;
4588 },
4589 "%" => Scalar {
4590 params!(Int16, Int16) => ModInt16 => Int16, 529;
4591 params!(Int32, Int32) => ModInt32 => Int32, 530;
4592 params!(Int64, Int64) => ModInt64 => Int64, 439;
4593 params!(UInt16, UInt16) => ModUInt16 => UInt16, oid::FUNC_MOD_UINT16;
4594 params!(UInt32, UInt32) => ModUInt32 => UInt32, oid::FUNC_MOD_UINT32;
4595 params!(UInt64, UInt64) => ModUInt64 => UInt64, oid::FUNC_MOD_UINT64;
4596 params!(Float32, Float32) => ModFloat32 => Float32, oid::OP_MOD_F32_OID;
4597 params!(Float64, Float64) => ModFloat64 => Float64, oid::OP_MOD_F64_OID;
4598 params!(Numeric, Numeric) => ModNumeric => Numeric, 1762;
4599 },
4600 "&" => Scalar {
4601 params!(Int16, Int16) => BitAndInt16 => Int16, 1874;
4602 params!(Int32, Int32) => BitAndInt32 => Int32, 1880;
4603 params!(Int64, Int64) => BitAndInt64 => Int64, 1886;
4604 params!(UInt16, UInt16) => BitAndUInt16 => UInt16, oid::FUNC_AND_UINT16;
4605 params!(UInt32, UInt32) => BitAndUInt32 => UInt32, oid::FUNC_AND_UINT32;
4606 params!(UInt64, UInt64) => BitAndUInt64 => UInt64, oid::FUNC_AND_UINT64;
4607 },
4608 "|" => Scalar {
4609 params!(Int16, Int16) => BitOrInt16 => Int16, 1875;
4610 params!(Int32, Int32) => BitOrInt32 => Int32, 1881;
4611 params!(Int64, Int64) => BitOrInt64 => Int64, 1887;
4612 params!(UInt16, UInt16) => BitOrUInt16 => UInt16, oid::FUNC_OR_UINT16;
4613 params!(UInt32, UInt32) => BitOrUInt32 => UInt32, oid::FUNC_OR_UINT32;
4614 params!(UInt64, UInt64) => BitOrUInt64 => UInt64, oid::FUNC_OR_UINT64;
4615 },
4616 "#" => Scalar {
4617 params!(Int16, Int16) => BitXorInt16 => Int16, 1876;
4618 params!(Int32, Int32) => BitXorInt32 => Int32, 1882;
4619 params!(Int64, Int64) => BitXorInt64 => Int64, 1888;
4620 params!(UInt16, UInt16) => BitXorUInt16 => UInt16, oid::FUNC_XOR_UINT16;
4621 params!(UInt32, UInt32) => BitXorUInt32 => UInt32, oid::FUNC_XOR_UINT32;
4622 params!(UInt64, UInt64) => BitXorUInt64 => UInt64, oid::FUNC_XOR_UINT64;
4623 },
4624 "<<" => Scalar {
4625 params!(Int16, Int32) => BitShiftLeftInt16 => Int16, 1878;
4626 params!(Int32, Int32) => BitShiftLeftInt32 => Int32, 1884;
4627 params!(Int64, Int32) => BitShiftLeftInt64 => Int64, 1890;
4628 params!(UInt16, UInt32) => BitShiftLeftUInt16 => UInt16, oid::FUNC_SHIFT_LEFT_UINT16;
4629 params!(UInt32, UInt32) => BitShiftLeftUInt32 => UInt32, oid::FUNC_SHIFT_LEFT_UINT32;
4630 params!(UInt64, UInt32) => BitShiftLeftUInt64 => UInt64, oid::FUNC_SHIFT_LEFT_UINT64;
4631 params!(RangeAny, RangeAny) => RangeBefore => Bool, 3893;
4632 },
4633 ">>" => Scalar {
4634 params!(Int16, Int32) => BitShiftRightInt16 => Int16, 1879;
4635 params!(Int32, Int32) => BitShiftRightInt32 => Int32, 1885;
4636 params!(Int64, Int32) => BitShiftRightInt64 => Int64, 1891;
4637 params!(UInt16, UInt32) => BitShiftRightUInt16 => UInt16, oid::FUNC_SHIFT_RIGHT_UINT16;
4638 params!(UInt32, UInt32) => BitShiftRightUInt32 => UInt32, oid::FUNC_SHIFT_RIGHT_UINT32;
4639 params!(UInt64, UInt32) => BitShiftRightUInt64 => UInt64, oid::FUNC_SHIFT_RIGHT_UINT64;
4640 params!(RangeAny, RangeAny) => RangeAfter => Bool, 3894;
4641 },
4642
4643 "~~*" => Scalar {
4645 params!(String, String) => IsLikeMatch { case_insensitive: true } => Bool, 1627;
4646 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
4647 let length = ecx.scalar_type(&lhs).unwrap_char_length();
4648 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
4649 .call_binary(rhs, IsLikeMatch { case_insensitive: true })
4650 )
4651 }) => Bool, 1629;
4652 },
4653 "!~~*" => Scalar {
4654 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
4655 Ok(lhs
4656 .call_binary(rhs, IsLikeMatch { case_insensitive: true })
4657 .call_unary(UnaryFunc::Not(func::Not)))
4658 }) => Bool, 1628;
4659 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
4660 let length = ecx.scalar_type(&lhs).unwrap_char_length();
4661 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
4662 .call_binary(rhs, IsLikeMatch { case_insensitive: true })
4663 .call_unary(UnaryFunc::Not(func::Not))
4664 )
4665 }) => Bool, 1630;
4666 },
4667
4668
4669 "~~" => Scalar {
4671 params!(String, String) => IsLikeMatch { case_insensitive: false } => Bool, 1209;
4672 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
4673 let length = ecx.scalar_type(&lhs).unwrap_char_length();
4674 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
4675 .call_binary(rhs, IsLikeMatch { case_insensitive: false })
4676 )
4677 }) => Bool, 1211;
4678 },
4679 "!~~" => Scalar {
4680 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
4681 Ok(lhs
4682 .call_binary(rhs, IsLikeMatch { case_insensitive: false })
4683 .call_unary(UnaryFunc::Not(func::Not)))
4684 }) => Bool, 1210;
4685 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
4686 let length = ecx.scalar_type(&lhs).unwrap_char_length();
4687 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
4688 .call_binary(rhs, IsLikeMatch { case_insensitive: false })
4689 .call_unary(UnaryFunc::Not(func::Not))
4690 )
4691 }) => Bool, 1212;
4692 },
4693
4694 "~" => Scalar {
4696 params!(Int16) => UnaryFunc::BitNotInt16(func::BitNotInt16) => Int16, 1877;
4697 params!(Int32) => UnaryFunc::BitNotInt32(func::BitNotInt32) => Int32, 1883;
4698 params!(Int64) => UnaryFunc::BitNotInt64(func::BitNotInt64) => Int64, 1889;
4699 params!(UInt16) => UnaryFunc::BitNotUint16(func::BitNotUint16) => UInt16, oid::FUNC_BIT_NOT_UINT16_OID;
4700 params!(UInt32) => UnaryFunc::BitNotUint32(func::BitNotUint32) => UInt32, oid::FUNC_BIT_NOT_UINT32_OID;
4701 params!(UInt64) => UnaryFunc::BitNotUint64(func::BitNotUint64) => UInt64, oid::FUNC_BIT_NOT_UINT64_OID;
4702 params!(String, String) => IsRegexpMatch { case_insensitive: false } => Bool, 641;
4703 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
4704 let length = ecx.scalar_type(&lhs).unwrap_char_length();
4705 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
4706 .call_binary(rhs, IsRegexpMatch { case_insensitive: false })
4707 )
4708 }) => Bool, 1055;
4709 },
4710 "~*" => Scalar {
4711 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
4712 Ok(lhs.call_binary(rhs, IsRegexpMatch { case_insensitive: true }))
4713 }) => Bool, 1228;
4714 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
4715 let length = ecx.scalar_type(&lhs).unwrap_char_length();
4716 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
4717 .call_binary(rhs, IsRegexpMatch { case_insensitive: true })
4718 )
4719 }) => Bool, 1234;
4720 },
4721 "!~" => Scalar {
4722 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
4723 Ok(lhs
4724 .call_binary(rhs, IsRegexpMatch { case_insensitive: false })
4725 .call_unary(UnaryFunc::Not(func::Not)))
4726 }) => Bool, 642;
4727 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
4728 let length = ecx.scalar_type(&lhs).unwrap_char_length();
4729 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
4730 .call_binary(rhs, IsRegexpMatch { case_insensitive: false })
4731 .call_unary(UnaryFunc::Not(func::Not))
4732 )
4733 }) => Bool, 1056;
4734 },
4735 "!~*" => Scalar {
4736 params!(String, String) => Operation::binary(|_ecx, lhs, rhs| {
4737 Ok(lhs
4738 .call_binary(rhs, IsRegexpMatch { case_insensitive: true })
4739 .call_unary(UnaryFunc::Not(func::Not)))
4740 }) => Bool, 1229;
4741 params!(Char, String) => Operation::binary(|ecx, lhs, rhs| {
4742 let length = ecx.scalar_type(&lhs).unwrap_char_length();
4743 Ok(lhs.call_unary(UnaryFunc::PadChar(func::PadChar { length }))
4744 .call_binary(rhs, IsRegexpMatch { case_insensitive: true })
4745 .call_unary(UnaryFunc::Not(func::Not))
4746 )
4747 }) => Bool, 1235;
4748 },
4749
4750 "||" => Scalar {
4752 params!(String, NonVecAny) => Operation::binary(|ecx, lhs, rhs| {
4753 let rhs = typeconv::plan_cast(
4754 ecx,
4755 CastContext::Explicit,
4756 rhs,
4757 &ScalarType::String,
4758 )?;
4759 Ok(lhs.call_binary(rhs, TextConcat))
4760 }) => String, 2779;
4761 params!(NonVecAny, String) => Operation::binary(|ecx, lhs, rhs| {
4762 let lhs = typeconv::plan_cast(
4763 ecx,
4764 CastContext::Explicit,
4765 lhs,
4766 &ScalarType::String,
4767 )?;
4768 Ok(lhs.call_binary(rhs, TextConcat))
4769 }) => String, 2780;
4770 params!(String, String) => TextConcat => String, 654;
4771 params!(Jsonb, Jsonb) => JsonbConcat => Jsonb, 3284;
4772 params!(ArrayAnyCompatible, ArrayAnyCompatible) => ArrayArrayConcat => ArrayAnyCompatible, 375;
4773 params!(ListAnyCompatible, ListAnyCompatible) => ListListConcat => ListAnyCompatible, oid::OP_CONCAT_LIST_LIST_OID;
4774 params!(ListAnyCompatible, ListElementAnyCompatible) => ListElementConcat => ListAnyCompatible, oid::OP_CONCAT_LIST_ELEMENT_OID;
4775 params!(ListElementAnyCompatible, ListAnyCompatible) => ElementListConcat => ListAnyCompatible, oid::OP_CONCAT_ELEMENY_LIST_OID;
4776 },
4777
4778 "->" => Scalar {
4780 params!(Jsonb, Int64) => JsonbGetInt64 => Jsonb, 3212;
4781 params!(Jsonb, String) => JsonbGetString => Jsonb, 3211;
4782 params!(MapAny, String) => MapGetValue => Any, oid::OP_GET_VALUE_MAP_OID;
4783 },
4784 "->>" => Scalar {
4785 params!(Jsonb, Int64) => JsonbGetInt64Stringify => String, 3481;
4786 params!(Jsonb, String) => JsonbGetStringStringify => String, 3477;
4787 },
4788 "#>" => Scalar {
4789 params!(Jsonb, ScalarType::Array(Box::new(ScalarType::String))) => JsonbGetPath => Jsonb, 3213;
4790 },
4791 "#>>" => Scalar {
4792 params!(Jsonb, ScalarType::Array(Box::new(ScalarType::String))) => JsonbGetPathStringify => String, 3206;
4793 },
4794 "@>" => Scalar {
4795 params!(Jsonb, Jsonb) => JsonbContainsJsonb => Bool, 3246;
4796 params!(Jsonb, String) => Operation::binary(|_ecx, lhs, rhs| {
4797 Ok(lhs.call_binary(
4798 rhs.call_unary(UnaryFunc::CastStringToJsonb(func::CastStringToJsonb)),
4799 JsonbContainsJsonb,
4800 ))
4801 }) => Bool, oid::OP_CONTAINS_JSONB_STRING_OID;
4802 params!(String, Jsonb) => Operation::binary(|_ecx, lhs, rhs| {
4803 Ok(lhs.call_unary(UnaryFunc::CastStringToJsonb(func::CastStringToJsonb))
4804 .call_binary(rhs, JsonbContainsJsonb))
4805 }) => Bool, oid::OP_CONTAINS_STRING_JSONB_OID;
4806 params!(MapAnyCompatible, MapAnyCompatible) => MapContainsMap => Bool, oid::OP_CONTAINS_MAP_MAP_OID;
4807 params!(RangeAny, AnyElement) => Operation::binary(|ecx, lhs, rhs| {
4808 let elem_type = ecx.scalar_type(&lhs).unwrap_range_element_type().clone();
4809 Ok(lhs.call_binary(rhs, BinaryFunc::RangeContainsElem { elem_type, rev: false }))
4810 }) => Bool, 3889;
4811 params!(RangeAny, RangeAny) => Operation::binary(|_ecx, lhs, rhs| {
4812 Ok(lhs.call_binary(rhs, BinaryFunc::RangeContainsRange { rev: false }))
4813 }) => Bool, 3890;
4814 params!(ArrayAny, ArrayAny) => Operation::binary(|_ecx, lhs, rhs| {
4815 Ok(lhs.call_binary(rhs, BinaryFunc::ArrayContainsArray { rev: false }))
4816 }) => Bool, 2751;
4817 params!(ListAny, ListAny) => Operation::binary(|_ecx, lhs, rhs| {
4818 Ok(lhs.call_binary(rhs, BinaryFunc::ListContainsList { rev: false }))
4819 }) => Bool, oid::OP_CONTAINS_LIST_LIST_OID;
4820 },
4821 "<@" => Scalar {
4822 params!(Jsonb, Jsonb) => Operation::binary(|_ecx, lhs, rhs| {
4823 Ok(rhs.call_binary(
4824 lhs,
4825 JsonbContainsJsonb
4826 ))
4827 }) => Bool, 3250;
4828 params!(Jsonb, String) => Operation::binary(|_ecx, lhs, rhs| {
4829 Ok(rhs.call_unary(UnaryFunc::CastStringToJsonb(func::CastStringToJsonb))
4830 .call_binary(lhs, BinaryFunc::JsonbContainsJsonb))
4831 }) => Bool, oid::OP_CONTAINED_JSONB_STRING_OID;
4832 params!(String, Jsonb) => Operation::binary(|_ecx, lhs, rhs| {
4833 Ok(rhs.call_binary(
4834 lhs.call_unary(UnaryFunc::CastStringToJsonb(func::CastStringToJsonb)),
4835 BinaryFunc::JsonbContainsJsonb,
4836 ))
4837 }) => Bool, oid::OP_CONTAINED_STRING_JSONB_OID;
4838 params!(MapAnyCompatible, MapAnyCompatible) => Operation::binary(|_ecx, lhs, rhs| {
4839 Ok(rhs.call_binary(lhs, MapContainsMap))
4840 }) => Bool, oid::OP_CONTAINED_MAP_MAP_OID;
4841 params!(AnyElement, RangeAny) => Operation::binary(|ecx, lhs, rhs| {
4842 let elem_type = ecx.scalar_type(&rhs).unwrap_range_element_type().clone();
4843 Ok(rhs.call_binary(lhs, BinaryFunc::RangeContainsElem { elem_type, rev: true }))
4844 }) => Bool, 3891;
4845 params!(RangeAny, RangeAny) => Operation::binary(|_ecx, lhs, rhs| {
4846 Ok(rhs.call_binary(lhs, BinaryFunc::RangeContainsRange { rev: true }))
4847 }) => Bool, 3892;
4848 params!(ArrayAny, ArrayAny) => Operation::binary(|_ecx, lhs, rhs| {
4849 Ok(lhs.call_binary(rhs, BinaryFunc::ArrayContainsArray { rev: true }))
4850 }) => Bool, 2752;
4851 params!(ListAny, ListAny) => Operation::binary(|_ecx, lhs, rhs| {
4852 Ok(lhs.call_binary(rhs, BinaryFunc::ListContainsList { rev: true }))
4853 }) => Bool, oid::OP_IS_CONTAINED_LIST_LIST_OID;
4854 },
4855 "?" => Scalar {
4856 params!(Jsonb, String) => JsonbContainsString => Bool, 3247;
4857 params!(MapAny, String) => MapContainsKey => Bool, oid::OP_CONTAINS_KEY_MAP_OID;
4858 },
4859 "?&" => Scalar {
4860 params!(MapAny, ScalarType::Array(Box::new(ScalarType::String))) => MapContainsAllKeys => Bool, oid::OP_CONTAINS_ALL_KEYS_MAP_OID;
4861 },
4862 "?|" => Scalar {
4863 params!(MapAny, ScalarType::Array(Box::new(ScalarType::String))) => MapContainsAnyKeys => Bool, oid::OP_CONTAINS_ANY_KEYS_MAP_OID;
4864 },
4865 "&&" => Scalar {
4866 params!(RangeAny, RangeAny) => BinaryFunc::RangeOverlaps => Bool, 3888;
4867 },
4868 "&<" => Scalar {
4869 params!(RangeAny, RangeAny) => BinaryFunc::RangeOverleft => Bool, 3895;
4870 },
4871 "&>" => Scalar {
4872 params!(RangeAny, RangeAny) => BinaryFunc::RangeOverright => Bool, 3896;
4873 },
4874 "-|-" => Scalar {
4875 params!(RangeAny, RangeAny) => BinaryFunc::RangeAdjacent => Bool, 3897;
4876 },
4877
4878 "<" => Scalar {
4880 params!(Numeric, Numeric) => BinaryFunc::Lt => Bool, 1754;
4881 params!(Bool, Bool) => BinaryFunc::Lt => Bool, 58;
4882 params!(Int16, Int16) => BinaryFunc::Lt => Bool, 95;
4883 params!(Int32, Int32) => BinaryFunc::Lt => Bool, 97;
4884 params!(Int64, Int64) => BinaryFunc::Lt => Bool, 412;
4885 params!(UInt16, UInt16) => BinaryFunc::Lt => Bool, oid::FUNC_LT_UINT16_OID;
4886 params!(UInt32, UInt32) => BinaryFunc::Lt => Bool, oid::FUNC_LT_UINT32_OID;
4887 params!(UInt64, UInt64) => BinaryFunc::Lt => Bool, oid::FUNC_LT_UINT64_OID;
4888 params!(Float32, Float32) => BinaryFunc::Lt => Bool, 622;
4889 params!(Float64, Float64) => BinaryFunc::Lt => Bool, 672;
4890 params!(Oid, Oid) => BinaryFunc::Lt => Bool, 609;
4891 params!(Date, Date) => BinaryFunc::Lt => Bool, 1095;
4892 params!(Time, Time) => BinaryFunc::Lt => Bool, 1110;
4893 params!(Timestamp, Timestamp) => BinaryFunc::Lt => Bool, 2062;
4894 params!(TimestampTz, TimestampTz) => BinaryFunc::Lt => Bool, 1322;
4895 params!(Uuid, Uuid) => BinaryFunc::Lt => Bool, 2974;
4896 params!(Interval, Interval) => BinaryFunc::Lt => Bool, 1332;
4897 params!(Bytes, Bytes) => BinaryFunc::Lt => Bool, 1957;
4898 params!(String, String) => BinaryFunc::Lt => Bool, 664;
4899 params!(Char, Char) => BinaryFunc::Lt => Bool, 1058;
4900 params!(PgLegacyChar, PgLegacyChar) => BinaryFunc::Lt => Bool, 631;
4901 params!(PgLegacyName, PgLegacyName) => BinaryFunc::Lt => Bool, 660;
4902 params!(Jsonb, Jsonb) => BinaryFunc::Lt => Bool, 3242;
4903 params!(ArrayAny, ArrayAny) => BinaryFunc::Lt => Bool, 1072;
4904 params!(RecordAny, RecordAny) => BinaryFunc::Lt => Bool, 2990;
4905 params!(MzTimestamp, MzTimestamp)=>BinaryFunc::Lt =>Bool, oid::FUNC_MZ_TIMESTAMP_LT_MZ_TIMESTAMP_OID;
4906 params!(RangeAny, RangeAny) => BinaryFunc::Lt => Bool, 3884;
4907 },
4908 "<=" => Scalar {
4909 params!(Numeric, Numeric) => BinaryFunc::Lte => Bool, 1755;
4910 params!(Bool, Bool) => BinaryFunc::Lte => Bool, 1694;
4911 params!(Int16, Int16) => BinaryFunc::Lte => Bool, 522;
4912 params!(Int32, Int32) => BinaryFunc::Lte => Bool, 523;
4913 params!(Int64, Int64) => BinaryFunc::Lte => Bool, 414;
4914 params!(UInt16, UInt16) => BinaryFunc::Lte => Bool, oid::FUNC_LTE_UINT16_OID;
4915 params!(UInt32, UInt32) => BinaryFunc::Lte => Bool, oid::FUNC_LTE_UINT32_OID;
4916 params!(UInt64, UInt64) => BinaryFunc::Lte => Bool, oid::FUNC_LTE_UINT64_OID;
4917 params!(Float32, Float32) => BinaryFunc::Lte => Bool, 624;
4918 params!(Float64, Float64) => BinaryFunc::Lte => Bool, 673;
4919 params!(Oid, Oid) => BinaryFunc::Lte => Bool, 611;
4920 params!(Date, Date) => BinaryFunc::Lte => Bool, 1096;
4921 params!(Time, Time) => BinaryFunc::Lte => Bool, 1111;
4922 params!(Timestamp, Timestamp) => BinaryFunc::Lte => Bool, 2063;
4923 params!(TimestampTz, TimestampTz) => BinaryFunc::Lte => Bool, 1323;
4924 params!(Uuid, Uuid) => BinaryFunc::Lte => Bool, 2976;
4925 params!(Interval, Interval) => BinaryFunc::Lte => Bool, 1333;
4926 params!(Bytes, Bytes) => BinaryFunc::Lte => Bool, 1958;
4927 params!(String, String) => BinaryFunc::Lte => Bool, 665;
4928 params!(Char, Char) => BinaryFunc::Lte => Bool, 1059;
4929 params!(PgLegacyChar, PgLegacyChar) => BinaryFunc::Lte => Bool, 632;
4930 params!(PgLegacyName, PgLegacyName) => BinaryFunc::Lte => Bool, 661;
4931 params!(Jsonb, Jsonb) => BinaryFunc::Lte => Bool, 3244;
4932 params!(ArrayAny, ArrayAny) => BinaryFunc::Lte => Bool, 1074;
4933 params!(RecordAny, RecordAny) => BinaryFunc::Lte => Bool, 2992;
4934 params!(MzTimestamp, MzTimestamp)=>BinaryFunc::Lte =>Bool, oid::FUNC_MZ_TIMESTAMP_LTE_MZ_TIMESTAMP_OID;
4935 params!(RangeAny, RangeAny) => BinaryFunc::Lte => Bool, 3885;
4936 },
4937 ">" => Scalar {
4938 params!(Numeric, Numeric) => BinaryFunc::Gt => Bool, 1756;
4939 params!(Bool, Bool) => BinaryFunc::Gt => Bool, 59;
4940 params!(Int16, Int16) => BinaryFunc::Gt => Bool, 520;
4941 params!(Int32, Int32) => BinaryFunc::Gt => Bool, 521;
4942 params!(Int64, Int64) => BinaryFunc::Gt => Bool, 413;
4943 params!(UInt16, UInt16) => BinaryFunc::Gt => Bool, oid::FUNC_GT_UINT16_OID;
4944 params!(UInt32, UInt32) => BinaryFunc::Gt => Bool, oid::FUNC_GT_UINT32_OID;
4945 params!(UInt64, UInt64) => BinaryFunc::Gt => Bool, oid::FUNC_GT_UINT64_OID;
4946 params!(Float32, Float32) => BinaryFunc::Gt => Bool, 623;
4947 params!(Float64, Float64) => BinaryFunc::Gt => Bool, 674;
4948 params!(Oid, Oid) => BinaryFunc::Gt => Bool, 610;
4949 params!(Date, Date) => BinaryFunc::Gt => Bool, 1097;
4950 params!(Time, Time) => BinaryFunc::Gt => Bool, 1112;
4951 params!(Timestamp, Timestamp) => BinaryFunc::Gt => Bool, 2064;
4952 params!(TimestampTz, TimestampTz) => BinaryFunc::Gt => Bool, 1324;
4953 params!(Uuid, Uuid) => BinaryFunc::Gt => Bool, 2975;
4954 params!(Interval, Interval) => BinaryFunc::Gt => Bool, 1334;
4955 params!(Bytes, Bytes) => BinaryFunc::Gt => Bool, 1959;
4956 params!(String, String) => BinaryFunc::Gt => Bool, 666;
4957 params!(Char, Char) => BinaryFunc::Gt => Bool, 1060;
4958 params!(PgLegacyChar, PgLegacyChar) => BinaryFunc::Gt => Bool, 633;
4959 params!(PgLegacyName, PgLegacyName) => BinaryFunc::Gt => Bool, 662;
4960 params!(Jsonb, Jsonb) => BinaryFunc::Gt => Bool, 3243;
4961 params!(ArrayAny, ArrayAny) => BinaryFunc::Gt => Bool, 1073;
4962 params!(RecordAny, RecordAny) => BinaryFunc::Gt => Bool, 2991;
4963 params!(MzTimestamp, MzTimestamp)=>BinaryFunc::Gt =>Bool, oid::FUNC_MZ_TIMESTAMP_GT_MZ_TIMESTAMP_OID;
4964 params!(RangeAny, RangeAny) => BinaryFunc::Gt => Bool, 3887;
4965 },
4966 ">=" => Scalar {
4967 params!(Numeric, Numeric) => BinaryFunc::Gte => Bool, 1757;
4968 params!(Bool, Bool) => BinaryFunc::Gte => Bool, 1695;
4969 params!(Int16, Int16) => BinaryFunc::Gte => Bool, 524;
4970 params!(Int32, Int32) => BinaryFunc::Gte => Bool, 525;
4971 params!(Int64, Int64) => BinaryFunc::Gte => Bool, 415;
4972 params!(UInt16, UInt16) => BinaryFunc::Gte => Bool, oid::FUNC_GTE_UINT16_OID;
4973 params!(UInt32, UInt32) => BinaryFunc::Gte => Bool, oid::FUNC_GTE_UINT32_OID;
4974 params!(UInt64, UInt64) => BinaryFunc::Gte => Bool, oid::FUNC_GTE_UINT64_OID;
4975 params!(Float32, Float32) => BinaryFunc::Gte => Bool, 625;
4976 params!(Float64, Float64) => BinaryFunc::Gte => Bool, 675;
4977 params!(Oid, Oid) => BinaryFunc::Gte => Bool, 612;
4978 params!(Date, Date) => BinaryFunc::Gte => Bool, 1098;
4979 params!(Time, Time) => BinaryFunc::Gte => Bool, 1113;
4980 params!(Timestamp, Timestamp) => BinaryFunc::Gte => Bool, 2065;
4981 params!(TimestampTz, TimestampTz) => BinaryFunc::Gte => Bool, 1325;
4982 params!(Uuid, Uuid) => BinaryFunc::Gte => Bool, 2977;
4983 params!(Interval, Interval) => BinaryFunc::Gte => Bool, 1335;
4984 params!(Bytes, Bytes) => BinaryFunc::Gte => Bool, 1960;
4985 params!(String, String) => BinaryFunc::Gte => Bool, 667;
4986 params!(Char, Char) => BinaryFunc::Gte => Bool, 1061;
4987 params!(PgLegacyChar, PgLegacyChar) => BinaryFunc::Gte => Bool, 634;
4988 params!(PgLegacyName, PgLegacyName) => BinaryFunc::Gte => Bool, 663;
4989 params!(Jsonb, Jsonb) => BinaryFunc::Gte => Bool, 3245;
4990 params!(ArrayAny, ArrayAny) => BinaryFunc::Gte => Bool, 1075;
4991 params!(RecordAny, RecordAny) => BinaryFunc::Gte => Bool, 2993;
4992 params!(MzTimestamp, MzTimestamp)=>BinaryFunc::Gte =>Bool, oid::FUNC_MZ_TIMESTAMP_GTE_MZ_TIMESTAMP_OID;
4993 params!(RangeAny, RangeAny) => BinaryFunc::Gte => Bool, 3886;
4994 },
4995 "=" => Scalar {
5006 params!(Numeric, Numeric) => BinaryFunc::Eq => Bool, 1752;
5007 params!(Bool, Bool) => BinaryFunc::Eq => Bool, 91;
5008 params!(Int16, Int16) => BinaryFunc::Eq => Bool, 94;
5009 params!(Int32, Int32) => BinaryFunc::Eq => Bool, 96;
5010 params!(Int64, Int64) => BinaryFunc::Eq => Bool, 410;
5011 params!(UInt16, UInt16) => BinaryFunc::Eq => Bool, oid::FUNC_EQ_UINT16_OID;
5012 params!(UInt32, UInt32) => BinaryFunc::Eq => Bool, oid::FUNC_EQ_UINT32_OID;
5013 params!(UInt64, UInt64) => BinaryFunc::Eq => Bool, oid::FUNC_EQ_UINT64_OID;
5014 params!(Float32, Float32) => BinaryFunc::Eq => Bool, 620;
5015 params!(Float64, Float64) => BinaryFunc::Eq => Bool, 670;
5016 params!(Oid, Oid) => BinaryFunc::Eq => Bool, 607;
5017 params!(Date, Date) => BinaryFunc::Eq => Bool, 1093;
5018 params!(Time, Time) => BinaryFunc::Eq => Bool, 1108;
5019 params!(Timestamp, Timestamp) => BinaryFunc::Eq => Bool, 2060;
5020 params!(TimestampTz, TimestampTz) => BinaryFunc::Eq => Bool, 1320;
5021 params!(Uuid, Uuid) => BinaryFunc::Eq => Bool, 2972;
5022 params!(Interval, Interval) => BinaryFunc::Eq => Bool, 1330;
5023 params!(Bytes, Bytes) => BinaryFunc::Eq => Bool, 1955;
5024 params!(String, String) => BinaryFunc::Eq => Bool, 98;
5025 params!(Char, Char) => BinaryFunc::Eq => Bool, 1054;
5026 params!(PgLegacyChar, PgLegacyChar) => BinaryFunc::Eq => Bool, 92;
5027 params!(PgLegacyName, PgLegacyName) => BinaryFunc::Eq => Bool, 93;
5028 params!(Jsonb, Jsonb) => BinaryFunc::Eq => Bool, 3240;
5029 params!(ListAny, ListAny) => BinaryFunc::Eq => Bool, oid::FUNC_LIST_EQ_OID;
5030 params!(ArrayAny, ArrayAny) => BinaryFunc::Eq => Bool, 1070;
5031 params!(RecordAny, RecordAny) => BinaryFunc::Eq => Bool, 2988;
5032 params!(MzTimestamp, MzTimestamp) => BinaryFunc::Eq => Bool, oid::FUNC_MZ_TIMESTAMP_EQ_MZ_TIMESTAMP_OID;
5033 params!(RangeAny, RangeAny) => BinaryFunc::Eq => Bool, 3882;
5034 params!(MzAclItem, MzAclItem) => BinaryFunc::Eq => Bool, oid::FUNC_MZ_ACL_ITEM_EQ_MZ_ACL_ITEM_OID;
5035 params!(AclItem, AclItem) => BinaryFunc::Eq => Bool, 974;
5036 },
5037 "<>" => Scalar {
5038 params!(Numeric, Numeric) => BinaryFunc::NotEq => Bool, 1753;
5039 params!(Bool, Bool) => BinaryFunc::NotEq => Bool, 85;
5040 params!(Int16, Int16) => BinaryFunc::NotEq => Bool, 519;
5041 params!(Int32, Int32) => BinaryFunc::NotEq => Bool, 518;
5042 params!(Int64, Int64) => BinaryFunc::NotEq => Bool, 411;
5043 params!(UInt16, UInt16) => BinaryFunc::NotEq => Bool, oid::FUNC_NOT_EQ_UINT16_OID;
5044 params!(UInt32, UInt32) => BinaryFunc::NotEq => Bool, oid::FUNC_NOT_EQ_UINT32_OID;
5045 params!(UInt64, UInt64) => BinaryFunc::NotEq => Bool, oid::FUNC_NOT_EQ_UINT64_OID;
5046 params!(Float32, Float32) => BinaryFunc::NotEq => Bool, 621;
5047 params!(Float64, Float64) => BinaryFunc::NotEq => Bool, 671;
5048 params!(Oid, Oid) => BinaryFunc::NotEq => Bool, 608;
5049 params!(Date, Date) => BinaryFunc::NotEq => Bool, 1094;
5050 params!(Time, Time) => BinaryFunc::NotEq => Bool, 1109;
5051 params!(Timestamp, Timestamp) => BinaryFunc::NotEq => Bool, 2061;
5052 params!(TimestampTz, TimestampTz) => BinaryFunc::NotEq => Bool, 1321;
5053 params!(Uuid, Uuid) => BinaryFunc::NotEq => Bool, 2973;
5054 params!(Interval, Interval) => BinaryFunc::NotEq => Bool, 1331;
5055 params!(Bytes, Bytes) => BinaryFunc::NotEq => Bool, 1956;
5056 params!(String, String) => BinaryFunc::NotEq => Bool, 531;
5057 params!(Char, Char) => BinaryFunc::NotEq => Bool, 1057;
5058 params!(PgLegacyChar, PgLegacyChar) => BinaryFunc::NotEq => Bool, 630;
5059 params!(PgLegacyName, PgLegacyName) => BinaryFunc::NotEq => Bool, 643;
5060 params!(Jsonb, Jsonb) => BinaryFunc::NotEq => Bool, 3241;
5061 params!(ArrayAny, ArrayAny) => BinaryFunc::NotEq => Bool, 1071;
5062 params!(RecordAny, RecordAny) => BinaryFunc::NotEq => Bool, 2989;
5063 params!(MzTimestamp, MzTimestamp) => BinaryFunc::NotEq => Bool, oid::FUNC_MZ_TIMESTAMP_NOT_EQ_MZ_TIMESTAMP_OID;
5064 params!(RangeAny, RangeAny) => BinaryFunc::NotEq => Bool, 3883;
5065 params!(MzAclItem, MzAclItem) => BinaryFunc::NotEq => Bool, oid::FUNC_MZ_ACL_ITEM_NOT_EQ_MZ_ACL_ITEM_OID;
5066 }
5067 }
5068});
5069
5070pub fn resolve_op(op: &str) -> Result<&'static [FuncImpl<HirScalarExpr>], PlanError> {
5072 match OP_IMPLS.get(op) {
5073 Some(Func::Scalar(impls)) => Ok(impls),
5074 Some(_) => unreachable!("all operators must be scalar functions"),
5075 None => bail_unsupported!(format!("[{}]", op)),
5085 }
5086}
5087
5088fn current_settings(
5091 name: HirScalarExpr,
5092 missing_ok: HirScalarExpr,
5093) -> Result<HirScalarExpr, PlanError> {
5094 let expr = HirScalarExpr::call_binary(
5096 HirScalarExpr::call_unmaterializable(UnmaterializableFunc::ViewableVariables),
5097 HirScalarExpr::call_unary(name, UnaryFunc::Lower(func::Lower)),
5098 BinaryFunc::MapGetValue,
5099 );
5100 let expr = HirScalarExpr::if_then_else(
5101 missing_ok,
5102 expr.clone(),
5103 HirScalarExpr::call_variadic(
5104 VariadicFunc::ErrorIfNull,
5105 vec![
5106 expr,
5107 HirScalarExpr::literal(
5108 Datum::String("unrecognized configuration parameter"),
5109 ScalarType::String,
5110 ),
5111 ],
5112 ),
5113 );
5114 Ok(expr)
5115}