use of com.facebook.presto.spi.function.Signature in project presto by prestodb.
the class HiveScalarFunctionInvoker method createFunctionInvoker.
public static HiveScalarFunctionInvoker createFunctionInvoker(Class<?> cls, QualifiedObjectName name, List<TypeSignature> arguments, TypeManager typeManager) {
final List<Type> argumentTypes = arguments.stream().map(typeManager::getType).collect(Collectors.toList());
try {
// Step 1: Create function instance
final GenericUDF udf = createGenericUDF(name, cls);
// Step 2: Initialize function
ObjectInspector[] inputInspectors = argumentTypes.stream().map(argumentType -> ObjectInspectors.create(argumentType, typeManager)).toArray(ObjectInspector[]::new);
ObjectInspector resultInspector = udf.initialize(inputInspectors);
// Step 3: Create invoker
Type resultType = PrestoTypes.fromObjectInspector(resultInspector, typeManager);
ObjectInputDecoder[] argumentDecoders = argumentTypes.stream().map(argumentsType -> createDecoder(argumentsType, typeManager)).toArray(ObjectInputDecoder[]::new);
ObjectEncoder resultEncoder = createEncoder(resultType, resultInspector);
Signature signature = new Signature(name, SCALAR, resultType.getTypeSignature(), arguments);
// Step 4: Create ThreadLocal GenericUDF
final ThreadLocal<GenericUDF> genericUDFSupplier = ThreadLocal.withInitial(() -> {
try (ThreadContextClassLoader ignored = new ThreadContextClassLoader(cls.getClassLoader())) {
GenericUDF ret = createGenericUDF(name, cls);
ret.initialize(inputInspectors);
return ret;
} catch (Exception e) {
throw initializationError(e);
}
});
return new HiveScalarFunctionInvoker(signature, genericUDFSupplier::get, argumentDecoders, resultEncoder);
} catch (Exception e) {
throw initializationError(e);
}
}
use of com.facebook.presto.spi.function.Signature in project presto by prestodb.
the class TestScalarMethodHandles method runCase.
private void runCase(String resultType, String[] argumentTypes, Object result, Object... arguments) throws Throwable {
Signature signature = createScalarSignature(resultType, argumentTypes);
MethodHandle methodHandle = generateUnbound(signature, typeManager);
TestingScalarFunctionInvoker invoker = new TestingScalarFunctionInvoker(signature, result);
final Object output;
if (arguments.length == 1) {
output = methodHandle.invoke(invoker, arguments[0]);
} else if (arguments.length == 2) {
output = methodHandle.invoke(invoker, arguments[0], arguments[1]);
} else if (arguments.length == 3) {
output = methodHandle.invoke(invoker, arguments[0], arguments[1], arguments[2]);
} else if (arguments.length == 4) {
output = methodHandle.invoke(invoker, arguments[0], arguments[1], arguments[2], arguments[3]);
} else {
throw new RuntimeException("Not supported yet");
}
Object[] inputs = invoker.getInputs();
assertEquals(output, result);
assertEquals(inputs, arguments);
}
use of com.facebook.presto.spi.function.Signature in project presto by prestodb.
the class DecimalOperators method decimalDivideOperator.
private static SqlScalarFunction decimalDivideOperator() {
TypeSignature decimalLeftSignature = parseTypeSignature("decimal(a_precision, a_scale)", ImmutableSet.of("a_precision", "a_scale"));
TypeSignature decimalRightSignature = parseTypeSignature("decimal(b_precision, b_scale)", ImmutableSet.of("b_precision", "b_scale"));
TypeSignature decimalResultSignature = parseTypeSignature("decimal(r_precision, r_scale)", ImmutableSet.of("r_precision", "r_scale"));
// we extend target precision by b_scale. This is upper bound on how much division result will grow.
// pessimistic case is a / 0.0000001
// if scale of divisor is greater than scale of dividend we extend scale further as we
// want result scale to be maximum of scales of divisor and dividend.
Signature signature = SignatureBuilder.builder().kind(SCALAR).operatorType(DIVIDE).longVariableConstraints(longVariableExpression("r_precision", "min(38, a_precision + b_scale + max(b_scale - a_scale, 0))"), longVariableExpression("r_scale", "max(a_scale, b_scale)")).argumentTypes(decimalLeftSignature, decimalRightSignature).returnType(decimalResultSignature).build();
return SqlScalarFunction.builder(DecimalOperators.class, DIVIDE).signature(signature).deterministic(true).choice(choice -> choice.implementation(methodsGroup -> methodsGroup.methods("divideShortShortShort", "divideShortLongShort", "divideLongShortShort", "divideShortShortLong", "divideLongLongLong", "divideShortLongLong", "divideLongShortLong").withExtraParameters(DecimalOperators::divideRescaleFactor))).build();
}
use of com.facebook.presto.spi.function.Signature in project presto by prestodb.
the class DecimalOperators method decimalSubtractOperator.
private static SqlScalarFunction decimalSubtractOperator() {
TypeSignature decimalLeftSignature = parseTypeSignature("decimal(a_precision, a_scale)", ImmutableSet.of("a_precision", "a_scale"));
TypeSignature decimalRightSignature = parseTypeSignature("decimal(b_precision, b_scale)", ImmutableSet.of("b_precision", "b_scale"));
TypeSignature decimalResultSignature = parseTypeSignature("decimal(r_precision, r_scale)", ImmutableSet.of("r_precision", "r_scale"));
Signature signature = SignatureBuilder.builder().kind(SCALAR).operatorType(SUBTRACT).longVariableConstraints(longVariableExpression("r_precision", "min(38, max(a_precision - a_scale, b_precision - b_scale) + max(a_scale, b_scale) + 1)"), longVariableExpression("r_scale", "max(a_scale, b_scale)")).argumentTypes(decimalLeftSignature, decimalRightSignature).returnType(decimalResultSignature).build();
return SqlScalarFunction.builder(DecimalOperators.class, SUBTRACT).signature(signature).deterministic(true).choice(choice -> choice.implementation(methodsGroup -> methodsGroup.methods("subtractShortShortShort").withExtraParameters(DecimalOperators::calculateShortRescaleParameters)).implementation(methodsGroup -> methodsGroup.methods("subtractShortShortLong", "subtractLongLongLong", "subtractShortLongLong", "subtractLongShortLong").withExtraParameters(DecimalOperators::calculateLongRescaleParameters))).build();
}
use of com.facebook.presto.spi.function.Signature in project presto by prestodb.
the class CodegenScalarFromAnnotationsParser method createSqlScalarFunction.
private static SqlScalarFunction createSqlScalarFunction(Method method) {
CodegenScalarFunction codegenScalarFunction = method.getAnnotation(CodegenScalarFunction.class);
Signature signature = new Signature(QualifiedObjectName.valueOf(DEFAULT_NAMESPACE, codegenScalarFunction.value()), FunctionKind.SCALAR, Arrays.stream(method.getAnnotationsByType(TypeParameter.class)).map(t -> withVariadicBound(t.value(), t.boundedBy().isEmpty() ? null : t.boundedBy())).collect(toImmutableList()), ImmutableList.of(), parseTypeSignature(method.getAnnotation(SqlType.class).value()), Arrays.stream(method.getParameters()).map(p -> parseTypeSignature(p.getAnnotation(SqlType.class).value())).collect(toImmutableList()), false);
return new SqlScalarFunction(signature) {
@Override
public BuiltInScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, FunctionAndTypeManager functionAndTypeManager) {
Signature boundSignature = applyBoundVariables(signature, boundVariables, arity);
MethodHandle handle;
try {
handle = (MethodHandle) method.invoke(null, boundSignature.getArgumentTypes().stream().map(t -> functionAndTypeManager.getType(t)).toArray());
} catch (Exception e) {
throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, format("Method %s does not return valid MethodHandle", method), e);
}
return new BuiltInScalarFunctionImplementation(method.getAnnotation(SqlNullable.class) != null, getArgumentProperties(method), handle, Optional.empty());
}
@Override
public SqlFunctionVisibility getVisibility() {
return codegenScalarFunction.visibility();
}
@Override
public boolean isDeterministic() {
return codegenScalarFunction.deterministic();
}
@Override
public String getDescription() {
Description description = method.getAnnotation(Description.class);
return description == null ? "" : description.value();
}
@Override
public boolean isCalledOnNullInput() {
return codegenScalarFunction.calledOnNullInput();
}
};
}
Aggregations