Search in sources :

Example 1 with ArgumentProperty

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

the class ArrayJoin method specializeArrayJoin.

private static BuiltInScalarFunctionImplementation specializeArrayJoin(Map<String, Type> types, FunctionAndTypeManager functionAndTypeManager, List<Boolean> nullableArguments, MethodHandle methodHandle) {
    Type type = types.get("T");
    List<ArgumentProperty> argumentProperties = nullableArguments.stream().map(nullable -> nullable ? valueTypeArgumentProperty(USE_BOXED_TYPE) : valueTypeArgumentProperty(RETURN_NULL_ON_NULL)).collect(toImmutableList());
    if (type instanceof UnknownType) {
        return new BuiltInScalarFunctionImplementation(false, argumentProperties, methodHandle.bindTo(null), Optional.of(STATE_FACTORY));
    } else {
        try {
            BuiltInScalarFunctionImplementation castFunction = functionAndTypeManager.getBuiltInScalarFunctionImplementation(functionAndTypeManager.lookupCast(CastType.CAST, type.getTypeSignature(), VARCHAR_TYPE_SIGNATURE));
            MethodHandle getter;
            Class<?> elementType = type.getJavaType();
            if (elementType == boolean.class) {
                getter = GET_BOOLEAN;
            } else if (elementType == double.class) {
                getter = GET_DOUBLE;
            } else if (elementType == long.class) {
                getter = GET_LONG;
            } else if (elementType == Slice.class) {
                getter = GET_SLICE;
            } else {
                throw new UnsupportedOperationException("Unsupported type: " + elementType.getName());
            }
            MethodHandle cast = castFunction.getMethodHandle();
            // if the cast doesn't take a ConnectorSession, create an adapter that drops the provided session
            if (cast.type().parameterArray()[0] != ConnectorSession.class) {
                cast = MethodHandles.dropArguments(cast, 0, ConnectorSession.class);
            }
            // Adapt a target cast that takes (ConnectorSession, ?) to one that takes (Block, int, ConnectorSession), which will be invoked by the implementation
            // The first two arguments (Block, int) are filtered through the element type's getXXX method to produce the underlying value that needs to be passed to
            // the cast.
            cast = MethodHandles.permuteArguments(cast, MethodType.methodType(Slice.class, cast.type().parameterArray()[1], cast.type().parameterArray()[0]), 1, 0);
            cast = MethodHandles.dropArguments(cast, 1, int.class);
            cast = MethodHandles.dropArguments(cast, 1, Block.class);
            cast = MethodHandles.foldArguments(cast, getter.bindTo(type));
            MethodHandle target = MethodHandles.insertArguments(methodHandle, 0, cast);
            return new BuiltInScalarFunctionImplementation(false, argumentProperties, target, Optional.of(STATE_FACTORY));
        } catch (PrestoException e) {
            throw new PrestoException(INVALID_FUNCTION_ARGUMENT, String.format("Input type %s not supported", type), e);
        }
    }
}
Also used : BuiltInScalarFunctionImplementation(io.prestosql.spi.function.BuiltInScalarFunctionImplementation) UnknownType(io.prestosql.spi.type.UnknownType) MethodHandle(java.lang.invoke.MethodHandle) Slice(io.airlift.slice.Slice) FunctionKind(io.prestosql.spi.function.FunctionKind) StandardTypes(io.prestosql.spi.type.StandardTypes) ArgumentProperty(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty) INVALID_FUNCTION_ARGUMENT(io.prestosql.spi.StandardErrorCode.INVALID_FUNCTION_ARGUMENT) BoundVariables(io.prestosql.metadata.BoundVariables) DEFAULT_NAMESPACE(io.prestosql.spi.connector.CatalogSchemaName.DEFAULT_NAMESPACE) USE_BOXED_TYPE(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.NullConvention.USE_BOXED_TYPE) UsedByGeneratedCode(io.prestosql.spi.annotation.UsedByGeneratedCode) QualifiedObjectName(io.prestosql.spi.connector.QualifiedObjectName) TypeSignature.parseTypeSignature(io.prestosql.spi.type.TypeSignature.parseTypeSignature) VARCHAR(io.prestosql.spi.type.VarcharType.VARCHAR) ImmutableList(com.google.common.collect.ImmutableList) ConnectorSession(io.prestosql.spi.connector.ConnectorSession) Map(java.util.Map) RETURN_NULL_ON_NULL(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.NullConvention.RETURN_NULL_ON_NULL) Type(io.prestosql.spi.type.Type) Signature(io.prestosql.spi.function.Signature) Block(io.prestosql.spi.block.Block) PrestoException(io.prestosql.spi.PrestoException) CastType(io.prestosql.metadata.CastType) SqlScalarFunction(io.prestosql.metadata.SqlScalarFunction) BlockBuilder(io.prestosql.spi.block.BlockBuilder) MethodHandles(java.lang.invoke.MethodHandles) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Reflection.methodHandle(io.prestosql.spi.util.Reflection.methodHandle) PageBuilder(io.prestosql.spi.PageBuilder) Signature.typeVariable(io.prestosql.spi.function.Signature.typeVariable) List(java.util.List) MethodType(java.lang.invoke.MethodType) GENERIC_INTERNAL_ERROR(io.prestosql.spi.StandardErrorCode.GENERIC_INTERNAL_ERROR) ArgumentProperty.valueTypeArgumentProperty(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty.valueTypeArgumentProperty) Optional(java.util.Optional) TypeSignature(io.prestosql.spi.type.TypeSignature) FunctionAndTypeManager(io.prestosql.metadata.FunctionAndTypeManager) ArgumentProperty(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty) ArgumentProperty.valueTypeArgumentProperty(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty.valueTypeArgumentProperty) BuiltInScalarFunctionImplementation(io.prestosql.spi.function.BuiltInScalarFunctionImplementation) PrestoException(io.prestosql.spi.PrestoException) UnknownType(io.prestosql.spi.type.UnknownType) UnknownType(io.prestosql.spi.type.UnknownType) Type(io.prestosql.spi.type.Type) CastType(io.prestosql.metadata.CastType) MethodType(java.lang.invoke.MethodType) Slice(io.airlift.slice.Slice) Block(io.prestosql.spi.block.Block) ConnectorSession(io.prestosql.spi.connector.ConnectorSession) MethodHandle(java.lang.invoke.MethodHandle)

Example 2 with ArgumentProperty

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

the class TestFunctionInvokerProvider method testFunctionInvokerProvider.

@Test
public void testFunctionInvokerProvider() {
    assertTrue(checkChoice(ImmutableList.of(new ArgumentProperty(VALUE_TYPE, Optional.of(USE_BOXED_TYPE), Optional.empty()), new ArgumentProperty(VALUE_TYPE, Optional.of(USE_BOXED_TYPE), Optional.empty())), true, false, Optional.of(new InvocationConvention(ImmutableList.of(BOXED_NULLABLE, BOXED_NULLABLE), InvocationReturnConvention.NULLABLE_RETURN, false))));
    assertTrue(checkChoice(ImmutableList.of(new ArgumentProperty(VALUE_TYPE, Optional.of(RETURN_NULL_ON_NULL), Optional.empty()), new ArgumentProperty(VALUE_TYPE, Optional.of(BLOCK_AND_POSITION), Optional.empty()), new ArgumentProperty(VALUE_TYPE, Optional.of(BLOCK_AND_POSITION), Optional.empty())), false, false, Optional.of(new InvocationConvention(ImmutableList.of(NEVER_NULL, BLOCK_POSITION, BLOCK_POSITION), InvocationReturnConvention.FAIL_ON_NULL, false))));
    assertTrue(checkChoice(ImmutableList.of(new ArgumentProperty(VALUE_TYPE, Optional.of(BLOCK_AND_POSITION), Optional.empty()), new ArgumentProperty(VALUE_TYPE, Optional.of(USE_NULL_FLAG), Optional.empty()), new ArgumentProperty(VALUE_TYPE, Optional.of(BLOCK_AND_POSITION), Optional.empty())), false, false, Optional.of(new InvocationConvention(ImmutableList.of(BLOCK_POSITION, NULL_FLAG, BLOCK_POSITION), InvocationReturnConvention.FAIL_ON_NULL, false))));
    assertFalse(checkChoice(ImmutableList.of(new ArgumentProperty(VALUE_TYPE, Optional.of(BLOCK_AND_POSITION), Optional.empty()), new ArgumentProperty(VALUE_TYPE, Optional.of(USE_BOXED_TYPE), Optional.empty())), false, false, Optional.of(new InvocationConvention(ImmutableList.of(BLOCK_POSITION, BOXED_NULLABLE), InvocationReturnConvention.NULLABLE_RETURN, false))));
    assertFalse(checkChoice(ImmutableList.of(new ArgumentProperty(VALUE_TYPE, Optional.of(BLOCK_AND_POSITION), Optional.empty()), new ArgumentProperty(VALUE_TYPE, Optional.of(BLOCK_AND_POSITION), Optional.empty())), false, false, Optional.of(new InvocationConvention(ImmutableList.of(BLOCK_POSITION, NULL_FLAG), InvocationReturnConvention.NULLABLE_RETURN, false))));
    assertFalse(checkChoice(ImmutableList.of(new ArgumentProperty(VALUE_TYPE, Optional.of(USE_NULL_FLAG), Optional.empty()), new ArgumentProperty(VALUE_TYPE, Optional.of(USE_BOXED_TYPE), Optional.empty())), true, false, Optional.of(new InvocationConvention(ImmutableList.of(BLOCK_POSITION, BOXED_NULLABLE), InvocationReturnConvention.FAIL_ON_NULL, false))));
}
Also used : ArgumentProperty(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty) InvocationConvention(io.prestosql.spi.function.InvocationConvention) Test(org.testng.annotations.Test)

Example 3 with ArgumentProperty

use of io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty 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 4 with ArgumentProperty

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

the class ParametricScalarImplementation method javaMethodType.

private static MethodType javaMethodType(ParametricScalarImplementationChoice choice, Signature signature, TypeManager typeManager) {
    // This method accomplishes two purposes:
    // * Assert that the method signature is as expected.
    // This catches errors that would otherwise surface during bytecode generation and class loading.
    // * Adapt the method signature when necessary (for example, when the parameter type or return type is declared as Object).
    ImmutableList.Builder<Class<?>> methodHandleParameterTypes = ImmutableList.builder();
    if (choice.getConstructor().isPresent()) {
        methodHandleParameterTypes.add(Object.class);
    }
    if (choice.hasConnectorSession()) {
        methodHandleParameterTypes.add(ConnectorSession.class);
    }
    List<ArgumentProperty> argumentProperties = choice.getArgumentProperties();
    for (int i = 0; i < argumentProperties.size(); i++) {
        ArgumentProperty argumentProperty = argumentProperties.get(i);
        switch(argumentProperty.getArgumentType()) {
            case VALUE_TYPE:
                Type signatureType = typeManager.getType(signature.getArgumentTypes().get(i));
                switch(argumentProperty.getNullConvention()) {
                    case RETURN_NULL_ON_NULL:
                        methodHandleParameterTypes.add(signatureType.getJavaType());
                        break;
                    case USE_NULL_FLAG:
                        methodHandleParameterTypes.add(signatureType.getJavaType());
                        methodHandleParameterTypes.add(boolean.class);
                        break;
                    case USE_BOXED_TYPE:
                        methodHandleParameterTypes.add(Primitives.wrap(signatureType.getJavaType()));
                        break;
                    case BLOCK_AND_POSITION:
                        methodHandleParameterTypes.add(Block.class);
                        methodHandleParameterTypes.add(int.class);
                        break;
                    default:
                        throw new UnsupportedOperationException("unknown NullConvention");
                }
                break;
            case FUNCTION_TYPE:
                methodHandleParameterTypes.add(argumentProperty.getLambdaInterface());
                break;
            default:
                throw new UnsupportedOperationException("unknown ArgumentType");
        }
    }
    Class<?> methodHandleReturnType = typeManager.getType(signature.getReturnType()).getJavaType();
    if (choice.isNullable()) {
        methodHandleReturnType = Primitives.wrap(methodHandleReturnType);
    }
    return MethodType.methodType(methodHandleReturnType, methodHandleParameterTypes.build());
}
Also used : ArgumentProperty(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty) ArgumentProperty.functionTypeArgumentProperty(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty.functionTypeArgumentProperty) ArgumentProperty.valueTypeArgumentProperty(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty.valueTypeArgumentProperty) Type(io.prestosql.spi.type.Type) SqlType(io.prestosql.spi.function.SqlType) FunctionType(io.prestosql.spi.type.FunctionType) MethodType(java.lang.invoke.MethodType) ImmutableList(com.google.common.collect.ImmutableList) LongVariableConstraint(io.prestosql.spi.function.LongVariableConstraint)

Example 5 with ArgumentProperty

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

the class TryCastFunction method specialize.

@Override
public BuiltInScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, FunctionAndTypeManager functionAndTypeManager) {
    Type fromType = boundVariables.getTypeVariable("F");
    Type toType = boundVariables.getTypeVariable("T");
    Class<?> returnType = Primitives.wrap(toType.getJavaType());
    List<ArgumentProperty> argumentProperties;
    MethodHandle tryCastHandle;
    // the resulting method needs to return a boxed type
    FunctionHandle functionHandle = functionAndTypeManager.lookupCast(CAST, fromType.getTypeSignature(), toType.getTypeSignature());
    BuiltInScalarFunctionImplementation implementation = functionAndTypeManager.getBuiltInScalarFunctionImplementation(functionHandle);
    argumentProperties = ImmutableList.of(implementation.getArgumentProperty(0));
    MethodHandle coercion = implementation.getMethodHandle();
    coercion = coercion.asType(methodType(returnType, coercion.type()));
    MethodHandle exceptionHandler = dropArguments(constant(returnType, null), 0, RuntimeException.class);
    tryCastHandle = catchException(coercion, RuntimeException.class, exceptionHandler);
    return new BuiltInScalarFunctionImplementation(true, argumentProperties, tryCastHandle);
}
Also used : ArgumentProperty(io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty) MethodType.methodType(java.lang.invoke.MethodType.methodType) Type(io.prestosql.spi.type.Type) BuiltInScalarFunctionImplementation(io.prestosql.spi.function.BuiltInScalarFunctionImplementation) FunctionHandle(io.prestosql.spi.function.FunctionHandle) MethodHandle(java.lang.invoke.MethodHandle)

Aggregations

ArgumentProperty (io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty)7 Type (io.prestosql.spi.type.Type)4 ConnectorSession (io.prestosql.spi.connector.ConnectorSession)3 BuiltInScalarFunctionImplementation (io.prestosql.spi.function.BuiltInScalarFunctionImplementation)3 ArgumentProperty.valueTypeArgumentProperty (io.prestosql.spi.function.BuiltInScalarFunctionImplementation.ArgumentProperty.valueTypeArgumentProperty)3 MethodHandle (java.lang.invoke.MethodHandle)3 MethodType (java.lang.invoke.MethodType)3 ImmutableList (com.google.common.collect.ImmutableList)2 Block (io.prestosql.spi.block.Block)2 MethodType.methodType (java.lang.invoke.MethodType.methodType)2 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)1 BytecodeBlock (io.airlift.bytecode.BytecodeBlock)1 LabelNode (io.airlift.bytecode.instruction.LabelNode)1 Slice (io.airlift.slice.Slice)1 BoundVariables (io.prestosql.metadata.BoundVariables)1 CastType (io.prestosql.metadata.CastType)1 FunctionAndTypeManager (io.prestosql.metadata.FunctionAndTypeManager)1 SqlScalarFunction (io.prestosql.metadata.SqlScalarFunction)1 PageBuilder (io.prestosql.spi.PageBuilder)1 PrestoException (io.prestosql.spi.PrestoException)1