MCPcopy Create free account
hub / github.com/MaterializeInc/materialize / select_impl

Function select_impl

src/sql/src/func.rs:998–1077  ·  view source on GitHub ↗

Selects the best implementation given the provided `args` using a process similar to [PostgreSQL's parser][pgparser], and returns the `ScalarExpr` to invoke that function. Inline comments prefixed with number are taken from the "Function Type Resolution" section of the aforelinked page. # Errors - When the provided arguments are not valid for any implementation, e.g. cannot be converted to the a

(
    ecx: &ExprContext,
    spec: FuncSpec,
    impls: &[FuncImpl<R>],
    args: Vec<CoercibleScalarExpr>,
    order_by: Vec<ColumnOrder>,
)

Source from the content-addressed store, hash-verified

996///
997/// [pgparser]: https://www.postgresql.org/docs/current/typeconv-oper.html
998pub fn select_impl<R>(
999 ecx: &ExprContext,
1000 spec: FuncSpec,
1001 impls: &[FuncImpl<R>],
1002 args: Vec<CoercibleScalarExpr>,
1003 order_by: Vec<ColumnOrder>,
1004) -> Result<R, PlanError>
1005where
1006 R: fmt::Debug,
1007{
1008 let name = spec.to_string();
1009 let ecx = &ecx.with_name(&name);
1010 let mut types: Vec<_> = args.iter().map(|e| ecx.scalar_type(e)).collect();
1011
1012 // PostgreSQL force coerces all record types before function selection. We
1013 // may want to do something smarter in the future (e.g., a function that
1014 // accepts multiple `RecordAny` parameters should perhaps coerce to the
1015 // result of calling `guess_best_common_type` on all those parameters), but
1016 // for now we just directly match PostgreSQL's behavior.
1017 for ty in &mut types {
1018 ty.force_coerced_if_record();
1019 }
1020
1021 // 4.a. Discard candidate functions for which the input types do not
1022 // match and cannot be converted (using an implicit conversion) to
1023 // match. unknown literals are assumed to be convertible to anything for
1024 // this purpose.
1025 let impls: Vec<_> = impls
1026 .iter()
1027 .filter(|i| i.params.matches_argtypes(ecx, &types))
1028 .collect();
1029
1030 let f = find_match(ecx, &types, impls).map_err(|candidates| {
1031 let arg_types: Vec<_> = types
1032 .into_iter()
1033 .map(|ty| match ty {
1034 // This will be used in error msgs, therefore we call with `postgres_compat` false.
1035 CoercibleScalarType::Coerced(ty) => ecx.humanize_sql_scalar_type(&ty, false),
1036 CoercibleScalarType::Record(_) => "record".to_string(),
1037 CoercibleScalarType::Uncoerced => "unknown".to_string(),
1038 })
1039 .collect();
1040
1041 if candidates == 0 {
1042 match spec {
1043 FuncSpec::Func(name) => PlanError::UnknownFunction {
1044 name: ecx
1045 .qcx
1046 .scx
1047 .humanize_resolved_name(name)
1048 .expect("resolved to object")
1049 .to_string(),
1050 arg_types,
1051 },
1052 FuncSpec::Op(name) => PlanError::UnknownOperator {
1053 name: name.to_string(),
1054 arg_types,
1055 },

Callers 4

plan_aggregate_commonFunction · 0.85
plan_opFunction · 0.85
plan_functionFunction · 0.85

Calls 14

find_matchFunction · 0.85
matches_argtypesMethod · 0.80
expectMethod · 0.80
to_stringMethod · 0.45
with_nameMethod · 0.45
collectMethod · 0.45
mapMethod · 0.45
iterMethod · 0.45
scalar_typeMethod · 0.45
filterMethod · 0.45

Tested by

no test coverage detected