use of io.trino.spi.function.InvocationConvention.InvocationArgumentConvention in project trino by trinodb.
the class TestScalarFunctionAdapter method toCallArgumentTypes.
private static List<Class<?>> toCallArgumentTypes(InvocationConvention callingConvention, List<Type> argumentTypes) {
List<Class<?>> expectedArguments = new ArrayList<>();
for (int i = 0; i < callingConvention.getArgumentConventions().size(); i++) {
Type argumentType = argumentTypes.get(i);
InvocationArgumentConvention argumentConvention = callingConvention.getArgumentConvention(i);
Class<?> javaType = argumentType.getJavaType();
if (argumentType.equals(CHAR_TYPE) || argumentType.equals(TIMESTAMP_TYPE)) {
javaType = Object.class;
}
switch(argumentConvention) {
case NEVER_NULL:
expectedArguments.add(javaType);
break;
case BOXED_NULLABLE:
expectedArguments.add(Primitives.wrap(javaType));
break;
case NULL_FLAG:
expectedArguments.add(javaType);
expectedArguments.add(boolean.class);
break;
case BLOCK_POSITION:
expectedArguments.add(Block.class);
expectedArguments.add(int.class);
break;
default:
throw new IllegalArgumentException("Unsupported argument convention: " + argumentConvention);
}
}
return expectedArguments;
}
use of io.trino.spi.function.InvocationConvention.InvocationArgumentConvention in project trino by trinodb.
the class ParametricScalarImplementation method javaMethodType.
private static MethodType javaMethodType(ParametricScalarImplementationChoice choice, BoundSignature signature) {
// 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<InvocationArgumentConvention> argumentConventions = choice.getArgumentConventions();
int lambdaArgumentIndex = 0;
for (int i = 0; i < argumentConventions.size(); i++) {
InvocationArgumentConvention argumentConvention = argumentConventions.get(i);
Type signatureType = signature.getArgumentTypes().get(i);
switch(argumentConvention) {
case NEVER_NULL:
methodHandleParameterTypes.add(signatureType.getJavaType());
break;
case NULL_FLAG:
methodHandleParameterTypes.add(signatureType.getJavaType());
methodHandleParameterTypes.add(boolean.class);
break;
case BOXED_NULLABLE:
methodHandleParameterTypes.add(Primitives.wrap(signatureType.getJavaType()));
break;
case BLOCK_POSITION:
methodHandleParameterTypes.add(Block.class);
methodHandleParameterTypes.add(int.class);
break;
case FUNCTION:
methodHandleParameterTypes.add(choice.getLambdaInterfaces().get(lambdaArgumentIndex));
lambdaArgumentIndex++;
break;
default:
throw new UnsupportedOperationException("unknown argument convention: " + argumentConvention);
}
}
Class<?> methodHandleReturnType = signature.getReturnType().getJavaType();
if (choice.getReturnConvention().isNullable()) {
methodHandleReturnType = Primitives.wrap(methodHandleReturnType);
}
return MethodType.methodType(methodHandleReturnType, methodHandleParameterTypes.build());
}
use of io.trino.spi.function.InvocationConvention.InvocationArgumentConvention in project trino by trinodb.
the class ParametricScalarImplementation method matches.
private static boolean matches(List<Boolean> argumentNullability, List<InvocationArgumentConvention> argumentConventions) {
if (argumentNullability.size() != argumentConventions.size()) {
return false;
}
for (int i = 0; i < argumentNullability.size(); i++) {
boolean expectedNullable = argumentNullability.get(i);
InvocationArgumentConvention argumentConvention = argumentConventions.get(i);
if (argumentConvention == FUNCTION) {
// functions are never null
if (expectedNullable) {
return false;
}
} else {
// block and position can be nullable or not
if (argumentConvention != BLOCK_POSITION) {
if (expectedNullable != argumentConvention.isNullable()) {
return false;
}
}
}
}
return true;
}
use of io.trino.spi.function.InvocationConvention.InvocationArgumentConvention in project trino by trinodb.
the class ScalarFunctionAdapter method canAdapt.
/**
* Can the actual calling convention of a method be converted to the expected calling convention?
*/
public boolean canAdapt(InvocationConvention actualConvention, InvocationConvention expectedConvention) {
requireNonNull(actualConvention, "actualConvention is null");
requireNonNull(expectedConvention, "expectedConvention is null");
if (actualConvention.getArgumentConventions().size() != expectedConvention.getArgumentConventions().size()) {
throw new IllegalArgumentException("Actual and expected conventions have different number of arguments");
}
if (actualConvention.supportsSession() && !expectedConvention.supportsSession()) {
return false;
}
if (actualConvention.supportsInstanceFactor() && !expectedConvention.supportsInstanceFactor()) {
return false;
}
if (!canAdaptReturn(actualConvention.getReturnConvention(), expectedConvention.getReturnConvention())) {
return false;
}
for (int argumentIndex = 0; argumentIndex < actualConvention.getArgumentConventions().size(); argumentIndex++) {
InvocationArgumentConvention actualArgumentConvention = actualConvention.getArgumentConvention(argumentIndex);
InvocationArgumentConvention expectedArgumentConvention = expectedConvention.getArgumentConvention(argumentIndex);
if (!canAdaptParameter(actualArgumentConvention, expectedArgumentConvention, expectedConvention.getReturnConvention())) {
return false;
}
}
return true;
}
use of io.trino.spi.function.InvocationConvention.InvocationArgumentConvention in project trino by trinodb.
the class ScalarFunctionAdapter method adapt.
/**
* Adapt the method handle from the actual calling convention of a method be converted to the expected calling convention?
*/
public MethodHandle adapt(MethodHandle methodHandle, List<Type> actualArgumentTypes, InvocationConvention actualConvention, InvocationConvention expectedConvention) {
requireNonNull(methodHandle, "methodHandle is null");
requireNonNull(actualConvention, "actualConvention is null");
requireNonNull(expectedConvention, "expectedConvention is null");
if (actualConvention.getArgumentConventions().size() != expectedConvention.getArgumentConventions().size()) {
throw new IllegalArgumentException("Actual and expected conventions have different number of arguments");
}
if (actualConvention.supportsSession() && !expectedConvention.supportsSession()) {
throw new IllegalArgumentException("Session method can not be adapted to no session");
}
if (!(expectedConvention.supportsInstanceFactor() || !actualConvention.supportsInstanceFactor())) {
throw new IllegalArgumentException("Instance method can not be adapted to no instance");
}
// adapt return first, since return-null-on-null parameter convention must know if the return type is nullable
methodHandle = adaptReturn(methodHandle, actualConvention.getReturnConvention(), expectedConvention.getReturnConvention());
// adapt parameters one at a time
int parameterIndex = 0;
if (actualConvention.supportsInstanceFactor()) {
parameterIndex++;
}
if (actualConvention.supportsSession()) {
parameterIndex++;
}
for (int argumentIndex = 0; argumentIndex < actualConvention.getArgumentConventions().size(); argumentIndex++) {
Type argumentType = actualArgumentTypes.get(argumentIndex);
InvocationArgumentConvention actualArgumentConvention = actualConvention.getArgumentConvention(argumentIndex);
InvocationArgumentConvention expectedArgumentConvention = expectedConvention.getArgumentConvention(argumentIndex);
methodHandle = adaptParameter(methodHandle, parameterIndex, argumentType, actualArgumentConvention, expectedArgumentConvention, expectedConvention.getReturnConvention());
parameterIndex++;
if (expectedArgumentConvention == NULL_FLAG || expectedArgumentConvention == BLOCK_POSITION) {
parameterIndex++;
}
}
return methodHandle;
}
Aggregations