Search in sources :

Example 1 with ScalarImplementationChoice

use of io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ScalarImplementationChoice in project hetu-core by openlookeng.

the class PolymorphicScalarFunction method getScalarFunctionImplementationChoice.

private ScalarImplementationChoice getScalarFunctionImplementationChoice(BoundVariables boundVariables, FunctionAndTypeManager functionAndTypeManager, PolymorphicScalarFunctionChoice choice) {
    List<Type> resolvedParameterTypes = applyBoundVariables(functionAndTypeManager, getSignature().getArgumentTypes(), boundVariables);
    Type resolvedReturnType = applyBoundVariables(functionAndTypeManager, getSignature().getReturnType(), boundVariables);
    SpecializeContext context = new SpecializeContext(boundVariables, resolvedParameterTypes, resolvedReturnType, functionAndTypeManager);
    Optional<MethodAndNativeContainerTypes> matchingMethod = Optional.empty();
    Optional<MethodsGroup> matchingMethodsGroup = Optional.empty();
    for (MethodsGroup candidateMethodsGroup : choice.getMethodsGroups()) {
        for (MethodAndNativeContainerTypes candidateMethod : candidateMethodsGroup.getMethods()) {
            if (matchesParameterAndReturnTypes(candidateMethod, resolvedParameterTypes, resolvedReturnType, choice.getArgumentProperties(), choice.isNullableResult())) {
                if (matchingMethod.isPresent()) {
                    throw new IllegalStateException("two matching methods (" + matchingMethod.get().getMethod().getName() + " and " + candidateMethod.getMethod().getName() + ") for parameter types " + resolvedParameterTypes);
                }
                matchingMethod = Optional.of(candidateMethod);
                matchingMethodsGroup = Optional.of(candidateMethodsGroup);
            }
        }
    }
    checkState(matchingMethod.isPresent(), "no matching method for parameter types %s", resolvedParameterTypes);
    List<Object> extraParameters = computeExtraParameters(matchingMethodsGroup.get(), context);
    MethodHandle methodHandle = applyExtraParameters(matchingMethod.get().getMethod(), extraParameters, choice.getArgumentProperties());
    return new ScalarImplementationChoice(choice.isNullableResult(), choice.getArgumentProperties(), choice.getReturnPlaceConvention(), methodHandle, Optional.empty());
}
Also used : SpecializeContext(io.prestosql.metadata.PolymorphicScalarFunctionBuilder.SpecializeContext) Type(io.prestosql.spi.type.Type) MethodAndNativeContainerTypes(io.prestosql.metadata.PolymorphicScalarFunctionBuilder.MethodAndNativeContainerTypes) MethodsGroup(io.prestosql.metadata.PolymorphicScalarFunctionBuilder.MethodsGroup) ScalarImplementationChoice(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ScalarImplementationChoice) MethodHandle(java.lang.invoke.MethodHandle)

Example 2 with ScalarImplementationChoice

use of io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ScalarImplementationChoice in project hetu-core by openlookeng.

the class BytecodeUtils method generateInvocation.

public static BytecodeNode generateInvocation(Scope scope, String name, BuiltInScalarFunctionImplementation function, Optional<BytecodeNode> instance, List<BytecodeNode> arguments, CallSiteBinder binder) {
    LabelNode end = new LabelNode("end");
    BytecodeBlock block = new BytecodeBlock().setDescription("invoke " + name);
    List<Class<?>> stackTypes = new ArrayList<>();
    if (function.getInstanceFactory().isPresent()) {
        checkArgument(instance.isPresent());
    }
    // Index of current parameter in the MethodHandle
    int currentParameterIndex = 0;
    // Index of parameter (without @IsNull) in Presto function
    int realParameterIndex = 0;
    // Go through all the choices in the function and then pick the best one
    List<ScalarImplementationChoice> choices = function.getAllChoices();
    ScalarImplementationChoice bestChoice = null;
    for (ScalarImplementationChoice currentChoice : choices) {
        boolean isValid = true;
        for (int i = 0; i < arguments.size(); i++) {
            if (currentChoice.getArgumentProperty(i).getArgumentType() != VALUE_TYPE) {
                continue;
            }
            if (!(arguments.get(i) instanceof InputReferenceNode) && currentChoice.getArgumentProperty(i).getNullConvention() == NullConvention.BLOCK_AND_POSITION) {
                isValid = false;
                break;
            }
        }
        if (isValid) {
            bestChoice = currentChoice;
        }
    }
    checkState(bestChoice != null, "None of the scalar function implementation choices are valid");
    Binding binding = binder.bind(bestChoice.getMethodHandle());
    MethodType methodType = binding.getType();
    Class<?> returnType = methodType.returnType();
    Class<?> unboxedReturnType = Primitives.unwrap(returnType);
    boolean boundInstance = false;
    while (currentParameterIndex < methodType.parameterArray().length) {
        Class<?> type = methodType.parameterArray()[currentParameterIndex];
        stackTypes.add(type);
        if (bestChoice.getInstanceFactory().isPresent() && !boundInstance) {
            checkState(type.equals(bestChoice.getInstanceFactory().get().type().returnType()), "Mismatched type for instance parameter");
            block.append(instance.get());
            boundInstance = true;
        } else if (type == ConnectorSession.class) {
            block.append(scope.getVariable("session"));
        } else {
            ArgumentProperty argumentProperty = bestChoice.getArgumentProperty(realParameterIndex);
            switch(argumentProperty.getArgumentType()) {
                case VALUE_TYPE:
                    // Apply null convention for value type argument
                    switch(argumentProperty.getNullConvention()) {
                        case RETURN_NULL_ON_NULL:
                            block.append(arguments.get(realParameterIndex));
                            checkArgument(!Primitives.isWrapperType(type), "Non-nullable argument must not be primitive wrapper type");
                            block.append(ifWasNullPopAndGoto(scope, end, unboxedReturnType, Lists.reverse(stackTypes)));
                            break;
                        case USE_NULL_FLAG:
                            block.append(arguments.get(realParameterIndex));
                            block.append(scope.getVariable("wasNull"));
                            block.append(scope.getVariable("wasNull").set(constantFalse()));
                            stackTypes.add(boolean.class);
                            currentParameterIndex++;
                            break;
                        case USE_BOXED_TYPE:
                            block.append(arguments.get(realParameterIndex));
                            block.append(boxPrimitiveIfNecessary(scope, type));
                            block.append(scope.getVariable("wasNull").set(constantFalse()));
                            break;
                        case BLOCK_AND_POSITION:
                            InputReferenceNode inputReferenceNode = (InputReferenceNode) arguments.get(realParameterIndex);
                            block.append(inputReferenceNode.produceBlockAndPosition());
                            stackTypes.add(int.class);
                            currentParameterIndex++;
                            break;
                        default:
                            throw new UnsupportedOperationException(format("Unsupported null convention: %s", argumentProperty.getNullConvention()));
                    }
                    break;
                case FUNCTION_TYPE:
                    block.append(arguments.get(realParameterIndex));
                    break;
                default:
                    throw new UnsupportedOperationException(format("Unsupported argument type: %s", argumentProperty.getArgumentType()));
            }
            realParameterIndex++;
        }
        currentParameterIndex++;
    }
    block.append(invoke(binding, name));
    if (function.isNullable()) {
        block.append(unboxPrimitiveIfNecessary(scope, returnType));
    }
    block.visitLabel(end);
    return block;
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) MethodType(java.lang.invoke.MethodType) ArgumentProperty(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) ArrayList(java.util.ArrayList) ScalarImplementationChoice(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ScalarImplementationChoice) InputReferenceNode(io.prestosql.sql.gen.InputReferenceCompiler.InputReferenceNode) ConnectorSession(io.prestosql.spi.connector.ConnectorSession)

Example 3 with ScalarImplementationChoice

use of io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ScalarImplementationChoice in project hetu-core by openlookeng.

the class ParametricScalarImplementation method specialize.

public Optional<BuiltInScalarFunctionImplementation> specialize(Signature boundSignature, BoundVariables boundVariables, FunctionAndTypeManager functionAndTypeManager, boolean isDeterministic) {
    List<ScalarImplementationChoice> implementationChoices = new ArrayList<>();
    for (Map.Entry<String, Class<?>> entry : specializedTypeParameters.entrySet()) {
        if (entry.getValue() != boundVariables.getTypeVariable(entry.getKey()).getJavaType()) {
            return Optional.empty();
        }
    }
    if (returnNativeContainerType != Object.class && returnNativeContainerType != functionAndTypeManager.getType(boundSignature.getReturnType()).getJavaType()) {
        return Optional.empty();
    }
    for (int i = 0; i < boundSignature.getArgumentTypes().size(); i++) {
        if (boundSignature.getArgumentTypes().get(i).getBase().equals(FunctionType.NAME)) {
            if (argumentNativeContainerTypes.get(i).isPresent()) {
                return Optional.empty();
            }
        } else {
            if (!argumentNativeContainerTypes.get(i).isPresent()) {
                return Optional.empty();
            }
            Class<?> argumentType = functionAndTypeManager.getType(boundSignature.getArgumentTypes().get(i)).getJavaType();
            Class<?> argumentNativeContainerType = argumentNativeContainerTypes.get(i).get();
            if (argumentNativeContainerType != Object.class && argumentNativeContainerType != argumentType) {
                return Optional.empty();
            }
        }
    }
    for (ParametricScalarImplementationChoice choice : choices) {
        MethodHandle boundMethodHandle = bindDependencies(choice.getMethodHandle(), choice.getDependencies(), boundVariables, functionAndTypeManager);
        Optional<MethodHandle> boundConstructor = choice.getConstructor().map(constructor -> {
            MethodHandle result = bindDependencies(constructor, choice.getConstructorDependencies(), boundVariables, functionAndTypeManager);
            checkCondition(result.type().parameterList().isEmpty(), FUNCTION_IMPLEMENTATION_ERROR, "All parameters of a constructor in a function definition class must be Dependencies. Signature: %s", boundSignature);
            return result;
        });
        implementationChoices.add(new ScalarImplementationChoice(choice.nullable, choice.argumentProperties, choice.returnPlaceConvention, boundMethodHandle.asType(javaMethodType(choice, boundSignature, functionAndTypeManager)), boundConstructor));
    }
    return Optional.of(new BuiltInScalarFunctionImplementation(implementationChoices));
}
Also used : BuiltInScalarFunctionImplementation(io.prestosql.spi.function.BuiltInScalarFunctionImplementation) ArrayList(java.util.ArrayList) ScalarImplementationChoice(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ScalarImplementationChoice) LongVariableConstraint(io.prestosql.spi.function.LongVariableConstraint) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) Reflection.constructorMethodHandle(io.prestosql.spi.util.Reflection.constructorMethodHandle) MethodHandle(java.lang.invoke.MethodHandle)

Example 4 with ScalarImplementationChoice

use of io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ScalarImplementationChoice in project hetu-core by openlookeng.

the class FunctionInvokerProvider method createFunctionInvoker.

public FunctionInvoker createFunctionInvoker(FunctionHandle functionHandle, Optional<InvocationConvention> invocationConvention) {
    BuiltInScalarFunctionImplementation builtInScalarFunctionImplementation = functionAndTypeManager.getBuiltInScalarFunctionImplementation(functionHandle);
    for (ScalarImplementationChoice choice : builtInScalarFunctionImplementation.getAllChoices()) {
        if (checkChoice(choice.getArgumentProperties(), choice.isNullable(), choice.hasProperties(), invocationConvention)) {
            return new FunctionInvoker(choice.getMethodHandle());
        }
    }
    checkState(invocationConvention.isPresent());
    throw new PrestoException(FUNCTION_NOT_FOUND, format("Dependent function implementation (%s) with convention (%s) is not available", functionHandle, invocationConvention.toString()));
}
Also used : BuiltInScalarFunctionImplementation(io.prestosql.spi.function.BuiltInScalarFunctionImplementation) ScalarImplementationChoice(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ScalarImplementationChoice) PrestoException(io.prestosql.spi.PrestoException)

Example 5 with ScalarImplementationChoice

use of io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ScalarImplementationChoice in project hetu-core by openlookeng.

the class RowDistinctFromOperator method specialize.

@Override
public BuiltInScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, FunctionAndTypeManager functionAndTypeManager) {
    ImmutableList.Builder<MethodHandle> argumentMethods = ImmutableList.builder();
    Type type = boundVariables.getTypeVariable("T");
    for (Type parameterType : type.getTypeParameters()) {
        FunctionHandle operatorHandle = functionAndTypeManager.resolveOperatorFunctionHandle(IS_DISTINCT_FROM, TypeSignatureProvider.fromTypes(parameterType, parameterType));
        FunctionInvoker functionInvoker = functionAndTypeManager.getFunctionInvokerProvider().createFunctionInvoker(operatorHandle, Optional.of(new InvocationConvention(ImmutableList.of(NULL_FLAG, NULL_FLAG), InvocationConvention.InvocationReturnConvention.FAIL_ON_NULL, false)));
        argumentMethods.add(functionInvoker.methodHandle());
    }
    return new BuiltInScalarFunctionImplementation(ImmutableList.of(new ScalarImplementationChoice(false, ImmutableList.of(valueTypeArgumentProperty(USE_NULL_FLAG), valueTypeArgumentProperty(USE_NULL_FLAG)), BuiltInScalarFunctionImplementation.ReturnPlaceConvention.STACK, METHOD_HANDLE_NULL_FLAG.bindTo(type).bindTo(argumentMethods.build()), Optional.empty()), new ScalarImplementationChoice(false, ImmutableList.of(valueTypeArgumentProperty(BLOCK_AND_POSITION), valueTypeArgumentProperty(BLOCK_AND_POSITION)), BuiltInScalarFunctionImplementation.ReturnPlaceConvention.STACK, METHOD_HANDLE_BLOCK_POSITION.bindTo(type).bindTo(argumentMethods.build()), Optional.empty())));
}
Also used : Type(io.prestosql.spi.type.Type) ImmutableList(com.google.common.collect.ImmutableList) BuiltInScalarFunctionImplementation(io.prestosql.spi.function.BuiltInScalarFunctionImplementation) InvocationConvention(io.prestosql.spi.function.InvocationConvention) ScalarImplementationChoice(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ScalarImplementationChoice) FunctionInvoker(io.prestosql.metadata.FunctionInvoker) FunctionHandle(io.prestosql.spi.function.FunctionHandle) MethodHandle(java.lang.invoke.MethodHandle)

Aggregations

ScalarImplementationChoice (io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ScalarImplementationChoice)5 BuiltInScalarFunctionImplementation (io.prestosql.spi.function.BuiltInScalarFunctionImplementation)3 MethodHandle (java.lang.invoke.MethodHandle)3 Type (io.prestosql.spi.type.Type)2 ArrayList (java.util.ArrayList)2 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 BytecodeBlock (io.airlift.bytecode.BytecodeBlock)1 LabelNode (io.airlift.bytecode.instruction.LabelNode)1 FunctionInvoker (io.prestosql.metadata.FunctionInvoker)1 MethodAndNativeContainerTypes (io.prestosql.metadata.PolymorphicScalarFunctionBuilder.MethodAndNativeContainerTypes)1 MethodsGroup (io.prestosql.metadata.PolymorphicScalarFunctionBuilder.MethodsGroup)1 SpecializeContext (io.prestosql.metadata.PolymorphicScalarFunctionBuilder.SpecializeContext)1 PrestoException (io.prestosql.spi.PrestoException)1 ConnectorSession (io.prestosql.spi.connector.ConnectorSession)1 ArgumentProperty (io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty)1 FunctionHandle (io.prestosql.spi.function.FunctionHandle)1 InvocationConvention (io.prestosql.spi.function.InvocationConvention)1 LongVariableConstraint (io.prestosql.spi.function.LongVariableConstraint)1 Reflection.constructorMethodHandle (io.prestosql.spi.util.Reflection.constructorMethodHandle)1