Search in sources :

Example 21 with GenericType

use of io.confluent.ksql.function.types.GenericType in project ksql by confluentinc.

the class UdfIndexTest method shouldMatchGenericMethodWithMultipleIdenticalGenerics.

@Test
public void shouldMatchGenericMethodWithMultipleIdenticalGenerics() {
    // Given:
    final GenericType generic = GenericType.of("A");
    givenFunctions(function(EXPECTED, false, generic, generic));
    // When:
    final KsqlScalarFunction fun = udfIndex.getFunction(ImmutableList.of(SqlArgument.of(INTEGER), SqlArgument.of(INTEGER)));
    // Then:
    assertThat(fun.name(), equalTo(EXPECTED));
}
Also used : GenericType(io.confluent.ksql.function.types.GenericType) Test(org.junit.Test)

Example 22 with GenericType

use of io.confluent.ksql.function.types.GenericType in project ksql by confluentinc.

the class GenericsUtil method reserveGenerics.

/**
 * Identifies a mapping from generic type to concrete type based on a {@code schema} and
 * an {@code instance}, where the {@code instance} schema is expected to have no generic
 * types and have the same nested structure as {@code schema}. Adds the mapping to an
 * existing mapping passed into the function
 *
 * @param schema    the schema that may contain generics
 * @param instance  a schema with the same structure as {@code schema} but with no generics
 * @param reservedGenerics  mapping of generic type to resolved type
 *
 * @return if the mapping succeeded and if it failed, an exception with why it failed
 */
public static Pair<Boolean, Optional<KsqlException>> reserveGenerics(final ParamType schema, final SqlArgument instance, final Map<GenericType, SqlType> reservedGenerics) {
    final List<Entry<GenericType, SqlType>> genericMapping = new ArrayList<>();
    final boolean success = resolveGenerics(genericMapping, schema, instance);
    if (!success) {
        return new Pair<>(false, Optional.of(new KsqlException(String.format("Cannot infer generics for %s from %s because " + "they do not have the same schema structure.", schema, instance))));
    }
    for (final Entry<GenericType, SqlType> entry : genericMapping) {
        final SqlType old = reservedGenerics.putIfAbsent(entry.getKey(), entry.getValue());
        if (old != null && !old.equals(entry.getValue())) {
            return new Pair<>(false, Optional.of(new KsqlException(String.format("Found invalid instance of generic schema when mapping %s to %s. " + "Cannot map %s to both %s and %s", schema, instance, entry.getKey(), old, entry.getValue()))));
        }
    }
    return new Pair<>(true, null);
}
Also used : Entry(java.util.Map.Entry) GenericType(io.confluent.ksql.function.types.GenericType) ArrayList(java.util.ArrayList) SqlType(io.confluent.ksql.schema.ksql.types.SqlType) KsqlException(io.confluent.ksql.util.KsqlException) Pair(io.confluent.ksql.util.Pair)

Example 23 with GenericType

use of io.confluent.ksql.function.types.GenericType in project ksql by confluentinc.

the class GenericsUtil method applyResolved.

/**
 * Replaces all generics in a schema with concrete schemas defined in {@code resolved}
 *
 * @param schema    the schema which may contain generics
 * @param resolved  the mapping from generics to resolved types
 * @return a schema with the same structure as {@code schema} but with no generics
 *
 * @throws KsqlException if there is a generic in {@code schema} that is not present
 *                       in {@code mapping}
 */
public static SqlType applyResolved(final ParamType schema, final Map<GenericType, SqlType> resolved) {
    if (schema instanceof ArrayType) {
        return SqlTypes.array(applyResolved(((ArrayType) schema).element(), resolved));
    }
    if (schema instanceof MapType) {
        final MapType mapType = (MapType) schema;
        final SqlType keyType = applyResolved(mapType.key(), resolved);
        final SqlType valueType = applyResolved(mapType.value(), resolved);
        return SqlTypes.map(keyType, valueType);
    }
    if (schema instanceof StructType) {
        final Builder struct = SqlTypes.struct();
        ((StructType) schema).getSchema().forEach((fieldName, type) -> struct.field(fieldName, applyResolved(type, resolved)));
        return struct.build();
    }
    if (schema instanceof GenericType) {
        final SqlType instance = resolved.get(schema);
        if (instance == null) {
            throw new KsqlException("Could not find mapping for generic type: " + schema);
        }
        return instance;
    }
    return SchemaConverters.functionToSqlConverter().toSqlType(schema);
}
Also used : ArrayType(io.confluent.ksql.function.types.ArrayType) GenericType(io.confluent.ksql.function.types.GenericType) StructType(io.confluent.ksql.function.types.StructType) Builder(io.confluent.ksql.schema.ksql.types.SqlStruct.Builder) SqlType(io.confluent.ksql.schema.ksql.types.SqlType) KsqlException(io.confluent.ksql.util.KsqlException) MapType(io.confluent.ksql.function.types.MapType)

Example 24 with GenericType

use of io.confluent.ksql.function.types.GenericType in project ksql by confluentinc.

the class GenericsUtil method resolveGenerics.

/**
 * Identifies a mapping from generic type to concrete type based on a {@code schema} and
 * an {@code instance}, where the {@code instance} schema is expected to have no generic
 * types and have the same nested structure as {@code schema}. Any Generic type mapping
 * identified is added to the list passed in.
 *
 * @param mapping   a list of GenericType to SqlType mappings
 * @param schema    the schema that may contain generics
 * @param instance  a schema with the same structure as {@code schema} but with no generics
 *
 * @return whether we were able to resolve generics in the instance and schema
 */
// CHECKSTYLE_RULES.OFF: NPathComplexity
// CHECKSTYLE_RULES.OFF: CyclomaticComplexity
private static boolean resolveGenerics(final List<Entry<GenericType, SqlType>> mapping, final ParamType schema, final SqlArgument instance) {
    if (!isGeneric(schema) && !matches(schema, instance)) {
        // cannot identify from type mismatch
        return false;
    } else if (!hasGenerics(schema)) {
        // nothing left to identify
        return true;
    }
    KsqlPreconditions.checkArgument(isGeneric(schema) || (matches(schema, instance)), "Cannot resolve generics if the schema and instance have differing types: " + schema + " vs. " + instance);
    if (schema instanceof LambdaType) {
        final LambdaType lambdaType = (LambdaType) schema;
        final SqlLambda sqlLambda = instance.getSqlLambdaOrThrow();
        if (lambdaType.inputTypes().size() == sqlLambda.getNumInputs()) {
            if (sqlLambda instanceof SqlLambdaResolved) {
                final SqlLambdaResolved sqlLambdaResolved = (SqlLambdaResolved) sqlLambda;
                int i = 0;
                for (final ParamType paramType : lambdaType.inputTypes()) {
                    if (!resolveGenerics(mapping, paramType, SqlArgument.of(sqlLambdaResolved.getInputType().get(i)))) {
                        return false;
                    }
                    i++;
                }
                return resolveGenerics(mapping, lambdaType.returnType(), SqlArgument.of(sqlLambdaResolved.getReturnType()));
            } else {
                return true;
            }
        } else {
            return false;
        }
    }
    final SqlType sqlType = instance.getSqlTypeOrThrow();
    if (isGeneric(schema)) {
        mapping.add(new HashMap.SimpleEntry<>((GenericType) schema, sqlType));
    }
    if (schema instanceof ArrayType) {
        final SqlArray sqlArray = (SqlArray) sqlType;
        return resolveGenerics(mapping, ((ArrayType) schema).element(), SqlArgument.of(sqlArray.getItemType()));
    }
    if (schema instanceof MapType) {
        final SqlMap sqlMap = (SqlMap) sqlType;
        final MapType mapType = (MapType) schema;
        return resolveGenerics(mapping, mapType.key(), SqlArgument.of(sqlMap.getKeyType())) && resolveGenerics(mapping, mapType.value(), SqlArgument.of(sqlMap.getValueType()));
    }
    if (schema instanceof StructType) {
        throw new KsqlException("Generic STRUCT is not yet supported");
    }
    return true;
}
Also used : LambdaType(io.confluent.ksql.function.types.LambdaType) GenericType(io.confluent.ksql.function.types.GenericType) SqlMap(io.confluent.ksql.schema.ksql.types.SqlMap) StructType(io.confluent.ksql.function.types.StructType) SqlLambda(io.confluent.ksql.schema.ksql.types.SqlLambda) HashMap(java.util.HashMap) KsqlException(io.confluent.ksql.util.KsqlException) ParamType(io.confluent.ksql.function.types.ParamType) MapType(io.confluent.ksql.function.types.MapType) ArrayType(io.confluent.ksql.function.types.ArrayType) SqlLambdaResolved(io.confluent.ksql.schema.ksql.types.SqlLambdaResolved) SqlType(io.confluent.ksql.schema.ksql.types.SqlType) SqlArray(io.confluent.ksql.schema.ksql.types.SqlArray)

Example 25 with GenericType

use of io.confluent.ksql.function.types.GenericType in project ksql by confluentinc.

the class UdfIndexTest method shouldMatchGenericMethodWithMultipleGenerics.

@Test
public void shouldMatchGenericMethodWithMultipleGenerics() {
    // Given:
    final GenericType genericA = GenericType.of("A");
    final GenericType genericB = GenericType.of("B");
    givenFunctions(function(EXPECTED, false, genericA, genericB));
    // When:
    final KsqlScalarFunction fun = udfIndex.getFunction(ImmutableList.of(SqlArgument.of(INTEGER), SqlArgument.of(SqlTypes.STRING)));
    // Then:
    assertThat(fun.name(), equalTo(EXPECTED));
}
Also used : GenericType(io.confluent.ksql.function.types.GenericType) Test(org.junit.Test)

Aggregations

GenericType (io.confluent.ksql.function.types.GenericType)34 Test (org.junit.Test)27 LambdaType (io.confluent.ksql.function.types.LambdaType)17 ParamType (io.confluent.ksql.function.types.ParamType)17 SqlType (io.confluent.ksql.schema.ksql.types.SqlType)16 ArrayType (io.confluent.ksql.function.types.ArrayType)12 MapType (io.confluent.ksql.function.types.MapType)12 StructType (io.confluent.ksql.function.types.StructType)12 SqlArgument (io.confluent.ksql.schema.ksql.SqlArgument)11 Type (java.lang.reflect.Type)10 KsqlException (io.confluent.ksql.util.KsqlException)5 HashMap (java.util.HashMap)5 ArrayList (java.util.ArrayList)2 Optional (java.util.Optional)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 Expression (io.confluent.ksql.execution.expression.tree.Expression)1 LambdaFunctionCall (io.confluent.ksql.execution.expression.tree.LambdaFunctionCall)1 UdfUtil (io.confluent.ksql.execution.function.UdfUtil)1 KsqlScalarFunction (io.confluent.ksql.function.KsqlScalarFunction)1 ParamTypes (io.confluent.ksql.function.types.ParamTypes)1