use of io.trino.type.FunctionType in project trino by trinodb.
the class ParametricScalarImplementation method specialize.
public Optional<ScalarFunctionImplementation> specialize(FunctionBinding functionBinding, FunctionDependencies functionDependencies) {
List<ScalarImplementationChoice> implementationChoices = new ArrayList<>();
for (Map.Entry<String, Class<?>> entry : specializedTypeParameters.entrySet()) {
if (!entry.getValue().isAssignableFrom(functionBinding.getTypeVariable(entry.getKey()).getJavaType())) {
return Optional.empty();
}
}
BoundSignature boundSignature = functionBinding.getBoundSignature();
if (returnNativeContainerType != Object.class && returnNativeContainerType != boundSignature.getReturnType().getJavaType()) {
return Optional.empty();
}
for (int i = 0; i < boundSignature.getArgumentTypes().size(); i++) {
if (boundSignature.getArgumentTypes().get(i) instanceof FunctionType) {
if (argumentNativeContainerTypes.get(i).isPresent()) {
return Optional.empty();
}
} else {
if (argumentNativeContainerTypes.get(i).isEmpty()) {
return Optional.empty();
}
Class<?> argumentType = 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(), functionBinding, functionDependencies);
Optional<MethodHandle> boundConstructor = choice.getConstructor().map(constructor -> {
MethodHandle result = bindDependencies(constructor, choice.getConstructorDependencies(), functionBinding, functionDependencies);
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.getReturnConvention(), choice.getArgumentConventions(), choice.getLambdaInterfaces(), boundMethodHandle.asType(javaMethodType(choice, boundSignature)), boundConstructor));
}
return Optional.of(new ChoicesScalarFunctionImplementation(boundSignature, implementationChoices));
}
use of io.trino.type.FunctionType in project trino by trinodb.
the class TestSignatureBinder method testFunction.
@Test
public void testFunction() {
Signature simple = functionSignature().returnType(BOOLEAN.getTypeSignature()).argumentTypes(functionType(INTEGER.getTypeSignature(), INTEGER.getTypeSignature())).build();
assertThat(simple).boundTo(INTEGER).fails();
assertThat(simple).boundTo(new FunctionType(ImmutableList.of(INTEGER), INTEGER)).succeeds();
// TODO: Support coercion of return type of lambda
assertThat(simple).boundTo(new FunctionType(ImmutableList.of(INTEGER), SMALLINT)).withCoercion().fails();
assertThat(simple).boundTo(new FunctionType(ImmutableList.of(INTEGER), BIGINT)).withCoercion().fails();
Signature applyTwice = functionSignature().returnType(new TypeSignature("V")).argumentTypes(new TypeSignature("T"), functionType(new TypeSignature("T"), new TypeSignature("U")), functionType(new TypeSignature("U"), new TypeSignature("V"))).typeVariableConstraints(typeVariable("T"), typeVariable("U"), typeVariable("V")).build();
assertThat(applyTwice).boundTo(INTEGER, INTEGER, INTEGER).fails();
assertThat(applyTwice).boundTo(INTEGER, new FunctionType(ImmutableList.of(INTEGER), VARCHAR), new FunctionType(ImmutableList.of(VARCHAR), DOUBLE)).produces(new BoundVariables().setTypeVariable("T", INTEGER).setTypeVariable("U", VARCHAR).setTypeVariable("V", DOUBLE));
assertThat(applyTwice).boundTo(INTEGER, new TypeSignatureProvider(functionArgumentTypes -> new FunctionType(ImmutableList.of(INTEGER), VARCHAR).getTypeSignature()), new TypeSignatureProvider(functionArgumentTypes -> new FunctionType(ImmutableList.of(VARCHAR), DOUBLE).getTypeSignature())).produces(new BoundVariables().setTypeVariable("T", INTEGER).setTypeVariable("U", VARCHAR).setTypeVariable("V", DOUBLE));
assertThat(applyTwice).boundTo(// pass function argument to non-function position of a function
new TypeSignatureProvider(functionArgumentTypes -> new FunctionType(ImmutableList.of(INTEGER), VARCHAR).getTypeSignature()), new TypeSignatureProvider(functionArgumentTypes -> new FunctionType(ImmutableList.of(INTEGER), VARCHAR).getTypeSignature()), new TypeSignatureProvider(functionArgumentTypes -> new FunctionType(ImmutableList.of(VARCHAR), DOUBLE).getTypeSignature())).fails();
assertThat(applyTwice).boundTo(new TypeSignatureProvider(functionArgumentTypes -> new FunctionType(ImmutableList.of(INTEGER), VARCHAR).getTypeSignature()), // pass non-function argument to function position of a function
INTEGER, new TypeSignatureProvider(functionArgumentTypes -> new FunctionType(ImmutableList.of(VARCHAR), DOUBLE).getTypeSignature())).fails();
Signature flatMap = functionSignature().returnType(arrayType(new TypeSignature("T"))).argumentTypes(arrayType(new TypeSignature("T")), functionType(new TypeSignature("T"), arrayType(new TypeSignature("T")))).typeVariableConstraints(typeVariable("T")).build();
assertThat(flatMap).boundTo(new ArrayType(INTEGER), new FunctionType(ImmutableList.of(INTEGER), new ArrayType(INTEGER))).produces(new BoundVariables().setTypeVariable("T", INTEGER));
Signature varargApply = functionSignature().returnType(new TypeSignature("T")).argumentTypes(new TypeSignature("T"), functionType(new TypeSignature("T"), new TypeSignature("T"))).typeVariableConstraints(typeVariable("T")).setVariableArity(true).build();
assertThat(varargApply).boundTo(INTEGER, new FunctionType(ImmutableList.of(INTEGER), INTEGER), new FunctionType(ImmutableList.of(INTEGER), INTEGER), new FunctionType(ImmutableList.of(INTEGER), INTEGER)).produces(new BoundVariables().setTypeVariable("T", INTEGER));
assertThat(varargApply).boundTo(INTEGER, new FunctionType(ImmutableList.of(INTEGER), INTEGER), new FunctionType(ImmutableList.of(INTEGER), DOUBLE), new FunctionType(ImmutableList.of(DOUBLE), DOUBLE)).fails();
Signature loop = functionSignature().returnType(new TypeSignature("T")).argumentTypes(new TypeSignature("T"), functionType(new TypeSignature("T"), new TypeSignature("T"))).typeVariableConstraints(typeVariable("T")).build();
assertThat(loop).boundTo(INTEGER, new TypeSignatureProvider(paramTypes -> new FunctionType(paramTypes, BIGINT).getTypeSignature())).fails();
assertThat(loop).boundTo(INTEGER, new TypeSignatureProvider(paramTypes -> new FunctionType(paramTypes, BIGINT).getTypeSignature())).withCoercion().produces(new BoundVariables().setTypeVariable("T", BIGINT));
// TODO: Support coercion of return type of lambda
assertThat(loop).withCoercion().boundTo(INTEGER, new TypeSignatureProvider(paramTypes -> new FunctionType(paramTypes, SMALLINT).getTypeSignature())).fails();
// TODO: Support coercion of return type of lambda
// Without coercion support for return type of lambda, the return type of lambda must be `varchar(x)` to avoid need for coercions.
Signature varcharApply = functionSignature().returnType(VARCHAR.getTypeSignature()).argumentTypes(VARCHAR.getTypeSignature(), functionType(VARCHAR.getTypeSignature(), new TypeSignature("varchar", TypeSignatureParameter.typeVariable("x")))).build();
assertThat(varcharApply).withCoercion().boundTo(createVarcharType(10), new TypeSignatureProvider(paramTypes -> new FunctionType(paramTypes, createVarcharType(1)).getTypeSignature())).succeeds();
Signature sortByKey = functionSignature().returnType(arrayType(new TypeSignature("T"))).argumentTypes(arrayType(new TypeSignature("T")), functionType(new TypeSignature("T"), new TypeSignature("E"))).typeVariableConstraints(typeVariable("T"), orderableTypeParameter("E")).build();
assertThat(sortByKey).boundTo(new ArrayType(INTEGER), new TypeSignatureProvider(paramTypes -> new FunctionType(paramTypes, VARCHAR).getTypeSignature())).produces(new BoundVariables().setTypeVariable("T", INTEGER).setTypeVariable("E", VARCHAR));
}
use of io.trino.type.FunctionType in project trino by trinodb.
the class InterpretedFunctionInvoker method invoke.
/**
* Arguments must be the native container type for the corresponding SQL types.
* <p>
* Returns a value in the native container type corresponding to the declared SQL return type
*/
public Object invoke(ResolvedFunction function, ConnectorSession session, List<Object> arguments) {
FunctionInvoker invoker = functionManager.getScalarFunctionInvoker(function, getInvocationConvention(function.getSignature(), function.getFunctionNullability()));
MethodHandle method = invoker.getMethodHandle();
List<Object> actualArguments = new ArrayList<>();
// handle function on instance method, to allow use of fields
if (invoker.getInstanceFactory().isPresent()) {
try {
actualArguments.add(invoker.getInstanceFactory().get().invoke());
} catch (Throwable throwable) {
throw propagate(throwable);
}
}
// add session
if (method.type().parameterCount() > actualArguments.size() && method.type().parameterType(actualArguments.size()) == ConnectorSession.class) {
actualArguments.add(session);
}
int lambdaArgumentIndex = 0;
for (int i = 0; i < arguments.size(); i++) {
Object argument = arguments.get(i);
// if argument is null and function does not handle nulls, result is null
if (argument == null && !function.getFunctionNullability().isArgumentNullable(i)) {
return null;
}
if (function.getSignature().getArgumentTypes().get(i) instanceof FunctionType) {
argument = asInterfaceInstance(invoker.getLambdaInterfaces().get(lambdaArgumentIndex), (MethodHandle) argument);
lambdaArgumentIndex++;
}
actualArguments.add(argument);
}
try {
return method.invokeWithArguments(actualArguments);
} catch (Throwable throwable) {
throw propagate(throwable);
}
}
use of io.trino.type.FunctionType in project trino by trinodb.
the class TestEqualityInference method testExpressionsThatMayReturnNullOnNonNullInput.
@Test
public void testExpressionsThatMayReturnNullOnNonNullInput() {
List<Expression> candidates = ImmutableList.of(// try_cast
new Cast(nameReference("b"), toSqlType(BIGINT), true), functionResolution.functionCallBuilder(QualifiedName.of(TryFunction.NAME)).addArgument(new FunctionType(ImmutableList.of(), VARCHAR), new LambdaExpression(ImmutableList.of(), nameReference("b"))).build(), new NullIfExpression(nameReference("b"), number(1)), new IfExpression(nameReference("b"), number(1), new NullLiteral()), new InPredicate(nameReference("b"), new InListExpression(ImmutableList.of(new NullLiteral()))), new SearchedCaseExpression(ImmutableList.of(new WhenClause(new IsNotNullPredicate(nameReference("b")), new NullLiteral())), Optional.empty()), new SimpleCaseExpression(nameReference("b"), ImmutableList.of(new WhenClause(number(1), new NullLiteral())), Optional.empty()), new SubscriptExpression(new ArrayConstructor(ImmutableList.of(new NullLiteral())), nameReference("b")));
for (Expression candidate : candidates) {
EqualityInference inference = EqualityInference.newInstance(metadata, equals(nameReference("b"), nameReference("x")), equals(nameReference("a"), candidate));
List<Expression> equalities = inference.generateEqualitiesPartitionedBy(symbols("b")).getScopeStraddlingEqualities();
assertEquals(equalities.size(), 1);
assertTrue(equalities.get(0).equals(equals(nameReference("x"), nameReference("b"))) || equalities.get(0).equals(equals(nameReference("b"), nameReference("x"))));
}
}
use of io.trino.type.FunctionType in project trino by trinodb.
the class TestDesugarTryExpressionRewriter method testTryExpressionDesugaringRewriter.
@Test
public void testTryExpressionDesugaringRewriter() {
// 1 + try(2)
Expression initial = new ArithmeticBinaryExpression(ADD, new DecimalLiteral("1"), new TryExpression(new DecimalLiteral("2")));
Expression rewritten = DesugarTryExpressionRewriter.rewrite(initial, tester().getMetadata(), tester().getTypeAnalyzer(), tester().getSession(), new SymbolAllocator());
// 1 + try_function(() -> 2)
Expression expected = new ArithmeticBinaryExpression(ADD, new DecimalLiteral("1"), new TestingFunctionResolution().functionCallBuilder(QualifiedName.of(TryFunction.NAME)).addArgument(new FunctionType(ImmutableList.of(), createDecimalType(1)), new LambdaExpression(ImmutableList.of(), new DecimalLiteral("2"))).build());
ExpressionVerifier verifier = new ExpressionVerifier(new SymbolAliases());
assertTrue(verifier.process(rewritten, expected));
}
Aggregations