use of com.facebook.presto.operator.scalar.ScalarFunctionImplementation in project presto by prestodb.
the class FunctionRegistry method parameterIsNullable.
private boolean parameterIsNullable(Signature boundSignature, int parameterIndex) {
FunctionKind functionKind = boundSignature.getKind();
// Window and Aggregation functions have fixed semantic where NULL values are always skipped
if (functionKind != SCALAR) {
return false;
}
// TODO: Move information about nullable arguments to FunctionSignature. Remove this hack.
ScalarFunctionImplementation implementation = getScalarFunctionImplementation(boundSignature);
return implementation.getNullableArguments().get(parameterIndex);
}
use of com.facebook.presto.operator.scalar.ScalarFunctionImplementation in project presto by prestodb.
the class PolymorphicScalarFunction method specialize.
@Override
public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) {
List<TypeSignature> resolvedParameterTypeSignatures = applyBoundVariables(getSignature().getArgumentTypes(), boundVariables);
List<Type> resolvedParameterTypes = resolveTypes(resolvedParameterTypeSignatures, typeManager);
TypeSignature resolvedReturnTypeSignature = applyBoundVariables(getSignature().getReturnType(), boundVariables);
Type resolvedReturnType = typeManager.getType(resolvedReturnTypeSignature);
SpecializeContext context = new SpecializeContext(boundVariables, resolvedParameterTypes, resolvedReturnType, typeManager, functionRegistry);
Optional<Method> matchingMethod = Optional.empty();
Optional<MethodsGroup> matchingMethodsGroup = Optional.empty();
for (MethodsGroup candidateMethodsGroup : methodsGroups) {
for (Method candidateMethod : candidateMethodsGroup.getMethods()) {
if (matchesParameterAndReturnTypes(candidateMethod, resolvedParameterTypes, resolvedReturnType) && predicateIsTrue(candidateMethodsGroup, context)) {
if (matchingMethod.isPresent()) {
if (onlyFirstMatchedMethodHasPredicate(matchingMethodsGroup.get(), candidateMethodsGroup)) {
continue;
}
throw new IllegalStateException("two matching methods (" + matchingMethod.get().getName() + " and " + candidateMethod.getName() + ") for parameter types " + resolvedParameterTypeSignatures);
}
matchingMethod = Optional.of(candidateMethod);
matchingMethodsGroup = Optional.of(candidateMethodsGroup);
}
}
}
checkState(matchingMethod.isPresent(), "no matching method for parameter types %s", resolvedParameterTypes);
List<Object> extraParameters = computeExtraParameters(matchingMethodsGroup.get(), context);
MethodHandle matchingMethodHandle = applyExtraParameters(matchingMethod.get(), extraParameters);
return new ScalarFunctionImplementation(nullableResult, nullableArguments, nullFlags, matchingMethodHandle, deterministic);
}
use of com.facebook.presto.operator.scalar.ScalarFunctionImplementation in project presto by prestodb.
the class FunctionInvoker method invoke.
/**
* Arguments must be the native container type for the corresponding SQL types.
*
* Returns a value in the native container type corresponding to the declared SQL return type
*/
public Object invoke(Signature function, ConnectorSession session, List<Object> arguments) {
ScalarFunctionImplementation implementation = registry.getScalarFunctionImplementation(function);
MethodHandle method = implementation.getMethodHandle();
List<Object> actualArguments = new ArrayList<>(arguments.size() + 1);
Iterator<Object> iterator = arguments.iterator();
for (int i = 0; i < method.type().parameterCount(); i++) {
Class<?> parameterType = method.type().parameterType(i);
if (parameterType == ConnectorSession.class) {
actualArguments.add(session);
} else {
checkArgument(iterator.hasNext(), "Not enough arguments provided for method: %s", method.type());
Object argument = iterator.next();
if (implementation.getNullFlags().get(i)) {
boolean isNull = argument == null;
if (isNull) {
argument = Defaults.defaultValue(parameterType);
}
actualArguments.add(argument);
actualArguments.add(isNull);
// Skip the next method parameter which is marked @IsNull
i++;
} else {
actualArguments.add(argument);
}
}
}
checkArgument(!iterator.hasNext(), "Too many arguments provided for method: %s", method.type());
try {
return method.invokeWithArguments(actualArguments);
} catch (Throwable throwable) {
throw Throwables.propagate(throwable);
}
}
use of com.facebook.presto.operator.scalar.ScalarFunctionImplementation in project presto by prestodb.
the class NullIfCodeGenerator method generateExpression.
@Override
public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments) {
Scope scope = generatorContext.getScope();
RowExpression first = arguments.get(0);
RowExpression second = arguments.get(1);
LabelNode notMatch = new LabelNode("notMatch");
// push first arg on the stack
BytecodeBlock block = new BytecodeBlock().comment("check if first arg is null").append(generatorContext.generate(first)).append(BytecodeUtils.ifWasNullPopAndGoto(scope, notMatch, void.class));
Type firstType = first.getType();
Type secondType = second.getType();
// if (equal(cast(first as <common type>), cast(second as <common type>))
Signature equalsSignature = generatorContext.getRegistry().resolveOperator(OperatorType.EQUAL, ImmutableList.of(firstType, secondType));
ScalarFunctionImplementation equalsFunction = generatorContext.getRegistry().getScalarFunctionImplementation(equalsSignature);
BytecodeNode equalsCall = generatorContext.generateCall(equalsSignature.getName(), equalsFunction, ImmutableList.of(cast(generatorContext, new BytecodeBlock().dup(firstType.getJavaType()), firstType, equalsSignature.getArgumentTypes().get(0)), cast(generatorContext, generatorContext.generate(second), secondType, equalsSignature.getArgumentTypes().get(1))));
BytecodeBlock conditionBlock = new BytecodeBlock().append(equalsCall).append(BytecodeUtils.ifWasNullClearPopAndGoto(scope, notMatch, void.class, boolean.class));
// if first and second are equal, return null
BytecodeBlock trueBlock = new BytecodeBlock().append(generatorContext.wasNull().set(constantTrue())).pop(first.getType().getJavaType()).pushJavaDefault(first.getType().getJavaType());
// else return first (which is still on the stack
block.append(new IfStatement().condition(conditionBlock).ifTrue(trueBlock).ifFalse(notMatch));
return block;
}
use of com.facebook.presto.operator.scalar.ScalarFunctionImplementation in project presto by prestodb.
the class TestPolymorphicScalarFunction method testSetsHiddenToTrueForOperators.
@Test
public void testSetsHiddenToTrueForOperators() {
Signature signature = Signature.builder().operatorType(ADD).kind(SCALAR).returnType(parseTypeSignature("varchar(x)", ImmutableSet.of("x"))).argumentTypes(parseTypeSignature("varchar(x)", ImmutableSet.of("x"))).build();
SqlScalarFunction function = SqlScalarFunction.builder(TestMethods.class).signature(signature).implementation(b -> b.methods("varcharToVarchar")).build();
ScalarFunctionImplementation functionImplementation = function.specialize(BOUND_VARIABLES, 1, TYPE_REGISTRY, REGISTRY);
}
Aggregations