use of io.trino.spi.function.OperatorType in project trino by trinodb.
the class GlobalFunctionCatalog method checkNotSpecializedTypeOperator.
/**
* Type operators are handled automatically by the engine, so custom operator implementations
* cannot be registered for these.
*/
private static void checkNotSpecializedTypeOperator(Signature signature) {
String name = signature.getName();
if (!isOperatorName(name)) {
return;
}
OperatorType operatorType = unmangleOperator(name);
// The trick here is the Generic*Operator implementations implement these exact signatures,
// so we only these exact signatures to be registered. Since, only a single function with
// a specific signature can be registered, it prevents others from being registered.
Type expectedReturnType;
TypeVariableConstraint typeParameter;
switch(operatorType) {
case EQUAL:
case IS_DISTINCT_FROM:
case INDETERMINATE:
expectedReturnType = BOOLEAN;
typeParameter = comparableTypeParameter("T");
break;
case HASH_CODE:
case XX_HASH_64:
expectedReturnType = BIGINT;
typeParameter = comparableTypeParameter("T");
break;
case COMPARISON_UNORDERED_FIRST:
case COMPARISON_UNORDERED_LAST:
expectedReturnType = INTEGER;
typeParameter = orderableTypeParameter("T");
break;
case LESS_THAN:
case LESS_THAN_OR_EQUAL:
expectedReturnType = BOOLEAN;
typeParameter = orderableTypeParameter("T");
break;
default:
return;
}
Signature expectedSignature = new Signature(signature.getName(), ImmutableList.of(typeParameter), ImmutableList.of(), expectedReturnType.getTypeSignature(), Collections.nCopies(operatorType.getArgumentCount(), new TypeSignature("T")), false);
checkArgument(signature.equals(expectedSignature), "Can not register %s functionMetadata: %s", operatorType, signature);
}
use of io.trino.spi.function.OperatorType in project trino by trinodb.
the class MinMaxCompare method getMinMaxCompare.
public static MethodHandle getMinMaxCompare(FunctionDependencies dependencies, Type type, InvocationConvention convention, boolean min) {
OperatorType comparisonOperator = getMinMaxCompareOperatorType(min);
MethodHandle handle = dependencies.getOperatorInvoker(comparisonOperator, List.of(type, type), convention).getMethodHandle();
return comparisonToMinMaxResult(min, handle);
}
use of io.trino.spi.function.OperatorType in project trino by trinodb.
the class TestGlobalFunctionCatalog method testExactMatchBeforeCoercion.
@Test
public void testExactMatchBeforeCoercion() {
TestingFunctionResolution functionResolution = new TestingFunctionResolution();
Metadata metadata = functionResolution.getMetadata();
boolean foundOperator = false;
for (FunctionMetadata function : listOperators(metadata)) {
OperatorType operatorType = unmangleOperator(function.getSignature().getName());
if (operatorType == OperatorType.CAST || operatorType == OperatorType.SATURATED_FLOOR_CAST) {
continue;
}
if (!function.getSignature().getTypeVariableConstraints().isEmpty()) {
continue;
}
if (function.getSignature().getArgumentTypes().stream().anyMatch(TypeSignature::isCalculated)) {
continue;
}
List<Type> argumentTypes = function.getSignature().getArgumentTypes().stream().map(functionResolution.getPlannerContext().getTypeManager()::getType).collect(toImmutableList());
BoundSignature exactOperator = functionResolution.resolveOperator(operatorType, argumentTypes).getSignature();
assertEquals(exactOperator.toSignature(), function.getSignature());
foundOperator = true;
}
assertTrue(foundOperator);
}
use of io.trino.spi.function.OperatorType in project trino by trinodb.
the class TypeRegistry method verifyTypes.
public void verifyTypes() {
Set<Type> missingOperatorDeclaration = new HashSet<>();
Multimap<Type, OperatorType> missingOperators = HashMultimap.create();
for (Type type : ImmutableList.copyOf(types.values())) {
if (type.getTypeOperatorDeclaration(typeOperators) == null) {
missingOperatorDeclaration.add(type);
continue;
}
if (type.isComparable()) {
if (!hasEqualMethod(type)) {
missingOperators.put(type, EQUAL);
}
if (!hasHashCodeMethod(type)) {
missingOperators.put(type, HASH_CODE);
}
if (!hasXxHash64Method(type)) {
missingOperators.put(type, XX_HASH_64);
}
if (!hasDistinctFromMethod(type)) {
missingOperators.put(type, IS_DISTINCT_FROM);
}
if (!hasIndeterminateMethod(type)) {
missingOperators.put(type, INDETERMINATE);
}
}
if (type.isOrderable()) {
if (!hasComparisonUnorderedLastMethod(type)) {
missingOperators.put(type, COMPARISON_UNORDERED_LAST);
}
if (!hasComparisonUnorderedFirstMethod(type)) {
missingOperators.put(type, COMPARISON_UNORDERED_FIRST);
}
if (!hasLessThanMethod(type)) {
missingOperators.put(type, LESS_THAN);
}
if (!hasLessThanOrEqualMethod(type)) {
missingOperators.put(type, LESS_THAN_OR_EQUAL);
}
}
}
// TODO: verify the parametric types too
if (!missingOperators.isEmpty()) {
List<String> messages = new ArrayList<>();
for (Type type : missingOperatorDeclaration) {
messages.add(format("%s types operators is null", type));
}
for (Type type : missingOperators.keySet()) {
messages.add(format("%s missing for %s", missingOperators.get(type), type));
}
throw new IllegalStateException(Joiner.on(", ").join(messages));
}
}
use of io.trino.spi.function.OperatorType in project trino by trinodb.
the class FunctionsParserHelper method createTypeVariableConstraints.
public static List<TypeVariableConstraint> createTypeVariableConstraints(Collection<TypeParameter> typeParameters, List<ImplementationDependency> dependencies) {
Set<String> typeParameterNames = typeParameters.stream().map(TypeParameter::value).collect(toImmutableSortedSet(CASE_INSENSITIVE_ORDER));
Set<String> orderableRequired = new TreeSet<>(CASE_INSENSITIVE_ORDER);
Set<String> comparableRequired = new TreeSet<>(CASE_INSENSITIVE_ORDER);
HashMultimap<String, String> castableTo = HashMultimap.create();
HashMultimap<String, String> castableFrom = HashMultimap.create();
for (ImplementationDependency dependency : dependencies) {
if (dependency instanceof OperatorImplementationDependency) {
OperatorImplementationDependency operatorDependency = (OperatorImplementationDependency) dependency;
OperatorType operator = operatorDependency.getOperator();
List<TypeSignature> argumentTypes = operatorDependency.getArgumentTypes();
if (COMPARABLE_TYPE_OPERATORS.contains(operator)) {
verifyOperatorSignature(operator, argumentTypes);
TypeSignature typeSignature = argumentTypes.get(0);
if (typeParameterNames.contains(typeSignature.getBase())) {
comparableRequired.add(typeSignature.toString());
} else {
verifyTypeSignatureDoesNotContainAnyTypeParameters(typeSignature, typeSignature, typeParameterNames);
}
} else if (ORDERABLE_TYPE_OPERATORS.contains(operator)) {
verifyOperatorSignature(operator, argumentTypes);
TypeSignature typeSignature = argumentTypes.get(0);
if (typeParameterNames.contains(typeSignature.getBase())) {
orderableRequired.add(typeSignature.toString());
} else {
verifyTypeSignatureDoesNotContainAnyTypeParameters(typeSignature, typeSignature, typeParameterNames);
}
} else {
throw new IllegalArgumentException("Operator dependency on " + operator + " is not allowed");
}
} else if (dependency instanceof CastImplementationDependency) {
CastImplementationDependency castImplementationDependency = (CastImplementationDependency) dependency;
TypeSignature fromType = castImplementationDependency.getFromType();
TypeSignature toType = castImplementationDependency.getToType();
if (typeParameterNames.contains(fromType.getBase())) {
// fromType is a type parameter, so it must be castable to the toType, which might also be a type parameter
castableTo.put(fromType.toString().toLowerCase(Locale.ENGLISH), toType.toString());
} else if (typeParameterNames.contains(toType.getBase())) {
// toType is a type parameter, so it must be castable from the toType, which is not a type parameter
castableFrom.put(toType.toString().toLowerCase(Locale.ENGLISH), fromType.toString());
} else {
verifyTypeSignatureDoesNotContainAnyTypeParameters(fromType, fromType, typeParameterNames);
verifyTypeSignatureDoesNotContainAnyTypeParameters(toType, toType, typeParameterNames);
}
}
}
ImmutableList.Builder<TypeVariableConstraint> typeVariableConstraints = ImmutableList.builder();
for (String name : typeParameterNames) {
typeVariableConstraints.add(new TypeVariableConstraint(name, comparableRequired.contains(name), orderableRequired.contains(name), null, castableTo.get(name).stream().map(type -> parseTypeSignature(type, typeParameterNames)).collect(toImmutableSet()), castableFrom.get(name).stream().map(type -> parseTypeSignature(type, typeParameterNames)).collect(toImmutableSet())));
}
return typeVariableConstraints.build();
}
Aggregations