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>,
)
| 996 | /// |
| 997 | /// [pgparser]: https://www.postgresql.org/docs/current/typeconv-oper.html |
| 998 | pub 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> |
| 1005 | where |
| 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 | }, |
no test coverage detected