use of com.facebook.presto.sql.analyzer.TypeSignatureProvider in project presto by prestodb.
the class FunctionRegistry method doGetSpecializedFunctionKey.
private SpecializedFunctionKey doGetSpecializedFunctionKey(Signature signature) {
Iterable<SqlFunction> candidates = functions.get(QualifiedName.of(signature.getName()));
// search for exact match
Type returnType = typeManager.getType(signature.getReturnType());
List<TypeSignatureProvider> argumentTypeSignatureProviders = fromTypeSignatures(signature.getArgumentTypes());
for (SqlFunction candidate : candidates) {
Optional<BoundVariables> boundVariables = new SignatureBinder(typeManager, candidate.getSignature(), false).bindVariables(argumentTypeSignatureProviders, returnType);
if (boundVariables.isPresent()) {
return new SpecializedFunctionKey(candidate, boundVariables.get(), argumentTypeSignatureProviders.size());
}
}
// TODO: hack because there could be "type only" coercions (which aren't necessarily included as implicit casts),
// so do a second pass allowing "type only" coercions
List<Type> argumentTypes = resolveTypes(signature.getArgumentTypes(), typeManager);
for (SqlFunction candidate : candidates) {
SignatureBinder binder = new SignatureBinder(typeManager, candidate.getSignature(), true);
Optional<BoundVariables> boundVariables = binder.bindVariables(argumentTypeSignatureProviders, returnType);
if (!boundVariables.isPresent()) {
continue;
}
Signature boundSignature = applyBoundVariables(candidate.getSignature(), boundVariables.get(), argumentTypes.size());
if (!typeManager.isTypeOnlyCoercion(typeManager.getType(boundSignature.getReturnType()), returnType)) {
continue;
}
boolean nonTypeOnlyCoercion = false;
for (int i = 0; i < argumentTypes.size(); i++) {
Type expectedType = typeManager.getType(boundSignature.getArgumentTypes().get(i));
if (!typeManager.isTypeOnlyCoercion(argumentTypes.get(i), expectedType)) {
nonTypeOnlyCoercion = true;
break;
}
}
if (nonTypeOnlyCoercion) {
continue;
}
return new SpecializedFunctionKey(candidate, boundVariables.get(), argumentTypes.size());
}
// TODO: this is a hack and should be removed
if (signature.getName().startsWith(MAGIC_LITERAL_FUNCTION_PREFIX)) {
List<TypeSignature> parameterTypes = signature.getArgumentTypes();
// extract type from function name
String typeName = signature.getName().substring(MAGIC_LITERAL_FUNCTION_PREFIX.length());
// lookup the type
Type type = typeManager.getType(parseTypeSignature(typeName));
requireNonNull(type, format("Type %s not registered", typeName));
// verify we have one parameter of the proper type
checkArgument(parameterTypes.size() == 1, "Expected one argument to literal function, but got %s", parameterTypes);
Type parameterType = typeManager.getType(parameterTypes.get(0));
requireNonNull(parameterType, format("Type %s not found", parameterTypes.get(0)));
return new SpecializedFunctionKey(magicLiteralFunction, BoundVariables.builder().setTypeVariable("T", parameterType).setTypeVariable("R", type).build(), 1);
}
throw new PrestoException(FUNCTION_IMPLEMENTATION_MISSING, format("%s not found", signature));
}
use of com.facebook.presto.sql.analyzer.TypeSignatureProvider in project presto by prestodb.
the class FunctionRegistry method resolveFunction.
public Signature resolveFunction(QualifiedName name, List<TypeSignatureProvider> parameterTypes) {
Collection<SqlFunction> allCandidates = functions.get(name);
List<SqlFunction> exactCandidates = allCandidates.stream().filter(function -> function.getSignature().getTypeVariableConstraints().isEmpty()).collect(Collectors.toList());
Optional<Signature> match = matchFunctionExact(exactCandidates, parameterTypes);
if (match.isPresent()) {
return match.get();
}
List<SqlFunction> genericCandidates = allCandidates.stream().filter(function -> !function.getSignature().getTypeVariableConstraints().isEmpty()).collect(Collectors.toList());
match = matchFunctionExact(genericCandidates, parameterTypes);
if (match.isPresent()) {
return match.get();
}
match = matchFunctionWithCoercion(allCandidates, parameterTypes);
if (match.isPresent()) {
return match.get();
}
List<String> expectedParameters = new ArrayList<>();
for (SqlFunction function : allCandidates) {
expectedParameters.add(format("%s(%s) %s", name, Joiner.on(", ").join(function.getSignature().getArgumentTypes()), Joiner.on(", ").join(function.getSignature().getTypeVariableConstraints())));
}
String parameters = Joiner.on(", ").join(parameterTypes);
String message = format("Function %s not registered", name);
if (!expectedParameters.isEmpty()) {
String expected = Joiner.on(", ").join(expectedParameters);
message = format("Unexpected parameters (%s) for function %s. Expected: %s", parameters, name, expected);
}
if (name.getSuffix().startsWith(MAGIC_LITERAL_FUNCTION_PREFIX)) {
// extract type from function name
String typeName = name.getSuffix().substring(MAGIC_LITERAL_FUNCTION_PREFIX.length());
// lookup the type
Type type = typeManager.getType(parseTypeSignature(typeName));
requireNonNull(type, format("Type %s not registered", typeName));
// verify we have one parameter of the proper type
checkArgument(parameterTypes.size() == 1, "Expected one argument to literal function, but got %s", parameterTypes);
Type parameterType = typeManager.getType(parameterTypes.get(0).getTypeSignature());
requireNonNull(parameterType, format("Type %s not found", parameterTypes.get(0)));
return getMagicLiteralFunctionSignature(type);
}
throw new PrestoException(FUNCTION_NOT_FOUND, message);
}
use of com.facebook.presto.sql.analyzer.TypeSignatureProvider in project presto by prestodb.
the class BuiltInTypeAndFunctionNamespaceManager method doGetSpecializedFunctionKey.
private SpecializedFunctionKey doGetSpecializedFunctionKey(Signature signature) {
Iterable<SqlFunction> candidates = getFunctions(null, signature.getName());
// search for exact match
Type returnType = functionAndTypeManager.getType(signature.getReturnType());
List<TypeSignatureProvider> argumentTypeSignatureProviders = fromTypeSignatures(signature.getArgumentTypes());
for (SqlFunction candidate : candidates) {
Optional<BoundVariables> boundVariables = new SignatureBinder(functionAndTypeManager, candidate.getSignature(), false).bindVariables(argumentTypeSignatureProviders, returnType);
if (boundVariables.isPresent()) {
return new SpecializedFunctionKey(candidate, boundVariables.get(), argumentTypeSignatureProviders.size());
}
}
// TODO: hack because there could be "type only" coercions (which aren't necessarily included as implicit casts),
// so do a second pass allowing "type only" coercions
List<Type> argumentTypes = resolveTypes(signature.getArgumentTypes(), functionAndTypeManager);
for (SqlFunction candidate : candidates) {
SignatureBinder binder = new SignatureBinder(functionAndTypeManager, candidate.getSignature(), true);
Optional<BoundVariables> boundVariables = binder.bindVariables(argumentTypeSignatureProviders, returnType);
if (!boundVariables.isPresent()) {
continue;
}
Signature boundSignature = applyBoundVariables(candidate.getSignature(), boundVariables.get(), argumentTypes.size());
if (!functionAndTypeManager.isTypeOnlyCoercion(functionAndTypeManager.getType(boundSignature.getReturnType()), returnType)) {
continue;
}
boolean nonTypeOnlyCoercion = false;
for (int i = 0; i < argumentTypes.size(); i++) {
Type expectedType = functionAndTypeManager.getType(boundSignature.getArgumentTypes().get(i));
if (!functionAndTypeManager.isTypeOnlyCoercion(argumentTypes.get(i), expectedType)) {
nonTypeOnlyCoercion = true;
break;
}
}
if (nonTypeOnlyCoercion) {
continue;
}
return new SpecializedFunctionKey(candidate, boundVariables.get(), argumentTypes.size());
}
// TODO: this is a hack and should be removed
if (signature.getNameSuffix().startsWith(MAGIC_LITERAL_FUNCTION_PREFIX)) {
List<TypeSignature> parameterTypes = signature.getArgumentTypes();
// extract type from function name
String typeName = signature.getNameSuffix().substring(MAGIC_LITERAL_FUNCTION_PREFIX.length());
// lookup the type
Type type = functionAndTypeManager.getType(parseTypeSignature(typeName));
// verify we have one parameter of the proper type
checkArgument(parameterTypes.size() == 1, "Expected one argument to literal function, but got %s", parameterTypes);
Type parameterType = functionAndTypeManager.getType(parameterTypes.get(0));
requireNonNull(parameterType, format("Type %s not found", parameterTypes.get(0)));
return new SpecializedFunctionKey(magicLiteralFunction, BoundVariables.builder().setTypeVariable("T", parameterType).setTypeVariable("R", type).build(), 1);
}
throw new PrestoException(FUNCTION_IMPLEMENTATION_MISSING, format("%s not found", signature));
}
use of com.facebook.presto.sql.analyzer.TypeSignatureProvider in project presto by prestodb.
the class FunctionAndTypeManager method lookupFunction.
/**
* Lookup up a function with name and fully bound types. This can only be used for builtin functions. {@link #resolveFunction(Optional, Optional, QualifiedObjectName, List)}
* should be used for dynamically registered functions.
*
* @throws PrestoException if function could not be found
*/
public FunctionHandle lookupFunction(String name, List<TypeSignatureProvider> parameterTypes) {
QualifiedObjectName functionName = qualifyObjectName(QualifiedName.of(name));
if (parameterTypes.stream().noneMatch(TypeSignatureProvider::hasDependency)) {
return lookupCachedFunction(functionName, parameterTypes);
}
Collection<? extends SqlFunction> candidates = builtInTypeAndFunctionNamespaceManager.getFunctions(Optional.empty(), functionName);
Optional<Signature> match = functionSignatureMatcher.match(candidates, parameterTypes, false);
if (!match.isPresent()) {
throw new PrestoException(FUNCTION_NOT_FOUND, constructFunctionNotFoundErrorMessage(functionName, parameterTypes, candidates));
}
return builtInTypeAndFunctionNamespaceManager.getFunctionHandle(Optional.empty(), match.get());
}
use of com.facebook.presto.sql.analyzer.TypeSignatureProvider in project presto by prestodb.
the class TestSignatureBinder method testFunction.
@Test
public void testFunction() {
Signature simple = functionSignature().returnType(parseTypeSignature("boolean")).argumentTypes(parseTypeSignature("function(integer,integer)")).build();
assertThat(simple).boundTo("integer").fails();
assertThat(simple).boundTo("function(integer,integer)").succeeds();
// TODO: Support coercion of return type of lambda
assertThat(simple).boundTo("function(integer,smallint)").withCoercion().fails();
assertThat(simple).boundTo("function(integer,bigint)").withCoercion().fails();
Signature applyTwice = functionSignature().returnType(parseTypeSignature("V")).argumentTypes(parseTypeSignature("T"), parseTypeSignature("function(T,U)"), parseTypeSignature("function(U,V)")).typeVariableConstraints(typeVariable("T"), typeVariable("U"), typeVariable("V")).build();
assertThat(applyTwice).boundTo("integer", "integer", "integer").fails();
assertThat(applyTwice).boundTo("integer", "function(integer,varchar)", "function(varchar,double)").produces(BoundVariables.builder().setTypeVariable("T", INTEGER).setTypeVariable("U", VARCHAR).setTypeVariable("V", DOUBLE).build());
assertThat(applyTwice).boundTo("integer", new TypeSignatureProvider(functionArgumentTypes -> TypeSignature.parseTypeSignature("function(integer,varchar)")), new TypeSignatureProvider(functionArgumentTypes -> TypeSignature.parseTypeSignature("function(varchar,double)"))).produces(BoundVariables.builder().setTypeVariable("T", INTEGER).setTypeVariable("U", VARCHAR).setTypeVariable("V", DOUBLE).build());
assertThat(applyTwice).boundTo(// pass function argument to non-function position of a function
new TypeSignatureProvider(functionArgumentTypes -> TypeSignature.parseTypeSignature("function(integer,varchar)")), new TypeSignatureProvider(functionArgumentTypes -> TypeSignature.parseTypeSignature("function(integer,varchar)")), new TypeSignatureProvider(functionArgumentTypes -> TypeSignature.parseTypeSignature("function(varchar,double)"))).fails();
assertThat(applyTwice).boundTo(new TypeSignatureProvider(functionArgumentTypes -> TypeSignature.parseTypeSignature("function(integer,varchar)")), // pass non-function argument to function position of a function
"integer", new TypeSignatureProvider(functionArgumentTypes -> TypeSignature.parseTypeSignature("function(varchar,double)"))).fails();
Signature flatMap = functionSignature().returnType(parseTypeSignature("array(T)")).argumentTypes(parseTypeSignature("array(T)"), parseTypeSignature("function(T, array(T))")).typeVariableConstraints(typeVariable("T")).build();
assertThat(flatMap).boundTo("array(integer)", "function(integer, array(integer))").produces(BoundVariables.builder().setTypeVariable("T", INTEGER).build());
Signature varargApply = functionSignature().returnType(parseTypeSignature("T")).argumentTypes(parseTypeSignature("T"), parseTypeSignature("function(T, T)")).typeVariableConstraints(typeVariable("T")).setVariableArity(true).build();
assertThat(varargApply).boundTo("integer", "function(integer, integer)", "function(integer, integer)", "function(integer, integer)").produces(BoundVariables.builder().setTypeVariable("T", INTEGER).build());
assertThat(varargApply).boundTo("integer", "function(integer, integer)", "function(integer, double)", "function(double, double)").fails();
Signature loop = functionSignature().returnType(parseTypeSignature("T")).argumentTypes(parseTypeSignature("T"), parseTypeSignature("function(T, T)")).typeVariableConstraints(typeVariable("T")).build();
assertThat(loop).boundTo("integer", new TypeSignatureProvider(paramTypes -> new FunctionType(paramTypes, BIGINT).getTypeSignature())).fails();
assertThat(loop).boundTo("integer", new TypeSignatureProvider(paramTypes -> new FunctionType(paramTypes, BIGINT).getTypeSignature())).withCoercion().produces(BoundVariables.builder().setTypeVariable("T", BIGINT).build());
// TODO: Support coercion of return type of lambda
assertThat(loop).withCoercion().boundTo("integer", new TypeSignatureProvider(paramTypes -> new FunctionType(paramTypes, SMALLINT).getTypeSignature())).fails();
// TODO: Support coercion of return type of lambda
// Without coercion support for return type of lambda, the return type of lambda must be `varchar(x)` to avoid need for coercions.
Signature varcharApply = functionSignature().returnType(parseTypeSignature("varchar")).argumentTypes(parseTypeSignature("varchar"), parseTypeSignature("function(varchar, varchar(x))", ImmutableSet.of("x"))).build();
assertThat(varcharApply).withCoercion().boundTo("varchar(10)", new TypeSignatureProvider(paramTypes -> new FunctionType(paramTypes, createVarcharType(1)).getTypeSignature())).succeeds();
Signature sortByKey = functionSignature().returnType(parseTypeSignature("array(T)")).argumentTypes(parseTypeSignature("array(T)"), parseTypeSignature("function(T,E)")).typeVariableConstraints(typeVariable("T"), orderableTypeParameter("E")).build();
assertThat(sortByKey).boundTo("array(integer)", new TypeSignatureProvider(paramTypes -> new FunctionType(paramTypes, VARCHAR).getTypeSignature())).produces(BoundVariables.builder().setTypeVariable("T", INTEGER).setTypeVariable("E", VARCHAR).build());
}
Aggregations