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