Search in sources :

Example 1 with FAIL_ON_NULL

use of io.trino.spi.function.InvocationConvention.InvocationReturnConvention.FAIL_ON_NULL 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 2 with FAIL_ON_NULL

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

the class FormatFunction method valueConverter.

private static BiFunction<ConnectorSession, Block, Object> valueConverter(FunctionDependencies functionDependencies, Type type, int position) {
    if (type.equals(UNKNOWN)) {
        return (session, block) -> null;
    }
    if (type.equals(BOOLEAN)) {
        return (session, block) -> type.getBoolean(block, position);
    }
    if (type.equals(TINYINT) || type.equals(SMALLINT) || type.equals(INTEGER) || type.equals(BIGINT)) {
        return (session, block) -> type.getLong(block, position);
    }
    if (type.equals(REAL)) {
        return (session, block) -> intBitsToFloat(toIntExact(type.getLong(block, position)));
    }
    if (type.equals(DOUBLE)) {
        return (session, block) -> type.getDouble(block, position);
    }
    if (type.equals(DATE)) {
        return (session, block) -> LocalDate.ofEpochDay(type.getLong(block, position));
    }
    if (type instanceof TimestampWithTimeZoneType) {
        return (session, block) -> toZonedDateTime(((TimestampWithTimeZoneType) type), block, position);
    }
    if (type instanceof TimestampType) {
        return (session, block) -> toLocalDateTime(((TimestampType) type), block, position);
    }
    if (type instanceof TimeType) {
        return (session, block) -> toLocalTime(type.getLong(block, position));
    }
    // TODO: support TIME WITH TIME ZONE by https://github.com/trinodb/trino/issues/191 + mapping to java.time.OffsetTime
    if (type.equals(JSON)) {
        MethodHandle handle = functionDependencies.getFunctionInvoker(QualifiedName.of("json_format"), ImmutableList.of(JSON), simpleConvention(FAIL_ON_NULL, NEVER_NULL)).getMethodHandle();
        return (session, block) -> convertToString(handle, type.getSlice(block, position));
    }
    if (isShortDecimal(type)) {
        int scale = ((DecimalType) type).getScale();
        return (session, block) -> BigDecimal.valueOf(type.getLong(block, position), scale);
    }
    if (isLongDecimal(type)) {
        int scale = ((DecimalType) type).getScale();
        return (session, block) -> new BigDecimal(((Int128) type.getObject(block, position)).toBigInteger(), scale);
    }
    if (type instanceof VarcharType) {
        return (session, block) -> type.getSlice(block, position).toStringUtf8();
    }
    if (type instanceof CharType) {
        CharType charType = (CharType) type;
        return (session, block) -> padSpaces(type.getSlice(block, position), charType).toStringUtf8();
    }
    BiFunction<ConnectorSession, Block, Object> function;
    if (type.getJavaType() == long.class) {
        function = (session, block) -> type.getLong(block, position);
    } else if (type.getJavaType() == double.class) {
        function = (session, block) -> type.getDouble(block, position);
    } else if (type.getJavaType() == boolean.class) {
        function = (session, block) -> type.getBoolean(block, position);
    } else if (type.getJavaType() == Slice.class) {
        function = (session, block) -> type.getSlice(block, position);
    } else {
        function = (session, block) -> type.getObject(block, position);
    }
    MethodHandle handle = functionDependencies.getCastInvoker(type, VARCHAR, simpleConvention(FAIL_ON_NULL, NEVER_NULL)).getMethodHandle();
    return (session, block) -> convertToString(handle, function.apply(session, block));
}
Also used : FunctionDependencies(io.trino.metadata.FunctionDependencies) SCALAR(io.trino.metadata.FunctionKind.SCALAR) FunctionDependencyDeclarationBuilder(io.trino.metadata.FunctionDependencyDeclaration.FunctionDependencyDeclarationBuilder) FAIL_ON_NULL(io.trino.spi.function.InvocationConvention.InvocationReturnConvention.FAIL_ON_NULL) BiFunction(java.util.function.BiFunction) FunctionNullability(io.trino.metadata.FunctionNullability) UNKNOWN(io.trino.type.UnknownType.UNKNOWN) InvocationConvention.simpleConvention(io.trino.spi.function.InvocationConvention.simpleConvention) Timestamps.roundDiv(io.trino.spi.type.Timestamps.roundDiv) BigDecimal(java.math.BigDecimal) TimestampWithTimeZoneType(io.trino.spi.type.TimestampWithTimeZoneType) Block(io.trino.spi.block.Block) LocalTime(java.time.LocalTime) IllegalFormatException(java.util.IllegalFormatException) Slices.utf8Slice(io.airlift.slice.Slices.utf8Slice) INTEGER(io.trino.spi.type.IntegerType.INTEGER) FunctionMetadata(io.trino.metadata.FunctionMetadata) SMALLINT(io.trino.spi.type.SmallintType.SMALLINT) TypeSignature(io.trino.spi.type.TypeSignature) DateTimes.toLocalDateTime(io.trino.type.DateTimes.toLocalDateTime) FunctionDependencyDeclaration(io.trino.metadata.FunctionDependencyDeclaration) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) PICOSECONDS_PER_NANOSECOND(io.trino.type.DateTimes.PICOSECONDS_PER_NANOSECOND) TrinoException(io.trino.spi.TrinoException) String.format(java.lang.String.format) List(java.util.List) BIGINT(io.trino.spi.type.BigintType.BIGINT) INVALID_FUNCTION_ARGUMENT(io.trino.spi.StandardErrorCode.INVALID_FUNCTION_ARGUMENT) LocalDate(java.time.LocalDate) DecimalType(io.trino.spi.type.DecimalType) NEVER_NULL(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.NEVER_NULL) DATE(io.trino.spi.type.DateType.DATE) REAL(io.trino.spi.type.RealType.REAL) MethodHandle(java.lang.invoke.MethodHandle) Slice(io.airlift.slice.Slice) TimeType(io.trino.spi.type.TimeType) Decimals.isLongDecimal(io.trino.spi.type.Decimals.isLongDecimal) Type(io.trino.spi.type.Type) BOOLEAN(io.trino.spi.type.BooleanType.BOOLEAN) Float.intBitsToFloat(java.lang.Float.intBitsToFloat) DateTimes.toZonedDateTime(io.trino.type.DateTimes.toZonedDateTime) TimestampType(io.trino.spi.type.TimestampType) VarcharType(io.trino.spi.type.VarcharType) VARCHAR(io.trino.spi.type.VarcharType.VARCHAR) ImmutableList(com.google.common.collect.ImmutableList) Chars.padSpaces(io.trino.spi.type.Chars.padSpaces) Math.toIntExact(java.lang.Math.toIntExact) Signature(io.trino.metadata.Signature) Decimals.isShortDecimal(io.trino.spi.type.Decimals.isShortDecimal) Int128(io.trino.spi.type.Int128) Streams.mapWithIndex(com.google.common.collect.Streams.mapWithIndex) ConnectorSession(io.trino.spi.connector.ConnectorSession) Signature.withVariadicBound(io.trino.metadata.Signature.withVariadicBound) UsedByGeneratedCode(io.trino.annotation.UsedByGeneratedCode) SqlScalarFunction(io.trino.metadata.SqlScalarFunction) Failures.internalError(io.trino.util.Failures.internalError) QualifiedName(io.trino.sql.tree.QualifiedName) DOUBLE(io.trino.spi.type.DoubleType.DOUBLE) CharType(io.trino.spi.type.CharType) BoundSignature(io.trino.metadata.BoundSignature) TINYINT(io.trino.spi.type.TinyintType.TINYINT) JSON(io.trino.type.JsonType.JSON) Reflection.methodHandle(io.trino.util.Reflection.methodHandle) VarcharType(io.trino.spi.type.VarcharType) BigDecimal(java.math.BigDecimal) TimeType(io.trino.spi.type.TimeType) Slices.utf8Slice(io.airlift.slice.Slices.utf8Slice) Slice(io.airlift.slice.Slice) TimestampWithTimeZoneType(io.trino.spi.type.TimestampWithTimeZoneType) TimestampType(io.trino.spi.type.TimestampType) DecimalType(io.trino.spi.type.DecimalType) Block(io.trino.spi.block.Block) ConnectorSession(io.trino.spi.connector.ConnectorSession) CharType(io.trino.spi.type.CharType) MethodHandle(java.lang.invoke.MethodHandle)

Example 3 with FAIL_ON_NULL

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

the class TestPolymorphicScalarFunction method testSelectsMultipleChoiceWithBlockPosition.

@Test
public void testSelectsMultipleChoiceWithBlockPosition() throws Throwable {
    Signature signature = Signature.builder().operatorType(IS_DISTINCT_FROM).argumentTypes(DECIMAL_SIGNATURE, DECIMAL_SIGNATURE).returnType(BOOLEAN.getTypeSignature()).build();
    SqlScalarFunction function = new PolymorphicScalarFunctionBuilder(TestMethods.class).signature(signature).argumentNullability(true, true).deterministic(true).choice(choice -> choice.argumentProperties(NULL_FLAG, NULL_FLAG).implementation(methodsGroup -> methodsGroup.methods("shortShort", "longLong"))).choice(choice -> choice.argumentProperties(BLOCK_POSITION, BLOCK_POSITION).implementation(methodsGroup -> methodsGroup.methodWithExplicitJavaTypes("blockPositionLongLong", asList(Optional.of(Int128.class), Optional.of(Int128.class))).methodWithExplicitJavaTypes("blockPositionShortShort", asList(Optional.of(long.class), Optional.of(long.class))))).build();
    BoundSignature shortDecimalBoundSignature = new BoundSignature(signature.getName(), BOOLEAN, ImmutableList.of(SHORT_DECIMAL_BOUND_TYPE, SHORT_DECIMAL_BOUND_TYPE));
    ChoicesScalarFunctionImplementation functionImplementation = (ChoicesScalarFunctionImplementation) function.specialize(shortDecimalBoundSignature, new FunctionDependencies(FUNCTION_MANAGER::getScalarFunctionInvoker, ImmutableMap.of(), ImmutableSet.of()));
    assertEquals(functionImplementation.getChoices().size(), 2);
    assertEquals(functionImplementation.getChoices().get(0).getInvocationConvention(), new InvocationConvention(ImmutableList.of(NULL_FLAG, NULL_FLAG), FAIL_ON_NULL, false, false));
    assertEquals(functionImplementation.getChoices().get(1).getInvocationConvention(), new InvocationConvention(ImmutableList.of(BLOCK_POSITION, BLOCK_POSITION), FAIL_ON_NULL, false, false));
    Block block1 = new LongArrayBlock(0, Optional.empty(), new long[0]);
    Block block2 = new LongArrayBlock(0, Optional.empty(), new long[0]);
    assertFalse((boolean) functionImplementation.getChoices().get(1).getMethodHandle().invoke(block1, 0, block2, 0));
    BoundSignature longDecimalBoundSignature = new BoundSignature(signature.getName(), BOOLEAN, ImmutableList.of(LONG_DECIMAL_BOUND_TYPE, LONG_DECIMAL_BOUND_TYPE));
    functionImplementation = (ChoicesScalarFunctionImplementation) function.specialize(longDecimalBoundSignature, new FunctionDependencies(FUNCTION_MANAGER::getScalarFunctionInvoker, ImmutableMap.of(), ImmutableSet.of()));
    assertTrue((boolean) functionImplementation.getChoices().get(1).getMethodHandle().invoke(block1, 0, block2, 0));
}
Also used : VARCHAR_TO_VARCHAR_RETURN_VALUE(io.trino.metadata.TestPolymorphicScalarFunction.TestMethods.VARCHAR_TO_VARCHAR_RETURN_VALUE) BLOCK_POSITION(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.BLOCK_POSITION) Slice(io.airlift.slice.Slice) FAIL_ON_NULL(io.trino.spi.function.InvocationConvention.InvocationReturnConvention.FAIL_ON_NULL) MAX_SHORT_PRECISION(io.trino.spi.type.Decimals.MAX_SHORT_PRECISION) TypeSignatureParameter.typeVariable(io.trino.spi.type.TypeSignatureParameter.typeVariable) BOOLEAN(io.trino.spi.type.BooleanType.BOOLEAN) Assert.assertEquals(org.testng.Assert.assertEquals) ChoicesScalarFunctionImplementation(io.trino.operator.scalar.ChoicesScalarFunctionImplementation) Test(org.testng.annotations.Test) IS_DISTINCT_FROM(io.trino.spi.function.OperatorType.IS_DISTINCT_FROM) FunctionManager.createTestingFunctionManager(io.trino.metadata.FunctionManager.createTestingFunctionManager) VARCHAR(io.trino.spi.type.VarcharType.VARCHAR) ImmutableList(com.google.common.collect.ImmutableList) NULL_FLAG(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.NULL_FLAG) Assertions.assertThatThrownBy(org.assertj.core.api.Assertions.assertThatThrownBy) Block(io.trino.spi.block.Block) Arrays.asList(java.util.Arrays.asList) Slices(io.airlift.slice.Slices) LongArrayBlock(io.trino.spi.block.LongArrayBlock) Assert.assertFalse(org.testng.Assert.assertFalse) TypeSignature(io.trino.spi.type.TypeSignature) Int128(io.trino.spi.type.Int128) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Signature.comparableWithVariadicBound(io.trino.metadata.Signature.comparableWithVariadicBound) VARCHAR_TO_BIGINT_RETURN_VALUE(io.trino.metadata.TestPolymorphicScalarFunction.TestMethods.VARCHAR_TO_BIGINT_RETURN_VALUE) InvocationConvention(io.trino.spi.function.InvocationConvention) ADD(io.trino.spi.function.OperatorType.ADD) BIGINT(io.trino.spi.type.BigintType.BIGINT) Optional(java.util.Optional) Assert.assertTrue(org.testng.Assert.assertTrue) VarcharType.createVarcharType(io.trino.spi.type.VarcharType.createVarcharType) DecimalType(io.trino.spi.type.DecimalType) LongArrayBlock(io.trino.spi.block.LongArrayBlock) TypeSignature(io.trino.spi.type.TypeSignature) InvocationConvention(io.trino.spi.function.InvocationConvention) Block(io.trino.spi.block.Block) LongArrayBlock(io.trino.spi.block.LongArrayBlock) ChoicesScalarFunctionImplementation(io.trino.operator.scalar.ChoicesScalarFunctionImplementation) Test(org.testng.annotations.Test)

Example 4 with FAIL_ON_NULL

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

the class RowType method getDistinctFromOperatorInvokers.

private static List<OperatorMethodHandle> getDistinctFromOperatorInvokers(TypeOperators typeOperators, List<Field> fields) {
    boolean comparable = fields.stream().allMatch(field -> field.getType().isComparable());
    if (!comparable) {
        return emptyList();
    }
    // for large rows, use a generic loop with a megamorphic call site
    if (fields.size() > MEGAMORPHIC_FIELD_COUNT) {
        List<MethodHandle> distinctFromOperators = fields.stream().map(field -> typeOperators.getDistinctFromOperator(field.getType(), simpleConvention(FAIL_ON_NULL, BLOCK_POSITION, BLOCK_POSITION))).collect(toUnmodifiableList());
        return singletonList(new OperatorMethodHandle(DISTINCT_FROM_CONVENTION, DISTINCT_FROM.bindTo(distinctFromOperators)));
    }
    // (Block, Block):boolean
    MethodHandle distinctFrom = dropArguments(constant(boolean.class, false), 0, Block.class, Block.class);
    for (int fieldId = 0; fieldId < fields.size(); fieldId++) {
        Field field = fields.get(fieldId);
        // (Block, Block, int, MethodHandle, Block, Block):boolean
        distinctFrom = collectArguments(CHAIN_DISTINCT_FROM, 0, distinctFrom);
        // field distinctFrom
        MethodHandle fieldDistinctFromOperator = typeOperators.getDistinctFromOperator(field.getType(), simpleConvention(FAIL_ON_NULL, BLOCK_POSITION, BLOCK_POSITION));
        // (Block, Block, Block, Block):boolean
        distinctFrom = insertArguments(distinctFrom, 2, fieldId, fieldDistinctFromOperator);
        // (Block, Block):boolean
        distinctFrom = permuteArguments(distinctFrom, methodType(boolean.class, Block.class, Block.class), 0, 1, 0, 1);
    }
    distinctFrom = CHAIN_DISTINCT_FROM_START.bindTo(distinctFrom);
    return singletonList(new OperatorMethodHandle(DISTINCT_FROM_CONVENTION, distinctFrom));
}
Also used : MethodHandle(java.lang.invoke.MethodHandle) Arrays(java.util.Arrays) BLOCK_POSITION(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.BLOCK_POSITION) MethodHandles.dropArguments(java.lang.invoke.MethodHandles.dropArguments) ROW(io.trino.spi.type.StandardTypes.ROW) FAIL_ON_NULL(io.trino.spi.function.InvocationConvention.InvocationReturnConvention.FAIL_ON_NULL) BiFunction(java.util.function.BiFunction) MethodHandles.insertArguments(java.lang.invoke.MethodHandles.insertArguments) InvocationConvention.simpleConvention(io.trino.spi.function.InvocationConvention.simpleConvention) Function(java.util.function.Function) MethodHandles.lookup(java.lang.invoke.MethodHandles.lookup) OperatorMethodHandle(io.trino.spi.function.OperatorMethodHandle) ArrayList(java.util.ArrayList) Collections.singletonList(java.util.Collections.singletonList) Collectors.toUnmodifiableList(java.util.stream.Collectors.toUnmodifiableList) Lookup(java.lang.invoke.MethodHandles.Lookup) Block(io.trino.spi.block.Block) Objects.requireNonNull(java.util.Objects.requireNonNull) NULL_HASH_CODE(io.trino.spi.type.TypeUtils.NULL_HASH_CODE) NULLABLE_RETURN(io.trino.spi.function.InvocationConvention.InvocationReturnConvention.NULLABLE_RETURN) MethodType.methodType(java.lang.invoke.MethodType.methodType) FALSE(java.lang.Boolean.FALSE) MethodHandles.constant(java.lang.invoke.MethodHandles.constant) BlockBuilderStatus(io.trino.spi.block.BlockBuilderStatus) Collections.emptyList(java.util.Collections.emptyList) BOXED_NULLABLE(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.BOXED_NULLABLE) MethodHandles.permuteArguments(java.lang.invoke.MethodHandles.permuteArguments) TrinoException(io.trino.spi.TrinoException) ConnectorSession(io.trino.spi.connector.ConnectorSession) List(java.util.List) InvocationConvention(io.trino.spi.function.InvocationConvention) MethodHandles.collectArguments(java.lang.invoke.MethodHandles.collectArguments) StandardErrorCode(io.trino.spi.StandardErrorCode) Optional(java.util.Optional) BlockBuilder(io.trino.spi.block.BlockBuilder) RowBlockBuilder(io.trino.spi.block.RowBlockBuilder) Collections(java.util.Collections) TRUE(java.lang.Boolean.TRUE) NEVER_NULL(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.NEVER_NULL) OperatorMethodHandle(io.trino.spi.function.OperatorMethodHandle) MethodHandle(java.lang.invoke.MethodHandle) OperatorMethodHandle(io.trino.spi.function.OperatorMethodHandle)

Example 5 with FAIL_ON_NULL

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

the class RowType method getComparisonOperatorInvokers.

private static List<OperatorMethodHandle> getComparisonOperatorInvokers(BiFunction<Type, InvocationConvention, MethodHandle> comparisonOperatorFactory, List<Field> fields) {
    boolean orderable = fields.stream().allMatch(field -> field.getType().isOrderable());
    if (!orderable) {
        return emptyList();
    }
    // for large rows, use a generic loop with a megamorphic call site
    if (fields.size() > MEGAMORPHIC_FIELD_COUNT) {
        List<MethodHandle> comparisonOperators = fields.stream().map(field -> comparisonOperatorFactory.apply(field.getType(), simpleConvention(FAIL_ON_NULL, BLOCK_POSITION, BLOCK_POSITION))).collect(toUnmodifiableList());
        return singletonList(new OperatorMethodHandle(COMPARISON_CONVENTION, COMPARISON.bindTo(comparisonOperators)));
    }
    // (Block, Block):Boolean
    MethodHandle comparison = dropArguments(constant(long.class, 0), 0, Block.class, Block.class);
    for (int fieldId = 0; fieldId < fields.size(); fieldId++) {
        Field field = fields.get(fieldId);
        // (Block, Block, int, MethodHandle, Block, Block):Boolean
        comparison = collectArguments(CHAIN_COMPARISON, 0, comparison);
        // field comparison
        MethodHandle fieldComparisonOperator = comparisonOperatorFactory.apply(field.getType(), simpleConvention(FAIL_ON_NULL, BLOCK_POSITION, BLOCK_POSITION));
        // (Block, Block, Block, Block):Boolean
        comparison = insertArguments(comparison, 2, fieldId, fieldComparisonOperator);
        // (Block, Block):Boolean
        comparison = permuteArguments(comparison, methodType(long.class, Block.class, Block.class), 0, 1, 0, 1);
    }
    return singletonList(new OperatorMethodHandle(COMPARISON_CONVENTION, comparison));
}
Also used : MethodHandle(java.lang.invoke.MethodHandle) Arrays(java.util.Arrays) BLOCK_POSITION(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.BLOCK_POSITION) MethodHandles.dropArguments(java.lang.invoke.MethodHandles.dropArguments) ROW(io.trino.spi.type.StandardTypes.ROW) FAIL_ON_NULL(io.trino.spi.function.InvocationConvention.InvocationReturnConvention.FAIL_ON_NULL) BiFunction(java.util.function.BiFunction) MethodHandles.insertArguments(java.lang.invoke.MethodHandles.insertArguments) InvocationConvention.simpleConvention(io.trino.spi.function.InvocationConvention.simpleConvention) Function(java.util.function.Function) MethodHandles.lookup(java.lang.invoke.MethodHandles.lookup) OperatorMethodHandle(io.trino.spi.function.OperatorMethodHandle) ArrayList(java.util.ArrayList) Collections.singletonList(java.util.Collections.singletonList) Collectors.toUnmodifiableList(java.util.stream.Collectors.toUnmodifiableList) Lookup(java.lang.invoke.MethodHandles.Lookup) Block(io.trino.spi.block.Block) Objects.requireNonNull(java.util.Objects.requireNonNull) NULL_HASH_CODE(io.trino.spi.type.TypeUtils.NULL_HASH_CODE) NULLABLE_RETURN(io.trino.spi.function.InvocationConvention.InvocationReturnConvention.NULLABLE_RETURN) MethodType.methodType(java.lang.invoke.MethodType.methodType) FALSE(java.lang.Boolean.FALSE) MethodHandles.constant(java.lang.invoke.MethodHandles.constant) BlockBuilderStatus(io.trino.spi.block.BlockBuilderStatus) Collections.emptyList(java.util.Collections.emptyList) BOXED_NULLABLE(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.BOXED_NULLABLE) MethodHandles.permuteArguments(java.lang.invoke.MethodHandles.permuteArguments) TrinoException(io.trino.spi.TrinoException) ConnectorSession(io.trino.spi.connector.ConnectorSession) List(java.util.List) InvocationConvention(io.trino.spi.function.InvocationConvention) MethodHandles.collectArguments(java.lang.invoke.MethodHandles.collectArguments) StandardErrorCode(io.trino.spi.StandardErrorCode) Optional(java.util.Optional) BlockBuilder(io.trino.spi.block.BlockBuilder) RowBlockBuilder(io.trino.spi.block.RowBlockBuilder) Collections(java.util.Collections) TRUE(java.lang.Boolean.TRUE) NEVER_NULL(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.NEVER_NULL) OperatorMethodHandle(io.trino.spi.function.OperatorMethodHandle) MethodHandle(java.lang.invoke.MethodHandle) OperatorMethodHandle(io.trino.spi.function.OperatorMethodHandle)

Aggregations

FAIL_ON_NULL (io.trino.spi.function.InvocationConvention.InvocationReturnConvention.FAIL_ON_NULL)8 NEVER_NULL (io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.NEVER_NULL)7 MethodHandle (java.lang.invoke.MethodHandle)7 List (java.util.List)7 Block (io.trino.spi.block.Block)6 InvocationConvention.simpleConvention (io.trino.spi.function.InvocationConvention.simpleConvention)6 TrinoException (io.trino.spi.TrinoException)5 BLOCK_POSITION (io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.BLOCK_POSITION)5 StandardErrorCode (io.trino.spi.StandardErrorCode)4 ConnectorSession (io.trino.spi.connector.ConnectorSession)4 InvocationConvention (io.trino.spi.function.InvocationConvention)4 BOXED_NULLABLE (io.trino.spi.function.InvocationConvention.InvocationArgumentConvention.BOXED_NULLABLE)4 NULLABLE_RETURN (io.trino.spi.function.InvocationConvention.InvocationReturnConvention.NULLABLE_RETURN)4 MethodHandles.collectArguments (java.lang.invoke.MethodHandles.collectArguments)4 MethodHandles.constant (java.lang.invoke.MethodHandles.constant)4 MethodHandles.dropArguments (java.lang.invoke.MethodHandles.dropArguments)4 MethodHandles.insertArguments (java.lang.invoke.MethodHandles.insertArguments)4 MethodHandles.lookup (java.lang.invoke.MethodHandles.lookup)4 MethodHandles.permuteArguments (java.lang.invoke.MethodHandles.permuteArguments)4 MethodType.methodType (java.lang.invoke.MethodType.methodType)4