Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * 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.metadata;
 
import static com.facebook.presto.operator.aggregation.ArbitraryAggregation.ARBITRARY_AGGREGATION;
import static com.facebook.presto.operator.aggregation.CountColumn.COUNT_COLUMN;
import static com.facebook.presto.operator.aggregation.MapAggregation.MAP_AGG;
import static com.facebook.presto.operator.aggregation.MaxBy.MAX_BY;
import static com.facebook.presto.operator.aggregation.MinBy.MIN_BY;
import static com.facebook.presto.operator.scalar.ArrayCardinalityFunction.ARRAY_CARDINALITY;
import static com.facebook.presto.operator.scalar.ArrayConcatFunction.ARRAY_CONCAT_FUNCTION;
import static com.facebook.presto.operator.scalar.ArrayConstructor.ARRAY_CONSTRUCTOR;
import static com.facebook.presto.operator.scalar.ArrayEqualOperator.ARRAY_EQUAL;
import static com.facebook.presto.operator.scalar.ArrayGreaterThanOperator.ARRAY_GREATER_THAN;
import static com.facebook.presto.operator.scalar.ArrayGreaterThanOrEqualOperator.ARRAY_GREATER_THAN_OR_EQUAL;
import static com.facebook.presto.operator.scalar.ArrayHashCodeOperator.ARRAY_HASH_CODE;
import static com.facebook.presto.operator.scalar.ArrayLessThanOperator.ARRAY_LESS_THAN;
import static com.facebook.presto.operator.scalar.ArrayLessThanOrEqualOperator.ARRAY_LESS_THAN_OR_EQUAL;
import static com.facebook.presto.operator.scalar.ArrayNotEqualOperator.ARRAY_NOT_EQUAL;
import static com.facebook.presto.operator.scalar.ArraySortFunction.ARRAY_SORT_FUNCTION;
import static com.facebook.presto.operator.scalar.ArraySubscriptOperator.ARRAY_SUBSCRIPT;
import static com.facebook.presto.operator.scalar.ArrayToElementConcatFunction.ARRAY_TO_ELEMENT_CONCAT_FUNCTION;
import static com.facebook.presto.operator.scalar.ArrayToJsonCast.ARRAY_TO_JSON;
import static com.facebook.presto.operator.scalar.ElementToArrayConcatFunction.ELEMENT_TO_ARRAY_CONCAT_FUNCTION;
import static com.facebook.presto.operator.scalar.Greatest.GREATEST;
import static com.facebook.presto.operator.scalar.IdentityCast.IDENTITY_CAST;
import static com.facebook.presto.operator.scalar.JsonToArrayCast.JSON_TO_ARRAY;
import static com.facebook.presto.operator.scalar.JsonToMapCast.JSON_TO_MAP;
import static com.facebook.presto.operator.scalar.Least.LEAST;
import static com.facebook.presto.operator.scalar.MapCardinalityFunction.MAP_CARDINALITY;
import static com.facebook.presto.operator.scalar.MapConstructor.MAP_CONSTRUCTOR;
import static com.facebook.presto.operator.scalar.MapEqualOperator.MAP_EQUAL;
import static com.facebook.presto.operator.scalar.MapKeys.MAP_KEYS;
import static com.facebook.presto.operator.scalar.MapNotEqualOperator.MAP_NOT_EQUAL;
import static com.facebook.presto.operator.scalar.MapSubscriptOperator.MAP_SUBSCRIPT;
import static com.facebook.presto.operator.scalar.MapToJsonCast.MAP_TO_JSON;
import static com.facebook.presto.operator.scalar.MapValues.MAP_VALUES;
import static com.facebook.presto.operator.scalar.RowEqualOperator.ROW_EQUAL;
import static com.facebook.presto.operator.scalar.RowHashCodeOperator.ROW_HASH_CODE;
import static com.facebook.presto.operator.scalar.RowNotEqualOperator.ROW_NOT_EQUAL;
import static com.facebook.presto.operator.scalar.RowToJsonCast.ROW_TO_JSON;
import static com.facebook.presto.operator.scalar.TryCastFunction.TRY_CAST;
import static com.facebook.presto.spi.StandardErrorCode.FUNCTION_NOT_FOUND;
import static com.facebook.presto.spi.type.BigintType.BIGINT;
import static com.facebook.presto.spi.type.BooleanType.BOOLEAN;
import static com.facebook.presto.spi.type.DateType.DATE;
import static com.facebook.presto.spi.type.DoubleType.DOUBLE;
import static com.facebook.presto.spi.type.TimeType.TIME;
import static com.facebook.presto.spi.type.TimeWithTimeZoneType.TIME_WITH_TIME_ZONE;
import static com.facebook.presto.spi.type.TimestampType.TIMESTAMP;
import static com.facebook.presto.spi.type.TimestampWithTimeZoneType.TIMESTAMP_WITH_TIME_ZONE;
import static com.facebook.presto.spi.type.TypeSignature.parseTypeSignature;
import static com.facebook.presto.spi.type.VarcharType.VARCHAR;
import static com.facebook.presto.type.JsonPathType.JSON_PATH;
import static com.facebook.presto.type.LikePatternType.LIKE_PATTERN;
import static com.facebook.presto.type.RegexpType.REGEXP;
import static com.facebook.presto.type.TypeUtils.resolveTypes;
import static com.facebook.presto.type.UnknownType.UNKNOWN;
import static com.facebook.presto.util.ImmutableCollectors.toImmutableList;
import static com.facebook.presto.util.ImmutableCollectors.toImmutableSet;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Predicates.not;
import static java.lang.String.format;
public class FunctionRegistry
    private static final String MAGIC_LITERAL_FUNCTION_PREFIX = "$literal$";
    private static final String OPERATOR_PREFIX = "$operator$";
    private static final String FIELD_ACCESSOR_PREFIX = "$field_accessor$";
    // hack: java classes for types that can be used with magic literals
    private static final Set<Class<?>> SUPPORTED_LITERAL_TYPES = ImmutableSet.<Class<?>>of(long.classdouble.classSlice.classboolean.class);
    private final TypeManager typeManager;
    private volatile FunctionMap functions = new FunctionMap();
    public FunctionRegistry(TypeManager typeManagerboolean experimentalSyntaxEnabled)
    {
        this. = checkNotNull(typeManager"typeManager is null");
         = CacheBuilder.newBuilder()
                .maximumSize(1000)
                .build(new CacheLoader<SpecializedFunctionKeyFunctionInfo>()
                {
                    @Override
                    public FunctionInfo load(SpecializedFunctionKey key)
                            throws Exception
                    {
                        return key.getFunction().specialize(key.getBoundTypeParameters(), key.getArity(), typeManagerFunctionRegistry.this);
                    }
                });
        FunctionListBuilder builder = new FunctionListBuilder(typeManager)
                .window("row_number", ImmutableList.<Type>of(), RowNumberFunction.class)
                .window("rank", ImmutableList.<Type>of(), RankFunction.class)
                .window("dense_rank", ImmutableList.<Type>of(), DenseRankFunction.class)
                .window("percent_rank", ImmutableList.<Type>of(), PercentRankFunction.class)
                .window("cume_dist", ImmutableList.<Type>of(), CumulativeDistributionFunction.class)
                .window("ntile", ImmutableList.<Type>of(), NTileFunction.class)
                .window("first_value", ImmutableList.<Type>of(), BigintFirstValueFunction.class)
                .window("first_value", ImmutableList.<Type>of(), DoubleFirstValueFunction.class)
                .window("first_value", ImmutableList.<Type>of(), BooleanFirstValueFunction.class)
                .window("first_value", ImmutableList.<Type>of(), VarcharFirstValueFunction.class)
                .window("last_value", ImmutableList.<Type>of(), BigintLastValueFunction.class)
                .window("last_value", ImmutableList.<Type>of(), DoubleLastValueFunction.class)
                .window("last_value", ImmutableList.<Type>of(), BooleanLastValueFunction.class)
                .window("last_value", ImmutableList.<Type>of(), VarcharLastValueFunction.class)
                .window("nth_value", ImmutableList.<Type>of(), BigintNthValueFunction.class)
                .window("nth_value", ImmutableList.<Type>of(), DoubleNthValueFunction.class)
                .window("nth_value", ImmutableList.<Type>of(), BooleanNthValueFunction.class)
                .window("nth_value", ImmutableList.<Type>of(), VarcharNthValueFunction.class)
                .window("lag", ImmutableList.<Type>of(), BigintLagFunction.class)
                .window("lag", ImmutableList.<Type>of(), BigintLagFunction.class)
                .window("lag", ImmutableList.<Type>of(), BigintLagFunction.class)
                .window("lag", ImmutableList.<Type>of(), DoubleLagFunction.class)
                .window("lag", ImmutableList.<Type>of(), DoubleLagFunction.class)
                .window("lag", ImmutableList.<Type>of(), DoubleLagFunction.class)
                .window("lag", ImmutableList.<Type>of(), BooleanLagFunction.class)
                .window("lag", ImmutableList.<Type>of(), BooleanLagFunction.class)
                .window("lag", ImmutableList.<Type>of(), BooleanLagFunction.class)
                .window("lag", ImmutableList.<Type>of(), VarcharLagFunction.class)
                .window("lag", ImmutableList.<Type>of(), VarcharLagFunction.class)
                .window("lag", ImmutableList.<Type>of(), VarcharLagFunction.class)
                .window("lead", ImmutableList.<Type>of(), BigintLeadFunction.class)
                .window("lead", ImmutableList.<Type>of(), BigintLeadFunction.class)
                .window("lead", ImmutableList.<Type>of(), BigintLeadFunction.class)
                .window("lead", ImmutableList.<Type>of(), DoubleLeadFunction.class)
                .window("lead", ImmutableList.<Type>of(), DoubleLeadFunction.class)
                .window("lead", ImmutableList.<Type>of(), DoubleLeadFunction.class)
                .window("lead", ImmutableList.<Type>of(), BooleanLeadFunction.class)
                .window("lead", ImmutableList.<Type>of(), BooleanLeadFunction.class)
                .window("lead", ImmutableList.<Type>of(), BooleanLeadFunction.class)
                .window("lead", ImmutableList.<Type>of(), VarcharLeadFunction.class)
                .window("lead", ImmutableList.<Type>of(), VarcharLeadFunction.class)
                .window("lead", ImmutableList.<Type>of(), VarcharLeadFunction.class)
                .aggregate(CountAggregation.class)
                .aggregate(VarianceAggregation.class)
                .aggregate(ApproximateLongPercentileAggregations.class)
                .aggregate(ApproximateDoublePercentileAggregations.class)
                .aggregate(CountIfAggregation.class)
                .aggregate(BooleanAndAggregation.class)
                .aggregate(BooleanOrAggregation.class)
                .aggregate(DoubleMinAggregation.class)
                .aggregate(DoubleMaxAggregation.class)
                .aggregate(LongMinAggregation.class)
                .aggregate(LongMaxAggregation.class)
                .aggregate(VarBinaryMinAggregation.class)
                .aggregate(VarBinaryMaxAggregation.class)
                .aggregate(DoubleSumAggregation.class)
                .aggregate(LongSumAggregation.class)
                .aggregate(AverageAggregations.class)
                .aggregate(ApproximateCountDistinctAggregations.class)
                .aggregate(MergeHyperLogLogAggregation.class)
                .aggregate(ApproximateSetAggregation.class)
                .aggregate(NumericHistogramAggregation.class)
                .scalar(StringFunctions.class)
                .scalar(VarbinaryFunctions.class)
                .scalar(RegexpFunctions.class)
                .scalar(UrlFunctions.class)
                .scalar(MathFunctions.class)
                .scalar(DateTimeFunctions.class)
                .scalar(JsonFunctions.class)
                .scalar(ColorFunctions.class)
                .scalar(HyperLogLogFunctions.class)
                .scalar(BooleanOperators.class)
                .scalar(BigintOperators.class)
                .scalar(DoubleOperators.class)
                .scalar(VarcharOperators.class)
                .scalar(VarbinaryOperators.class)
                .scalar(DateOperators.class)
                .scalar(TimeOperators.class)
                .scalar(TimestampOperators.class)
                .scalar(IntervalDayTimeOperators.class)
                .scalar(IntervalYearMonthOperators.class)
                .scalar(TimeWithTimeZoneOperators.class)
                .scalar(TimestampWithTimeZoneOperators.class)
                .scalar(DateTimeOperators.class)
                .scalar(HyperLogLogOperators.class)
                .scalar(LikeFunctions.class)
                .scalar(ArrayFunctions.class)
                .scalar(CombineHashFunction.class)
                .scalar(JsonOperators.class)
                .functions()
                .function()
                .function()
                .function()
                .function()
                .function()
                .function()
                .function()
                .functions()
                .function();
        if (experimentalSyntaxEnabled) {
            builder.aggregate(ApproximateAverageAggregations.class)
                    .aggregate(ApproximateSumAggregations.class)
                    .aggregate(ApproximateCountAggregation.class)
                    .aggregate(ApproximateCountColumnAggregations.class);
        }
        addFunctions(builder.getFunctions());
    }
    public final synchronized void addFunctions(List<? extends ParametricFunctionfunctions)
    {
        for (ParametricFunction function : functions) {
            for (ParametricFunction existingFunction : this..list()) {
                checkArgument(!function.getSignature().equals(existingFunction.getSignature()), "Function already registered: %s"function.getSignature());
            }
        }
        this. = new FunctionMap(this.functions);
    }
    public List<ParametricFunctionlist()
    {
        return FluentIterable.from(.list())
                .filter(not(ParametricFunction::isHidden))
                .toList();
    }
    public boolean isAggregationFunction(QualifiedName name)
    {
        return Iterables.any(.get(name), ParametricFunction::isAggregate);
    }
    public FunctionInfo resolveFunction(QualifiedName nameList<TypeSignatureparameterTypesboolean approximate)
    {
        List<ParametricFunctioncandidates = .get(name).stream()
                .filter(function -> function.isScalar() || function.isApproximate() == approximate)
                .collect(toImmutableList());
        List<TyperesolvedTypes = resolveTypes(parameterTypes);
        // search for exact match
        FunctionInfo match = null;
        for (ParametricFunction function : candidates) {
            Map<StringTypeboundTypeParameters = function.getSignature().bindTypeParameters(resolvedTypesfalse);
            if (boundTypeParameters != null) {
                checkArgument(match == null"Ambiguous call to %s with parameters %s"nameparameterTypes);
                try {
                    match = .getUnchecked(new SpecializedFunctionKey(functionboundTypeParametersresolvedTypes.size()));
                }
                catch (UncheckedExecutionException e) {
                    throw Throwables.propagate(e.getCause());
                }
            }
        }
        if (match != null) {
            return match;
        }
        // search for coerced match
        for (ParametricFunction function : candidates) {
            Map<StringTypeboundTypeParameters = function.getSignature().bindTypeParameters(resolvedTypestrue);
            if (boundTypeParameters != null) {
                // TODO: This should also check for ambiguities
                try {
                    return .getUnchecked(new SpecializedFunctionKey(functionboundTypeParametersresolvedTypes.size()));
                }
                catch (UncheckedExecutionException e) {
                    throw Throwables.propagate(e.getCause());
                }
            }
        }
        List<StringexpectedParameters = new ArrayList<>();
        for (ParametricFunction function : candidates) {
            expectedParameters.add(format("%s(%s)"name, Joiner.on(", ").join(function.getSignature().getArgumentTypes())));
        }
        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"parametersnameexpected);
        }
        if (name.getSuffix().startsWith()) {
            // extract type from function name
            String typeName = name.getSuffix().substring(.length());
            // lookup the type
            Type type = .getType(parseTypeSignature(typeName));
            checkNotNull(type"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 = .getType(parameterTypes.get(0));
            checkNotNull(parameterType"Type %s not found"parameterTypes.get(0));
            checkArgument(parameterType.getJavaType() == type.getJavaType(),
                    "Expected type %s to use Java type %s, but Java type is %s",
                    type,
                    parameterType.getJavaType(),
                    type.getJavaType());
            MethodHandle identity = MethodHandles.identity(parameterType.getJavaType());
            return new FunctionInfo(
                    getMagicLiteralFunctionSignature(type),
                    null,
                    true,
                    identity,
                    true,
                    false,
                    ImmutableList.of(false));
        }
        // TODO this should be made to work for any parametric type
        for (TypeSignature typeSignature : parameterTypes) {
            if (typeSignature.getBase().equals(.)) {
                RowType rowType = ..createType(resolveTypes(typeSignature.getParameters(), ), typeSignature.getLiteralParameters());
                // search for exact match
                for (ParametricFunction function : ..createFunctions(rowType)) {
                    if (!function.getSignature().getName().equals(name.toString())) {
                        continue;
                    }
                    Map<StringTypeboundTypeParameters = function.getSignature().bindTypeParameters(resolvedTypesfalse);
                    if (boundTypeParameters != null) {
                        checkArgument(match == null"Ambiguous call to %s with parameters %s"nameparameterTypes);
                        try {
                            match = .getUnchecked(new SpecializedFunctionKey(functionboundTypeParametersresolvedTypes.size()));
                        }
                        catch (UncheckedExecutionException e) {
                            throw Throwables.propagate(e.getCause());
                        }
                    }
                }
                if (match != null) {
                    return match;
                }
            }
        }
        throw new PrestoException(message);
    }
    public FunctionInfo getExactFunction(Signature signature)
    {
        Iterable<ParametricFunctioncandidates = .get(QualifiedName.of(signature.getName()));
        // search for exact match
        for (ParametricFunction operator : candidates) {
            Type returnType = .getType(signature.getReturnType());
            List<TypeargumentTypes = resolveTypes(signature.getArgumentTypes(), );
            Map<StringTypeboundTypeParameters = operator.getSignature().bindTypeParameters(returnTypeargumentTypesfalse);
            if (boundTypeParameters != null) {
                try {
                    return .getUnchecked(new SpecializedFunctionKey(operatorboundTypeParameterssignature.getArgumentTypes().size()));
                }
                catch (UncheckedExecutionException e) {
                    throw Throwables.propagate(e.getCause());
                }
            }
        }
        return null;
    }
    {
        Set<StringoperatorNames = Arrays.asList(OperatorType.values()).stream()
                .map(FunctionRegistry::mangleOperatorName)
                .collect(toImmutableSet());
        return .list().stream()
                .filter(function -> operatorNames.contains(function.getSignature().getName()))
                .collect(toImmutableList());
    }
    public FunctionInfo resolveOperator(OperatorType operatorTypeList<? extends TypeargumentTypes)
            throws OperatorNotFoundException
    {
        try {
            return resolveFunction(QualifiedName.of(mangleOperatorName(operatorType)), Lists.transform(argumentTypes, Type::getTypeSignature), false);
        }
        catch (PrestoException e) {
            if (e.getErrorCode().getCode() == .toErrorCode().getCode()) {
                throw new OperatorNotFoundException(operatorTypeargumentTypes);
            }
            else {
                throw e;
            }
        }
    }
    public FunctionInfo getCoercion(Type fromTypeType toType)
    {
        List<? extends TypeargumentTypes = ImmutableList.of(fromType);
        FunctionInfo functionInfo = getExactFunction(Signature.internalOperator(..name(), toType.getTypeSignature(), Lists.transform(argumentTypes, Type::getTypeSignature)));
        if (functionInfo == null) {
            throw new OperatorNotFoundException(.argumentTypestoType);
        }
        return functionInfo;
    }
    public static boolean canCoerce(List<? extends TypeactualTypesList<TypeexpectedTypes)
    {
        if (actualTypes.size() != expectedTypes.size()) {
            return false;
        }
        for (int i = 0; i < expectedTypes.size(); i++) {
            Type expectedType = expectedTypes.get(i);
            Type actualType = actualTypes.get(i);
            if (!canCoerce(actualTypeexpectedType)) {
                return false;
            }
        }
        return true;
    }
    public static boolean canCoerce(Type actualTypeType expectedType)
    {
        // are types the same
        if (expectedType.equals(actualType)) {
            return true;
        }
        // null can be cast to anything
        if (actualType.equals()) {
            return true;
        }
        // widen bigint to double
        if (actualType.equals() && expectedType.equals()) {
            return true;
        }
        // widen date to timestamp
        if (actualType.equals() && expectedType.equals()) {
            return true;
        }
        // widen date to timestamp with time zone
        if (actualType.equals() && expectedType.equals()) {
            return true;
        }
        // widen time to time with time zone
        if (actualType.equals() && expectedType.equals()) {
            return true;
        }
        // widen timestamp to timestamp with time zone
        if (actualType.equals() && expectedType.equals()) {
            return true;
        }
        if (actualType.equals() && expectedType.equals()) {
            return true;
        }
        if (actualType.equals() && expectedType.equals()) {
            return true;
        }
        if (actualType.equals() && expectedType.equals()) {
            return true;
        }
        return false;
    }
    public static Optional<TypegetCommonSuperType(List<? extends Typetypes)
    {
        checkArgument(!types.isEmpty(), "types is empty");
        Type superType = ;
        for (Type type : types) {
            Optional<TypecommonSuperType = getCommonSuperType(superTypetype);
            if (!commonSuperType.isPresent()) {
                return Optional.empty();
            }
            superType = commonSuperType.get();
        }
        return Optional.of(superType);
    }
    public static Optional<TypegetCommonSuperType(Type firstTypeType secondType)
    {
        if (firstType.equals()) {
            return Optional.of(secondType);
        }
        if (secondType.equals()) {
            return Optional.of(firstType);
        }
        if (firstType.equals(secondType)) {
            return Optional.of(firstType);
        }
        if ((firstType.equals() || firstType.equals()) && (secondType.equals() || secondType.equals())) {
            return Optional.<Type>of();
        }
        if ((firstType.equals() || firstType.equals()) && (secondType.equals() || secondType.equals())) {
            return Optional.<Type>of();
        }
        if ((firstType.equals() || firstType.equals()) && (secondType.equals() || secondType.equals())) {
            return Optional.<Type>of();
        }
        return Optional.empty();
    }
    public static Type type(Class<?> clazz)
    {
        clazz = Primitives.unwrap(clazz);
        if (clazz == long.class) {
            return ;
        }
        if (clazz == double.class) {
            return ;
        }
        if (clazz == Slice.class) {
            return ;
        }
        if (clazz == boolean.class) {
            return ;
        }
        throw new IllegalArgumentException("Unhandled Java type: " + clazz.getName());
    }
    public static Signature getMagicLiteralFunctionSignature(Type type)
    {
        return new Signature( + type.getTypeSignature(),
                type.getTypeSignature(),
                Lists.transform(ImmutableList.of(type(type.getJavaType())), Type::getTypeSignature));
    }
    public static boolean isSupportedLiteralType(Type type)
    {
        return .contains(type.getJavaType());
    }
    public static FunctionInfo operatorInfo(OperatorType operatorTypeTypeSignature returnTypeList<TypeSignatureargumentTypesMethodHandle methodboolean nullableList<BooleannullableArguments)
    {
        operatorType.validateSignature(returnTypeargumentTypes);
        Signature signature = Signature.internalOperator(operatorType.name(), returnTypeargumentTypes);
        return new FunctionInfo(signatureoperatorType.getOperator(), truemethodtruenullablenullableArguments);
    }
    public static String mangleOperatorName(OperatorType operatorType)
    {
        return mangleOperatorName(operatorType.name());
    }
    public static String mangleOperatorName(String operatorName)
    {
        return  + operatorName;
    }
    public static String mangleFieldAccessor(String fieldName)
    {
        return  + fieldName;
    }
    public static OperatorType unmangleOperator(String mangledName)
    {
        checkArgument(mangledName.startsWith(), "%s is not a mangled operator name"mangledName);
        return OperatorType.valueOf(mangledName.substring(.length()));
    }
    private static class FunctionMap
    {
        private final Multimap<QualifiedNameParametricFunctionfunctions;
        public FunctionMap()
        {
             = ImmutableListMultimap.of();
        }
        public FunctionMap(FunctionMap mapIterable<? extends ParametricFunctionfunctions)
        {
            this. = ImmutableListMultimap.<QualifiedNameParametricFunction>builder()
                    .putAll(map.functions)
                    .putAll(Multimaps.index(functionsfunction -> QualifiedName.of(function.getSignature().getName())))
                    .build();
            // Make sure all functions with the same name are aggregations or none of them are
            for (Map.Entry<QualifiedNameCollection<ParametricFunction>> entry : this..asMap().entrySet()) {
                Collection<ParametricFunctionvalues = entry.getValue();
                checkState(Iterables.all(values, ParametricFunction::isAggregate) || !Iterables.any(values, ParametricFunction::isAggregate),
                        "'%s' is both an aggregation and a scalar function"entry.getKey());
            }
        }
        public List<ParametricFunctionlist()
        {
            return ImmutableList.copyOf(.values());
        }
        public Collection<ParametricFunctionget(QualifiedName name)
        {
            return .get(name);
        }
    }
New to GrepCode? Check out our FAQ X