use of com.facebook.presto.operator.scalar.ScalarFunctionImplementationChoice.ArgumentProperty in project presto by prestodb.
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))));
}
use of com.facebook.presto.operator.scalar.ScalarFunctionImplementationChoice.ArgumentProperty in project presto by prestodb.
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.hasSqlFunctionProperties()) {
methodHandleParameterTypes.add(SqlFunctionProperties.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());
}
use of com.facebook.presto.operator.scalar.ScalarFunctionImplementationChoice.ArgumentProperty in project presto by prestodb.
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
*/
private Object invoke(JavaScalarFunctionImplementation function, SqlFunctionProperties properties, List<Object> arguments) {
ScalarFunctionImplementationChoice choice = getAllScalarFunctionImplementationChoices(function).get(0);
MethodHandle method = choice.getMethodHandle();
// handle function on instance method, to allow use of fields
method = bindInstanceFactory(method, function);
if (method.type().parameterCount() > 0 && method.type().parameterType(0) == SqlFunctionProperties.class) {
method = method.bindTo(properties);
}
List<Object> actualArguments = new ArrayList<>();
for (int i = 0; i < arguments.size(); i++) {
Object argument = arguments.get(i);
ArgumentProperty argumentProperty = choice.getArgumentProperty(i);
if (argumentProperty.getArgumentType() == VALUE_TYPE) {
if (choice.getArgumentProperty(i).getNullConvention() == RETURN_NULL_ON_NULL) {
if (argument == null) {
return null;
}
actualArguments.add(argument);
} else if (choice.getArgumentProperty(i).getNullConvention() == USE_NULL_FLAG) {
boolean isNull = argument == null;
if (isNull) {
argument = Defaults.defaultValue(method.type().parameterType(actualArguments.size()));
}
actualArguments.add(argument);
actualArguments.add(isNull);
} else {
actualArguments.add(argument);
}
} else {
argument = asInterfaceInstance(argumentProperty.getLambdaInterface(), (MethodHandle) argument);
actualArguments.add(argument);
}
}
try {
return method.invokeWithArguments(actualArguments);
} catch (Throwable throwable) {
throw propagate(throwable);
}
}
use of com.facebook.presto.operator.scalar.ScalarFunctionImplementationChoice.ArgumentProperty in project presto by prestodb.
the class ZipFunction method specialize.
@Override
public BuiltInScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, FunctionAndTypeManager functionAndTypeManager) {
List<Type> types = this.typeParameters.stream().map(boundVariables::getTypeVariable).collect(toImmutableList());
List<ArgumentProperty> argumentProperties = nCopies(types.size(), valueTypeArgumentProperty(RETURN_NULL_ON_NULL));
List<Class<?>> javaArgumentTypes = nCopies(types.size(), Block.class);
MethodHandle methodHandle = METHOD_HANDLE.bindTo(types).asVarargsCollector(Block[].class).asType(methodType(Block.class, javaArgumentTypes));
return new BuiltInScalarFunctionImplementation(false, argumentProperties, methodHandle);
}
use of com.facebook.presto.operator.scalar.ScalarFunctionImplementationChoice.ArgumentProperty in project presto by prestodb.
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());
ScalarFunctionImplementationChoice implementation = getAllScalarFunctionImplementationChoices(functionAndTypeManager.getJavaScalarFunctionImplementation(functionHandle)).get(0);
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);
}
Aggregations