HiveScalarFunction.java
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.facebook.presto.hive.functions.scalar;
import com.facebook.presto.common.QualifiedObjectName;
import com.facebook.presto.common.type.TypeManager;
import com.facebook.presto.common.type.TypeSignature;
import com.facebook.presto.hive.functions.HiveFunction;
import com.facebook.presto.hive.functions.gen.ScalarMethodHandles;
import com.facebook.presto.spi.function.FunctionImplementationType;
import com.facebook.presto.spi.function.FunctionMetadata;
import com.facebook.presto.spi.function.InvocationConvention;
import com.facebook.presto.spi.function.JavaScalarFunctionImplementation;
import com.facebook.presto.spi.function.Signature;
import com.facebook.presto.spi.function.SqlFunctionVisibility;
import java.lang.invoke.MethodHandle;
import java.util.List;
import static com.facebook.presto.hive.functions.scalar.HiveScalarFunctionInvoker.createFunctionInvoker;
import static com.facebook.presto.spi.function.FunctionKind.SCALAR;
import static com.facebook.presto.spi.function.InvocationConvention.InvocationArgumentConvention.BOXED_NULLABLE;
import static com.facebook.presto.spi.function.SqlFunctionVisibility.PUBLIC;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.Objects.requireNonNull;
public class HiveScalarFunction
extends HiveFunction
{
private final JavaScalarFunctionImplementation implementation;
private final FunctionMetadata functionMetadata;
private HiveScalarFunction(FunctionMetadata metadata,
Signature signature,
String description,
JavaScalarFunctionImplementation implementation)
{
super(metadata.getName(),
signature,
false,
metadata.isDeterministic(),
metadata.isCalledOnNullInput(),
description);
this.functionMetadata = requireNonNull(metadata, "metadata is null");
this.implementation = requireNonNull(implementation, "implementation is null");
}
public static HiveScalarFunction createHiveScalarFunction(Class<?> cls, QualifiedObjectName name, List<TypeSignature> argumentTypes, TypeManager typeManager)
{
HiveScalarFunctionInvoker invoker = createFunctionInvoker(cls, name, argumentTypes, typeManager);
MethodHandle methodHandle = ScalarMethodHandles.generateUnbound(invoker.getSignature(), typeManager).bindTo(invoker);
Signature signature = invoker.getSignature();
FunctionMetadata functionMetadata = new FunctionMetadata(name,
signature.getArgumentTypes(),
signature.getReturnType(),
SCALAR,
FunctionImplementationType.JAVA,
true,
true);
InvocationConvention invocationConvention = new InvocationConvention(
signature.getArgumentTypes().stream().map(t -> BOXED_NULLABLE).collect(toImmutableList()),
InvocationConvention.InvocationReturnConvention.NULLABLE_RETURN,
false);
JavaScalarFunctionImplementation implementation = new HiveScalarFunctionImplementation(methodHandle, invocationConvention);
return new HiveScalarFunction(functionMetadata, signature, name.getObjectName(), implementation);
}
public FunctionMetadata getFunctionMetadata()
{
return functionMetadata;
}
public JavaScalarFunctionImplementation getJavaScalarFunctionImplementation()
{
return implementation;
}
@Override
public SqlFunctionVisibility getVisibility()
{
return PUBLIC;
}
private static class HiveScalarFunctionImplementation
implements JavaScalarFunctionImplementation
{
private final MethodHandle methodHandle;
private final InvocationConvention invocationConvention;
private HiveScalarFunctionImplementation(MethodHandle methodHandle, InvocationConvention invocationConvention)
{
this.methodHandle = requireNonNull(methodHandle, "methodHandle is null");
this.invocationConvention = requireNonNull(invocationConvention, "invocationConvention is null");
}
public InvocationConvention getInvocationConvention()
{
return invocationConvention;
}
public MethodHandle getMethodHandle()
{
return methodHandle;
}
}
}