Search in sources :

Example 1 with InvocationArgumentConvention

use of io.trino.spi.function.InvocationConvention.InvocationArgumentConvention in project trino by trinodb.

the class FunctionManager method verifyMethodHandleSignature.

private static void verifyMethodHandleSignature(BoundSignature boundSignature, FunctionInvoker functionInvoker, InvocationConvention convention) {
    MethodHandle methodHandle = functionInvoker.getMethodHandle();
    MethodType methodType = methodHandle.type();
    checkArgument(convention.getArgumentConventions().size() == boundSignature.getArgumentTypes().size(), "Expected %s arguments, but got %s", boundSignature.getArgumentTypes().size(), convention.getArgumentConventions().size());
    int expectedParameterCount = convention.getArgumentConventions().stream().mapToInt(InvocationArgumentConvention::getParameterCount).sum();
    expectedParameterCount += methodType.parameterList().stream().filter(ConnectorSession.class::equals).count();
    if (functionInvoker.getInstanceFactory().isPresent()) {
        expectedParameterCount++;
    }
    checkArgument(expectedParameterCount == methodType.parameterCount(), "Expected %s method parameters, but got %s", expectedParameterCount, methodType.parameterCount());
    int parameterIndex = 0;
    if (functionInvoker.getInstanceFactory().isPresent()) {
        verifyFunctionSignature(convention.supportsInstanceFactor(), "Method requires instance factory, but calling convention does not support an instance factory");
        MethodHandle factoryMethod = functionInvoker.getInstanceFactory().orElseThrow();
        verifyFunctionSignature(methodType.parameterType(parameterIndex).equals(factoryMethod.type().returnType()), "Invalid return type");
        parameterIndex++;
    }
    int lambdaArgumentIndex = 0;
    for (int argumentIndex = 0; argumentIndex < boundSignature.getArgumentTypes().size(); argumentIndex++) {
        // skip session parameters
        while (methodType.parameterType(parameterIndex).equals(ConnectorSession.class)) {
            verifyFunctionSignature(convention.supportsSession(), "Method requires session, but calling convention does not support session");
            parameterIndex++;
        }
        Class<?> parameterType = methodType.parameterType(parameterIndex);
        Type argumentType = boundSignature.getArgumentTypes().get(argumentIndex);
        InvocationArgumentConvention argumentConvention = convention.getArgumentConvention(argumentIndex);
        switch(argumentConvention) {
            case NEVER_NULL:
                verifyFunctionSignature(parameterType.isAssignableFrom(argumentType.getJavaType()), "Expected argument type to be %s, but is %s", argumentType, parameterType);
                break;
            case NULL_FLAG:
                verifyFunctionSignature(parameterType.isAssignableFrom(argumentType.getJavaType()), "Expected argument type to be %s, but is %s", argumentType.getJavaType(), parameterType);
                verifyFunctionSignature(methodType.parameterType(parameterIndex + 1).equals(boolean.class), "Expected null flag parameter to be followed by a boolean parameter");
                break;
            case BOXED_NULLABLE:
                verifyFunctionSignature(parameterType.isAssignableFrom(wrap(argumentType.getJavaType())), "Expected argument type to be %s, but is %s", wrap(argumentType.getJavaType()), parameterType);
                break;
            case BLOCK_POSITION:
                verifyFunctionSignature(parameterType.equals(Block.class) && methodType.parameterType(parameterIndex + 1).equals(int.class), "Expected BLOCK_POSITION argument have parameters Block and int");
                break;
            case FUNCTION:
                Class<?> lambdaInterface = functionInvoker.getLambdaInterfaces().get(lambdaArgumentIndex);
                verifyFunctionSignature(parameterType.equals(lambdaInterface), "Expected function interface to be %s, but is %s", lambdaInterface, parameterType);
                lambdaArgumentIndex++;
                break;
            default:
                throw new UnsupportedOperationException("Unknown argument convention: " + argumentConvention);
        }
        parameterIndex += argumentConvention.getParameterCount();
    }
    Type returnType = boundSignature.getReturnType();
    switch(convention.getReturnConvention()) {
        case FAIL_ON_NULL:
            verifyFunctionSignature(methodType.returnType().isAssignableFrom(returnType.getJavaType()), "Expected return type to be %s, but is %s", returnType.getJavaType(), methodType.returnType());
            break;
        case NULLABLE_RETURN:
            verifyFunctionSignature(methodType.returnType().isAssignableFrom(wrap(returnType.getJavaType())), "Expected return type to be %s, but is %s", returnType.getJavaType(), wrap(methodType.returnType()));
            break;
        default:
            throw new UnsupportedOperationException("Unknown return convention: " + convention.getReturnConvention());
    }
}
Also used : MethodType(java.lang.invoke.MethodType) Type(io.trino.spi.type.Type) MethodType(java.lang.invoke.MethodType) InvocationArgumentConvention(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention) ConnectorSession(io.trino.spi.connector.ConnectorSession) MethodHandle(java.lang.invoke.MethodHandle)

Example 2 with InvocationArgumentConvention

use of io.trino.spi.function.InvocationConvention.InvocationArgumentConvention in project trino by trinodb.

the class BytecodeUtils method generateFullInvocation.

private static BytecodeNode generateFullInvocation(Scope scope, String functionName, FunctionNullability functionNullability, List<Boolean> argumentIsFunctionType, Function<InvocationConvention, FunctionInvoker> functionInvokerProvider, Function<MethodHandle, BytecodeNode> instanceFactory, List<Function<Optional<Class<?>>, BytecodeNode>> argumentCompilers, CallSiteBinder binder) {
    verify(argumentIsFunctionType.size() == argumentCompilers.size());
    List<InvocationArgumentConvention> argumentConventions = new ArrayList<>();
    List<BytecodeNode> arguments = new ArrayList<>();
    for (int i = 0; i < argumentIsFunctionType.size(); i++) {
        if (argumentIsFunctionType.get(i)) {
            argumentConventions.add(FUNCTION);
            arguments.add(null);
        } else {
            BytecodeNode argument = argumentCompilers.get(i).apply(Optional.empty());
            argumentConventions.add(getPreferredArgumentConvention(argument, argumentCompilers.size(), functionNullability.isArgumentNullable(i)));
            arguments.add(argument);
        }
    }
    InvocationConvention invocationConvention = new InvocationConvention(argumentConventions, functionNullability.isReturnNullable() ? NULLABLE_RETURN : FAIL_ON_NULL, true, true);
    FunctionInvoker functionInvoker = functionInvokerProvider.apply(invocationConvention);
    Binding binding = binder.bind(functionInvoker.getMethodHandle());
    LabelNode end = new LabelNode("end");
    BytecodeBlock block = new BytecodeBlock().setDescription("invoke " + functionName);
    Optional<BytecodeNode> instance = functionInvoker.getInstanceFactory().map(instanceFactory);
    // Index of current parameter in the MethodHandle
    int currentParameterIndex = 0;
    // Index of parameter (without @IsNull) in Trino function
    int realParameterIndex = 0;
    // Index of function argument types
    int lambdaArgumentIndex = 0;
    MethodType methodType = binding.getType();
    Class<?> returnType = methodType.returnType();
    Class<?> unboxedReturnType = Primitives.unwrap(returnType);
    List<Class<?>> stackTypes = new ArrayList<>();
    boolean instanceIsBound = false;
    while (currentParameterIndex < methodType.parameterArray().length) {
        Class<?> type = methodType.parameterArray()[currentParameterIndex];
        stackTypes.add(type);
        if (instance.isPresent() && !instanceIsBound) {
            checkState(type.equals(functionInvoker.getInstanceFactory().get().type().returnType()), "Mismatched type for instance parameter");
            block.append(instance.get());
            instanceIsBound = true;
        } else if (type == ConnectorSession.class) {
            block.append(scope.getVariable("session"));
        } else {
            switch(invocationConvention.getArgumentConvention(realParameterIndex)) {
                case NEVER_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 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 BOXED_NULLABLE:
                    block.append(arguments.get(realParameterIndex));
                    block.append(boxPrimitiveIfNecessary(scope, type));
                    block.append(scope.getVariable("wasNull").set(constantFalse()));
                    break;
                case BLOCK_POSITION:
                    InputReferenceNode inputReferenceNode = (InputReferenceNode) arguments.get(realParameterIndex);
                    block.append(inputReferenceNode.produceBlockAndPosition());
                    stackTypes.add(int.class);
                    if (!functionNullability.isArgumentNullable(realParameterIndex)) {
                        block.append(scope.getVariable("wasNull").set(inputReferenceNode.blockAndPositionIsNull()));
                        block.append(ifWasNullPopAndGoto(scope, end, unboxedReturnType, Lists.reverse(stackTypes)));
                    }
                    currentParameterIndex++;
                    break;
                case FUNCTION:
                    Class<?> lambdaInterface = functionInvoker.getLambdaInterfaces().get(lambdaArgumentIndex);
                    block.append(argumentCompilers.get(realParameterIndex).apply(Optional.of(lambdaInterface)));
                    lambdaArgumentIndex++;
                    break;
                default:
                    throw new UnsupportedOperationException(format("Unsupported argument conventsion type: %s", invocationConvention.getArgumentConvention(realParameterIndex)));
            }
            realParameterIndex++;
        }
        currentParameterIndex++;
    }
    block.append(invoke(binding, functionName));
    if (functionNullability.isReturnNullable()) {
        block.append(unboxPrimitiveIfNecessary(scope, returnType));
    }
    block.visitLabel(end);
    return block;
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) MethodType(java.lang.invoke.MethodType) ArrayList(java.util.ArrayList) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) InputReferenceNode(io.trino.sql.gen.InputReferenceCompiler.InputReferenceNode) InvocationArgumentConvention(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention) InvocationConvention(io.trino.spi.function.InvocationConvention) BytecodeNode(io.airlift.bytecode.BytecodeNode) FunctionInvoker(io.trino.metadata.FunctionInvoker) ConnectorSession(io.trino.spi.connector.ConnectorSession)

Example 3 with InvocationArgumentConvention

use of io.trino.spi.function.InvocationConvention.InvocationArgumentConvention in project trino by trinodb.

the class ScalarFunctionAdapter method adaptParameter.

private MethodHandle adaptParameter(MethodHandle methodHandle, int parameterIndex, Type argumentType, InvocationArgumentConvention actualArgumentConvention, InvocationArgumentConvention expectedArgumentConvention, InvocationReturnConvention returnConvention) {
    if (actualArgumentConvention == expectedArgumentConvention) {
        return methodHandle;
    }
    if (actualArgumentConvention == BLOCK_POSITION) {
        throw new IllegalArgumentException("Block and position argument can not be adapted");
    }
    if (actualArgumentConvention == FUNCTION) {
        throw new IllegalArgumentException("Function argument can not be adapted");
    }
    // caller will never pass null
    if (expectedArgumentConvention == NEVER_NULL) {
        if (actualArgumentConvention == BOXED_NULLABLE) {
            // if actual argument is boxed primitive, change method handle to accept a primitive and then box to actual method
            if (isWrapperType(methodHandle.type().parameterType(parameterIndex))) {
                MethodType targetType = methodHandle.type().changeParameterType(parameterIndex, unwrap(methodHandle.type().parameterType(parameterIndex)));
                methodHandle = explicitCastArguments(methodHandle, targetType);
            }
            return methodHandle;
        }
        if (actualArgumentConvention == NULL_FLAG) {
            // actual method takes value and null flag, so change method handle to not have the flag and always pass false to the actual method
            return insertArguments(methodHandle, parameterIndex + 1, false);
        }
        throw new IllegalArgumentException("Unsupported actual argument convention: " + actualArgumentConvention);
    }
    // caller will pass Java null for SQL null
    if (expectedArgumentConvention == BOXED_NULLABLE) {
        if (actualArgumentConvention == NEVER_NULL) {
            if (nullAdaptationPolicy == UNSUPPORTED) {
                throw new IllegalArgumentException("Not null argument can not be adapted to nullable");
            }
            // box argument
            Class<?> boxedType = wrap(methodHandle.type().parameterType(parameterIndex));
            MethodType targetType = methodHandle.type().changeParameterType(parameterIndex, boxedType);
            methodHandle = explicitCastArguments(methodHandle, targetType);
            if (nullAdaptationPolicy == UNDEFINED_VALUE_FOR_NULL) {
                // currently, we just perform unboxing, which converts nulls to Java primitive default value
                return methodHandle;
            }
            if (nullAdaptationPolicy == RETURN_NULL_ON_NULL) {
                if (returnConvention == FAIL_ON_NULL) {
                    throw new IllegalArgumentException("RETURN_NULL_ON_NULL adaptation can not be used with FAIL_ON_NULL return convention");
                }
                return guardWithTest(isNullArgument(methodHandle.type(), parameterIndex), returnNull(methodHandle.type()), methodHandle);
            }
            if (nullAdaptationPolicy == THROW_ON_NULL) {
                MethodType adapterType = methodType(boxedType, boxedType);
                MethodHandle adapter = guardWithTest(isNullArgument(adapterType, 0), throwTrinoNullArgumentException(adapterType), identity(boxedType));
                return collectArguments(methodHandle, parameterIndex, adapter);
            }
        }
        if (actualArgumentConvention == NULL_FLAG) {
            // The conversion is described below in reverse order as this is how method handle adaptation works.  The provided example
            // signature is based on a boxed Long argument.
            // 3. unbox the value (if null the java default is sent)
            // long, boolean => Long, boolean
            Class<?> parameterType = methodHandle.type().parameterType(parameterIndex);
            methodHandle = explicitCastArguments(methodHandle, methodHandle.type().changeParameterType(parameterIndex, wrap(parameterType)));
            // 2. replace second argument with the result of isNull
            // long, boolean => Long, Long
            methodHandle = filterArguments(methodHandle, parameterIndex + 1, explicitCastArguments(IS_NULL_METHOD, methodType(boolean.class, wrap(parameterType))));
            // 1. Duplicate the argument, so we have two copies of the value
            // Long, Long => Long
            int[] reorder = IntStream.range(0, methodHandle.type().parameterCount()).map(i -> i <= parameterIndex ? i : i - 1).toArray();
            MethodType newType = methodHandle.type().dropParameterTypes(parameterIndex + 1, parameterIndex + 2);
            methodHandle = permuteArguments(methodHandle, newType, reorder);
            return methodHandle;
        }
        throw new IllegalArgumentException("Unsupported actual argument convention: " + actualArgumentConvention);
    }
    // caller will pass boolean true in the next argument for SQL null
    if (expectedArgumentConvention == NULL_FLAG) {
        if (actualArgumentConvention == NEVER_NULL) {
            if (nullAdaptationPolicy == UNSUPPORTED) {
                throw new IllegalArgumentException("Not null argument can not be adapted to nullable");
            }
            if (nullAdaptationPolicy == UNDEFINED_VALUE_FOR_NULL) {
                // add null flag to call
                methodHandle = dropArguments(methodHandle, parameterIndex + 1, boolean.class);
                return methodHandle;
            }
            // if caller sets null flag, return null, otherwise invoke target
            if (nullAdaptationPolicy == RETURN_NULL_ON_NULL) {
                if (returnConvention == FAIL_ON_NULL) {
                    throw new IllegalArgumentException("RETURN_NULL_ON_NULL adaptation can not be used with FAIL_ON_NULL return convention");
                }
                // add null flag to call
                methodHandle = dropArguments(methodHandle, parameterIndex + 1, boolean.class);
                return guardWithTest(isTrueNullFlag(methodHandle.type(), parameterIndex), returnNull(methodHandle.type()), methodHandle);
            }
            if (nullAdaptationPolicy == THROW_ON_NULL) {
                MethodHandle adapter = identity(methodHandle.type().parameterType(parameterIndex));
                adapter = dropArguments(adapter, 1, boolean.class);
                adapter = guardWithTest(isTrueNullFlag(adapter.type(), 0), throwTrinoNullArgumentException(adapter.type()), adapter);
                return collectArguments(methodHandle, parameterIndex, adapter);
            }
        }
        if (actualArgumentConvention == BOXED_NULLABLE) {
            return collectArguments(methodHandle, parameterIndex, boxedToNullFlagFilter(methodHandle.type().parameterType(parameterIndex)));
        }
        throw new IllegalArgumentException("Unsupported actual argument convention: " + actualArgumentConvention);
    }
    // caller will pass boolean true in the next argument for SQL null
    if (expectedArgumentConvention == BLOCK_POSITION) {
        MethodHandle getBlockValue = getBlockValue(argumentType, methodHandle.type().parameterType(parameterIndex));
        if (actualArgumentConvention == NEVER_NULL) {
            if (nullAdaptationPolicy == UNDEFINED_VALUE_FOR_NULL) {
                // Current, null is not checked, so whatever type returned is passed through
                methodHandle = collectArguments(methodHandle, parameterIndex, getBlockValue);
                return methodHandle;
            }
            if (nullAdaptationPolicy == RETURN_NULL_ON_NULL && returnConvention != FAIL_ON_NULL) {
                // if caller sets null flag, return null, otherwise invoke target
                methodHandle = collectArguments(methodHandle, parameterIndex, getBlockValue);
                return guardWithTest(isBlockPositionNull(methodHandle.type(), parameterIndex), returnNull(methodHandle.type()), methodHandle);
            }
            if (nullAdaptationPolicy == THROW_ON_NULL || nullAdaptationPolicy == UNSUPPORTED || nullAdaptationPolicy == RETURN_NULL_ON_NULL) {
                MethodHandle adapter = guardWithTest(isBlockPositionNull(getBlockValue.type(), 0), throwTrinoNullArgumentException(getBlockValue.type()), getBlockValue);
                return collectArguments(methodHandle, parameterIndex, adapter);
            }
        }
        if (actualArgumentConvention == BOXED_NULLABLE) {
            getBlockValue = explicitCastArguments(getBlockValue, getBlockValue.type().changeReturnType(wrap(getBlockValue.type().returnType())));
            getBlockValue = guardWithTest(isBlockPositionNull(getBlockValue.type(), 0), returnNull(getBlockValue.type()), getBlockValue);
            methodHandle = collectArguments(methodHandle, parameterIndex, getBlockValue);
            return methodHandle;
        }
        if (actualArgumentConvention == NULL_FLAG) {
            // long, boolean => long, Block, int
            MethodHandle isNull = isBlockPositionNull(getBlockValue.type(), 0);
            methodHandle = collectArguments(methodHandle, parameterIndex + 1, isNull);
            // long, Block, int => Block, int, Block, int
            getBlockValue = guardWithTest(isBlockPositionNull(getBlockValue.type(), 0), returnNull(getBlockValue.type()), getBlockValue);
            methodHandle = collectArguments(methodHandle, parameterIndex, getBlockValue);
            int[] reorder = IntStream.range(0, methodHandle.type().parameterCount()).map(i -> i <= parameterIndex + 1 ? i : i - 2).toArray();
            MethodType newType = methodHandle.type().dropParameterTypes(parameterIndex + 2, parameterIndex + 4);
            methodHandle = permuteArguments(methodHandle, newType, reorder);
            return methodHandle;
        }
        throw new IllegalArgumentException("Unsupported actual argument convention: " + actualArgumentConvention);
    }
    throw new IllegalArgumentException("Unsupported expected argument convention: " + expectedArgumentConvention);
}
Also used : IntStream(java.util.stream.IntStream) MethodHandles.guardWithTest(java.lang.invoke.MethodHandles.guardWithTest) MethodHandle(java.lang.invoke.MethodHandle) BLOCK_POSITION(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.BLOCK_POSITION) MethodHandles.dropArguments(java.lang.invoke.MethodHandles.dropArguments) Slice(io.airlift.slice.Slice) FAIL_ON_NULL(io.trino.spi.function.InvocationConvention.InvocationReturnConvention.FAIL_ON_NULL) RETURN_NULL_ON_NULL(io.trino.spi.function.ScalarFunctionAdapter.NullAdaptationPolicy.RETURN_NULL_ON_NULL) MethodHandles.explicitCastArguments(java.lang.invoke.MethodHandles.explicitCastArguments) MethodHandles.insertArguments(java.lang.invoke.MethodHandles.insertArguments) Type(io.trino.spi.type.Type) FUNCTION(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.FUNCTION) MethodHandles.publicLookup(java.lang.invoke.MethodHandles.publicLookup) MethodHandles.identity(java.lang.invoke.MethodHandles.identity) MethodHandles.lookup(java.lang.invoke.MethodHandles.lookup) UNDEFINED_VALUE_FOR_NULL(io.trino.spi.function.ScalarFunctionAdapter.NullAdaptationPolicy.UNDEFINED_VALUE_FOR_NULL) MethodHandles.filterReturnValue(java.lang.invoke.MethodHandles.filterReturnValue) NULL_FLAG(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.NULL_FLAG) Block(io.trino.spi.block.Block) Objects.requireNonNull(java.util.Objects.requireNonNull) InvocationArgumentConvention(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention) NULLABLE_RETURN(io.trino.spi.function.InvocationConvention.InvocationReturnConvention.NULLABLE_RETURN) MethodType.methodType(java.lang.invoke.MethodType.methodType) MethodHandles.constant(java.lang.invoke.MethodHandles.constant) BOXED_NULLABLE(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.BOXED_NULLABLE) MethodHandles.permuteArguments(java.lang.invoke.MethodHandles.permuteArguments) TrinoException(io.trino.spi.TrinoException) InvocationReturnConvention(io.trino.spi.function.InvocationConvention.InvocationReturnConvention) Objects(java.util.Objects) List(java.util.List) MethodType(java.lang.invoke.MethodType) THROW_ON_NULL(io.trino.spi.function.ScalarFunctionAdapter.NullAdaptationPolicy.THROW_ON_NULL) MethodHandles.collectArguments(java.lang.invoke.MethodHandles.collectArguments) MethodHandles.filterArguments(java.lang.invoke.MethodHandles.filterArguments) StandardErrorCode(io.trino.spi.StandardErrorCode) ErrorCodeSupplier(io.trino.spi.ErrorCodeSupplier) NEVER_NULL(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.NEVER_NULL) UNSUPPORTED(io.trino.spi.function.ScalarFunctionAdapter.NullAdaptationPolicy.UNSUPPORTED) MethodHandles.throwException(java.lang.invoke.MethodHandles.throwException) MethodType(java.lang.invoke.MethodType) MethodHandle(java.lang.invoke.MethodHandle)

Example 4 with InvocationArgumentConvention

use of io.trino.spi.function.InvocationConvention.InvocationArgumentConvention in project trino by trinodb.

the class TestScalarFunctionAdapter method verifyAllAdaptations.

private static void verifyAllAdaptations(InvocationConvention actualConvention, MethodHandle methodHandle, NullAdaptationPolicy nullAdaptationPolicy, List<Type> argumentTypes) throws Throwable {
    List<List<InvocationArgumentConvention>> allArgumentConventions = allCombinations(ImmutableList.of(NEVER_NULL, BOXED_NULLABLE, NULL_FLAG, BLOCK_POSITION), argumentTypes.size());
    for (List<InvocationArgumentConvention> argumentConventions : allArgumentConventions) {
        for (InvocationReturnConvention returnConvention : InvocationReturnConvention.values()) {
            InvocationConvention expectedConvention = new InvocationConvention(argumentConventions, returnConvention, false, true);
            adaptAndVerify(methodHandle, actualConvention, expectedConvention, nullAdaptationPolicy, argumentTypes);
        }
    }
}
Also used : InvocationReturnConvention(io.trino.spi.function.InvocationConvention.InvocationReturnConvention) InvocationArgumentConvention(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) List(java.util.List) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList)

Example 5 with InvocationArgumentConvention

use of io.trino.spi.function.InvocationConvention.InvocationArgumentConvention in project trino by trinodb.

the class TestScalarFunctionAdapter method hasNullableToNoNullableAdaptation.

private static boolean hasNullableToNoNullableAdaptation(InvocationConvention actualConvention, InvocationConvention expectedConvention) {
    for (int i = 0; i < actualConvention.getArgumentConventions().size(); i++) {
        InvocationArgumentConvention actualArgumentConvention = actualConvention.getArgumentConvention(i);
        InvocationArgumentConvention expectedArgumentConvention = expectedConvention.getArgumentConvention(i);
        if (actualArgumentConvention == NEVER_NULL && (expectedArgumentConvention == BOXED_NULLABLE || expectedArgumentConvention == NULL_FLAG)) {
            // this conversion is not allowed
            return true;
        }
    }
    return false;
}
Also used : InvocationArgumentConvention(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention)

Aggregations

InvocationArgumentConvention (io.trino.spi.function.InvocationConvention.InvocationArgumentConvention)14 Type (io.trino.spi.type.Type)8 MethodType (java.lang.invoke.MethodType)7 MethodHandle (java.lang.invoke.MethodHandle)4 MethodType.methodType (java.lang.invoke.MethodType.methodType)4 ArrayList (java.util.ArrayList)4 ConnectorSession (io.trino.spi.connector.ConnectorSession)3 ArrayType (io.trino.spi.type.ArrayType)3 ImmutableList (com.google.common.collect.ImmutableList)2 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)2 LongVariableConstraint (io.trino.metadata.LongVariableConstraint)2 TrinoException (io.trino.spi.TrinoException)2 InvocationConvention (io.trino.spi.function.InvocationConvention)2 InvocationReturnConvention (io.trino.spi.function.InvocationConvention.InvocationReturnConvention)2 CharType (io.trino.spi.type.CharType)2 CharType.createCharType (io.trino.spi.type.CharType.createCharType)2 TimestampType (io.trino.spi.type.TimestampType)2 TimestampType.createTimestampType (io.trino.spi.type.TimestampType.createTimestampType)2 List (java.util.List)2 BytecodeBlock (io.airlift.bytecode.BytecodeBlock)1