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

Function find_match

src/sql/src/func.rs:1084–1295  ·  view source on GitHub ↗

Finds an exact match based on the arguments, or, if no exact match, finds the best match available. Patterned after [PostgreSQL's type conversion matching algorithm][pgparser]. [pgparser]: https://www.postgresql.org/docs/current/typeconv-func.html

(
    ecx: &ExprContext,
    types: &[CoercibleScalarType],
    impls: Vec<&'a FuncImpl<R>>,
)

Source from the content-addressed store, hash-verified

1082///
1083/// [pgparser]: https://www.postgresql.org/docs/current/typeconv-func.html
1084fn find_match<'a, R: std::fmt::Debug>(
1085 ecx: &ExprContext,
1086 types: &[CoercibleScalarType],
1087 impls: Vec<&'a FuncImpl<R>>,
1088) -> Result<&'a FuncImpl<R>, usize> {
1089 let all_types_known = types.iter().all(|t| t.is_coerced());
1090
1091 // Check for exact match.
1092 if all_types_known {
1093 let known_types: Vec<_> = types.iter().filter_map(|t| t.as_coerced()).collect();
1094 let matching_impls: Vec<&FuncImpl<_>> = impls
1095 .iter()
1096 .filter(|i| i.params.exact_match(&known_types))
1097 .cloned()
1098 .collect();
1099
1100 if matching_impls.len() == 1 {
1101 return Ok(matching_impls[0]);
1102 }
1103 }
1104
1105 // No exact match. Apply PostgreSQL's best match algorithm. Generate
1106 // candidates by assessing their compatibility with each implementation's
1107 // parameters.
1108 let mut candidates: Vec<Candidate<_>> = Vec::new();
1109 macro_rules! maybe_get_last_candidate {
1110 () => {
1111 if candidates.len() == 1 {
1112 return Ok(&candidates[0].fimpl);
1113 }
1114 };
1115 }
1116 let mut max_exact_matches = 0;
1117
1118 for fimpl in impls {
1119 let mut exact_matches = 0;
1120 let mut preferred_types = 0;
1121 let mut near_matches = 0;
1122
1123 for (i, arg_type) in types.iter().enumerate() {
1124 let param_type = &fimpl.params[i];
1125
1126 match arg_type {
1127 CoercibleScalarType::Coerced(arg_type) => {
1128 if param_type == arg_type {
1129 exact_matches += 1;
1130 }
1131 if param_type.is_preferred_by(arg_type) {
1132 preferred_types += 1;
1133 }
1134 if param_type.is_near_match(arg_type) {
1135 near_matches += 1;
1136 }
1137 }
1138 CoercibleScalarType::Record(_) | CoercibleScalarType::Uncoerced => {
1139 if param_type.prefers_self() {
1140 preferred_types += 1;
1141 }

Callers 1

select_implFunction · 0.85

Calls 15

allMethod · 0.80
is_coercedMethod · 0.80
as_coercedMethod · 0.80
exact_matchMethod · 0.80
enumerateMethod · 0.80
is_preferred_byMethod · 0.80
is_near_matchMethod · 0.80
prefers_selfMethod · 0.80
unwrapMethod · 0.80
preferred_typeMethod · 0.80
accepts_typeMethod · 0.80
matches_argtypesMethod · 0.80

Tested by

no test coverage detected