Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import com.facebook.presto.sql.analyzer.FeaturesConfig;
import com.facebook.presto.sql.analyzer.FunctionAndTypeResolver;
import com.facebook.presto.sql.analyzer.FunctionsConfig;
import com.facebook.presto.sql.analyzer.SemanticException;
import com.facebook.presto.sql.analyzer.TypeSignatureProvider;
import com.facebook.presto.sql.gen.CacheStatsMBean;
import com.facebook.presto.sql.tree.QualifiedName;
Expand All @@ -80,6 +81,7 @@
import org.weakref.jmx.Managed;
import org.weakref.jmx.Nested;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
Expand All @@ -100,6 +102,7 @@
import static com.facebook.presto.metadata.BuiltInTypeAndFunctionNamespaceManager.JAVA_BUILTIN_NAMESPACE;
import static com.facebook.presto.metadata.CastType.toOperatorType;
import static com.facebook.presto.metadata.FunctionSignatureMatcher.constructFunctionNotFoundErrorMessage;
import static com.facebook.presto.metadata.FunctionSignatureMatcher.decideAndThrow;
import static com.facebook.presto.metadata.SessionFunctionHandle.SESSION_NAMESPACE;
import static com.facebook.presto.metadata.SignatureBinder.applyBoundVariables;
import static com.facebook.presto.spi.StandardErrorCode.AMBIGUOUS_FUNCTION_CALL;
Expand Down Expand Up @@ -1044,12 +1047,58 @@ private FunctionHandle getMatchingFunctionHandle(
List<TypeSignatureProvider> parameterTypes,
boolean coercionAllowed)
{
Optional<Signature> matchingDefaultFunctionSignature =
getMatchingFunction(functionNamespaceManager.getFunctions(transactionHandle, functionName), parameterTypes, coercionAllowed);
Optional<Signature> matchingPluginFunctionSignature =
getMatchingFunction(builtInPluginFunctionNamespaceManager.getFunctions(transactionHandle, functionName), parameterTypes, coercionAllowed);
Optional<Signature> matchingWorkerFunctionSignature =
getMatchingFunction(builtInWorkerFunctionNamespaceManager.getFunctions(transactionHandle, functionName), parameterTypes, coercionAllowed);
boolean foundMatch = false;
List<SemanticException> exceptions = new ArrayList<>();
List<SqlFunction> allCandidates = new ArrayList<>();
Optional<Signature> matchingDefaultFunctionSignature = Optional.empty();
Optional<Signature> matchingPluginFunctionSignature = Optional.empty();
Optional<Signature> matchingWorkerFunctionSignature = Optional.empty();

try {
Collection<? extends SqlFunction> defaultCandidates = functionNamespaceManager.getFunctions(transactionHandle, functionName);
allCandidates.addAll(defaultCandidates);
matchingDefaultFunctionSignature =
getMatchingFunction(defaultCandidates, parameterTypes, coercionAllowed);
if (matchingDefaultFunctionSignature.isPresent()) {
foundMatch = true;
}
}
catch (SemanticException e) {
Comment on lines 1057 to 1066
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Repeated try-catch blocks could be refactored for clarity.

Refactor the similar try-catch blocks into a shared helper or loop to minimize code duplication and enhance maintainability.

Suggested implementation:

        boolean foundMatch = false;
        List<SemanticException> exceptions = new ArrayList<>();
        List<SqlFunction> allCandidates = new ArrayList<>();
        Optional<Signature> matchingDefaultFunctionSignature = Optional.empty();
        Optional<Signature> matchingPluginFunctionSignature = Optional.empty();
        Optional<Signature> matchingWorkerFunctionSignature = Optional.empty();

        class FunctionMatchResult {
            Optional<Signature> signature;
            Collection<? extends SqlFunction> candidates;
            boolean matched;
            FunctionMatchResult(Optional<Signature> signature, Collection<? extends SqlFunction> candidates, boolean matched) {
                this.signature = signature;
                this.candidates = candidates;
                this.matched = matched;
            }
        }

        FunctionMatchResult matchFunction(FunctionNamespaceManager<?> namespaceManager) {
            try {
                Collection<? extends SqlFunction> candidates = namespaceManager.getFunctions(transactionHandle, functionName);
                Optional<Signature> signature = getMatchingFunction(candidates, parameterTypes, coercionAllowed);
                boolean matched = signature.isPresent();
                return new FunctionMatchResult(signature, candidates, matched);
            }
            catch (SemanticException e) {
                exceptions.add(e);
                return new FunctionMatchResult(Optional.empty(), Collections.emptyList(), false);
            }
        }

        FunctionMatchResult defaultResult = matchFunction(functionNamespaceManager);
        matchingDefaultFunctionSignature = defaultResult.signature;
        if (defaultResult.matched) {
            foundMatch = true;
            allCandidates.addAll(defaultResult.candidates);
        }

        FunctionMatchResult pluginResult = matchFunction(builtInPluginFunctionNamespaceManager);
        matchingPluginFunctionSignature = pluginResult.signature;
        if (pluginResult.matched) {
            foundMatch = true;

You should also refactor the third try-catch block (for worker functions) in the same way, using the new matchFunction helper.
If the worker function block exists further down, replace it with:

FunctionMatchResult workerResult = matchFunction(workerFunctionNamespaceManager);
matchingWorkerFunctionSignature = workerResult.signature;
if (workerResult.matched) {
    foundMatch = true;
    allCandidates.addAll(workerResult.candidates);
}

Remove the original try-catch for worker functions.

exceptions.add(e);
}

try {
Collection<? extends SqlFunction> pluginCandidates = builtInPluginFunctionNamespaceManager.getFunctions(transactionHandle, functionName);
allCandidates.addAll(pluginCandidates);
matchingPluginFunctionSignature =
getMatchingFunction(pluginCandidates, parameterTypes, coercionAllowed);
if (matchingPluginFunctionSignature.isPresent()) {
foundMatch = true;
}
}
catch (SemanticException e) {
exceptions.add(e);
}

try {
Collection<? extends SqlFunction> workerCandidates = builtInWorkerFunctionNamespaceManager.getFunctions(transactionHandle, functionName);
allCandidates.addAll(workerCandidates);
matchingWorkerFunctionSignature =
getMatchingFunction(workerCandidates, parameterTypes, coercionAllowed);
if (matchingWorkerFunctionSignature.isPresent()) {
foundMatch = true;
}
}
catch (SemanticException e) {
exceptions.add(e);
}

if (!foundMatch && !exceptions.isEmpty()) {
decideAndThrow(exceptions,
allCandidates.stream().findFirst()
.map(function -> function.getSignature().getName().getObjectName())
.orElse(""));
}

if (matchingDefaultFunctionSignature.isPresent() && matchingPluginFunctionSignature.isPresent()) {
throw new PrestoException(AMBIGUOUS_FUNCTION_CALL, format("Function '%s' has two matching signatures. Please specify parameter types. \n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ private static boolean returnsNullOnGivenInputTypes(ApplicableFunction applicabl
* If there's only one SemanticException, it throws that SemanticException directly.
* If there are multiple SemanticExceptions, it throws the SignatureMatchingException.
*/
private static void decideAndThrow(List<SemanticException> failedExceptions, String functionName)
public static void decideAndThrow(List<SemanticException> failedExceptions, String functionName)
throws SemanticException
{
if (failedExceptions.size() == 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ public HiveQueryRunnerBuilder setCoordinatorSidecarEnabled(boolean coordinatorSi
public HiveQueryRunnerBuilder setBuiltInWorkerFunctionsEnabled(boolean builtInWorkerFunctionsEnabled)
{
this.builtInWorkerFunctionsEnabled = builtInWorkerFunctionsEnabled;
if (builtInWorkerFunctionsEnabled) {
this.extraProperties.put("built-in-sidecar-functions-enabled", "true");
}

return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,5 +214,8 @@ public void testUdfQueries()

assertPlan("SELECT test_agg_function(cast(orderkey as integer), cast(orderkey as integer), cast(orderkey as bigint)) FROM tpch.tiny.orders", anyTree(any()));
assertPlan("SELECT test_agg_function(5, cast(orderkey as smallint), orderkey) FROM tpch.tiny.orders", anyTree(any()));

assertQuerySucceeds("SELECT ARRAY_SORT( ARRAY[ ARRAY['a', 'b', 'c'] ], (x, y) -> IF( COALESCE( x[1], '' ) > COALESCE( y[1], '' ), 1, IF( COALESCE( x[1], '' ) < COALESCE( y[1], '' ), -1, 0 ) ) )");
assertQuerySucceeds("SELECT ARRAY_SORT( ARRAY[ ARRAY['a', 'b', 'c'] ], (x, y) -> IF( COALESCE( x[1], '' ) > COALESCE( y[1], '' ), cast(1 as bigint), IF( COALESCE( x[1], '' ) < COALESCE( y[1], '' ), cast(-1 as bigint), cast(0 as bigint) ) ) )");
}
}
Loading