diff --git a/presto-common/src/main/java/com/facebook/presto/common/type/StandardTypes.java b/presto-common/src/main/java/com/facebook/presto/common/type/StandardTypes.java index e00e2241a76d0..2291fd8dc80e4 100644 --- a/presto-common/src/main/java/com/facebook/presto/common/type/StandardTypes.java +++ b/presto-common/src/main/java/com/facebook/presto/common/type/StandardTypes.java @@ -58,6 +58,7 @@ public final class StandardTypes public static final String VARCHAR_ENUM = "VarcharEnum"; public static final String DISTINCT_TYPE = "DistinctType"; public static final String UUID = "uuid"; + public static final String UNKNOWN = "unknown"; private StandardTypes() {} diff --git a/presto-common/src/main/java/com/facebook/presto/common/type/TypeManager.java b/presto-common/src/main/java/com/facebook/presto/common/type/TypeManager.java index 4eafde00c4d34..277ef86ffb881 100644 --- a/presto-common/src/main/java/com/facebook/presto/common/type/TypeManager.java +++ b/presto-common/src/main/java/com/facebook/presto/common/type/TypeManager.java @@ -13,6 +13,7 @@ */ package com.facebook.presto.common.type; +import java.util.Collection; import java.util.List; public interface TypeManager @@ -28,4 +29,19 @@ public interface TypeManager Type getParameterizedType(String baseTypeName, List typeParameters); boolean canCoerce(Type actualType, Type expectedType); + + default Type instantiateParametricType(TypeSignature typeSignature) + { + throw new UnsupportedOperationException(); + } + + List getTypes(); + + /** + * Gets all registered parametric types. + */ + default Collection getParametricTypes() + { + throw new UnsupportedOperationException(); + } } diff --git a/presto-common/src/test/java/com/facebook/presto/common/type/TestingTypeManager.java b/presto-common/src/test/java/com/facebook/presto/common/type/TestingTypeManager.java index 5e5042e87be3b..f2e6f847a48a5 100644 --- a/presto-common/src/test/java/com/facebook/presto/common/type/TestingTypeManager.java +++ b/presto-common/src/test/java/com/facebook/presto/common/type/TestingTypeManager.java @@ -54,7 +54,8 @@ public boolean canCoerce(Type actualType, Type expectedType) throw new UnsupportedOperationException(); } - private List getTypes() + @Override + public List getTypes() { return ImmutableList.of(BOOLEAN, INTEGER, BIGINT, DOUBLE, VARCHAR, VARBINARY, TIMESTAMP, DATE, ID, HYPER_LOG_LOG); } diff --git a/presto-hudi/src/test/java/com/facebook/presto/hudi/TestingTypeManager.java b/presto-hudi/src/test/java/com/facebook/presto/hudi/TestingTypeManager.java index 516f1805b40d8..8b9f9fb7a747a 100644 --- a/presto-hudi/src/test/java/com/facebook/presto/hudi/TestingTypeManager.java +++ b/presto-hudi/src/test/java/com/facebook/presto/hudi/TestingTypeManager.java @@ -58,7 +58,8 @@ public boolean canCoerce(Type actualType, Type expectedType) throw new UnsupportedOperationException(); } - private List getTypes() + @Override + public List getTypes() { return ImmutableList.of(BOOLEAN, INTEGER, BIGINT, DOUBLE, VARCHAR, VARBINARY, TIMESTAMP, DATE, HYPER_LOG_LOG); } diff --git a/presto-iceberg/src/test/java/com/facebook/presto/iceberg/TestIcebergFileWriter.java b/presto-iceberg/src/test/java/com/facebook/presto/iceberg/TestIcebergFileWriter.java index 3deaf5a828efd..b87e793547de7 100644 --- a/presto-iceberg/src/test/java/com/facebook/presto/iceberg/TestIcebergFileWriter.java +++ b/presto-iceberg/src/test/java/com/facebook/presto/iceberg/TestIcebergFileWriter.java @@ -184,7 +184,8 @@ public boolean canCoerce(Type actualType, Type expectedType) throw new UnsupportedOperationException(); } - private List getTypes() + @Override + public List getTypes() { return ImmutableList.of(BooleanType.BOOLEAN, INTEGER, BIGINT, DoubleType.DOUBLE, VARCHAR, VARBINARY, TIMESTAMP, DATE, HYPER_LOG_LOG); } diff --git a/presto-main/src/main/java/com/facebook/presto/UnknownTypeException.java b/presto-main/src/main/java/com/facebook/presto/UnknownTypeException.java new file mode 100644 index 0000000000000..984f953cbc0ee --- /dev/null +++ b/presto-main/src/main/java/com/facebook/presto/UnknownTypeException.java @@ -0,0 +1,28 @@ +/* + * 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; + +import com.facebook.presto.common.type.TypeSignature; +import com.facebook.presto.spi.PrestoException; + +import static com.facebook.presto.spi.StandardErrorCode.UNKNOWN_TYPE; + +public class UnknownTypeException + extends PrestoException +{ + public UnknownTypeException(TypeSignature signature) + { + super(UNKNOWN_TYPE, "Unknown type " + signature); + } +} diff --git a/presto-main/src/main/java/com/facebook/presto/execution/AddColumnTask.java b/presto-main/src/main/java/com/facebook/presto/execution/AddColumnTask.java index 0b233ef2ef8f6..261764cfd809e 100644 --- a/presto-main/src/main/java/com/facebook/presto/execution/AddColumnTask.java +++ b/presto-main/src/main/java/com/facebook/presto/execution/AddColumnTask.java @@ -14,6 +14,7 @@ package com.facebook.presto.execution; import com.facebook.presto.Session; +import com.facebook.presto.UnknownTypeException; import com.facebook.presto.common.QualifiedObjectName; import com.facebook.presto.common.type.Type; import com.facebook.presto.metadata.Metadata; @@ -88,7 +89,7 @@ public ListenableFuture execute(AddColumn statement, TransactionManager trans try { type = metadata.getType(parseTypeSignature(element.getType())); } - catch (IllegalArgumentException e) { + catch (UnknownTypeException e) { throw new SemanticException(TYPE_MISMATCH, element, "Unknown type '%s' for column '%s'", element.getType(), element.getName()); } if (type.equals(UNKNOWN)) { diff --git a/presto-main/src/main/java/com/facebook/presto/execution/CreateTableTask.java b/presto-main/src/main/java/com/facebook/presto/execution/CreateTableTask.java index 131ca3ae62237..7bf67508063f5 100644 --- a/presto-main/src/main/java/com/facebook/presto/execution/CreateTableTask.java +++ b/presto-main/src/main/java/com/facebook/presto/execution/CreateTableTask.java @@ -14,6 +14,7 @@ package com.facebook.presto.execution; import com.facebook.presto.Session; +import com.facebook.presto.UnknownTypeException; import com.facebook.presto.common.QualifiedObjectName; import com.facebook.presto.common.type.Type; import com.facebook.presto.metadata.Metadata; @@ -125,7 +126,7 @@ public ListenableFuture internalExecute(CreateTable statement, Metadata metad try { type = metadata.getType(parseTypeSignature(column.getType())); } - catch (IllegalArgumentException e) { + catch (UnknownTypeException e) { throw new SemanticException(TYPE_MISMATCH, element, "Unknown type '%s' for column '%s'", column.getType(), column.getName()); } if (type.equals(UNKNOWN)) { diff --git a/presto-main/src/main/java/com/facebook/presto/metadata/BuiltInTypeAndFunctionNamespaceManager.java b/presto-main/src/main/java/com/facebook/presto/metadata/BuiltInTypeAndFunctionNamespaceManager.java index c419822e91405..897f6657f4f3a 100644 --- a/presto-main/src/main/java/com/facebook/presto/metadata/BuiltInTypeAndFunctionNamespaceManager.java +++ b/presto-main/src/main/java/com/facebook/presto/metadata/BuiltInTypeAndFunctionNamespaceManager.java @@ -13,6 +13,7 @@ */ package com.facebook.presto.metadata; +import com.facebook.presto.UnknownTypeException; import com.facebook.presto.common.CatalogSchemaName; import com.facebook.presto.common.Page; import com.facebook.presto.common.QualifiedObjectName; @@ -531,7 +532,7 @@ @ThreadSafe public class BuiltInTypeAndFunctionNamespaceManager - implements FunctionNamespaceManager + implements FunctionNamespaceManager, TypeManager { public static final CatalogSchemaName JAVA_BUILTIN_NAMESPACE = new CatalogSchemaName("presto", "default"); public static final String ID = "builtin"; @@ -1261,14 +1262,15 @@ public ScalarFunctionImplementation getScalarFunctionImplementation(Signature si } } - public Optional getType(TypeSignature typeSignature) + @Override + public Type getType(TypeSignature typeSignature) { Type type = types.get(typeSignature); if (type != null) { - return Optional.of(type); + return type; } try { - return Optional.ofNullable(parametricTypeCache.getUnchecked(new ExactTypeSignature(typeSignature))); + return parametricTypeCache.getUnchecked(new ExactTypeSignature(typeSignature)); } catch (UncheckedExecutionException e) { throwIfUnchecked(e.getCause()); @@ -1276,6 +1278,18 @@ public Optional getType(TypeSignature typeSignature) } } + @Override + public Type getParameterizedType(String baseTypeName, List typeParameters) + { + throw new UnsupportedOperationException(); + } + + @Override + public boolean canCoerce(Type actualType, Type expectedType) + { + throw new UnsupportedOperationException(); + } + public List getTypes() { return ImmutableList.copyOf(types.values()); @@ -1295,14 +1309,22 @@ public void addParametricType(ParametricType parametricType) parametricTypes.putIfAbsent(name, parametricType); } + @Override public Collection getParametricTypes() { return parametricTypes.values(); } - private Type instantiateParametricType(ExactTypeSignature exactSignature) + private Type instantiateParametricType(ExactTypeSignature exactTypeSignature) + { + return instantiateParametricType(exactTypeSignature.getTypeSignature(), functionAndTypeManager, parametricTypes); + } + + public Type instantiateParametricType( + TypeSignature signature, + FunctionAndTypeManager functionAndTypeManager, + Map parametricTypes) { - TypeSignature signature = exactSignature.getTypeSignature(); List parameters = new ArrayList<>(); for (TypeSignatureParameter parameter : signature.getParameters()) { @@ -1312,7 +1334,7 @@ private Type instantiateParametricType(ExactTypeSignature exactSignature) ParametricType parametricType = parametricTypes.get(signature.getBase().toLowerCase(Locale.ENGLISH)); if (parametricType == null) { - throw new IllegalArgumentException("Unknown type " + signature); + throw new UnknownTypeException(signature); } if (parametricType instanceof MapParametricType) { diff --git a/presto-main/src/main/java/com/facebook/presto/metadata/FunctionAndTypeManager.java b/presto-main/src/main/java/com/facebook/presto/metadata/FunctionAndTypeManager.java index 456bdef5dba80..4ea19e25698cd 100644 --- a/presto-main/src/main/java/com/facebook/presto/metadata/FunctionAndTypeManager.java +++ b/presto-main/src/main/java/com/facebook/presto/metadata/FunctionAndTypeManager.java @@ -52,6 +52,8 @@ import com.facebook.presto.spi.function.SqlFunctionId; import com.facebook.presto.spi.function.SqlFunctionSupplier; import com.facebook.presto.spi.function.SqlInvokedFunction; +import com.facebook.presto.spi.type.TypeManagerContext; +import com.facebook.presto.spi.type.TypeManagerFactory; import com.facebook.presto.sql.analyzer.FeaturesConfig; import com.facebook.presto.sql.analyzer.FunctionAndTypeResolver; import com.facebook.presto.sql.analyzer.FunctionsConfig; @@ -61,6 +63,7 @@ import com.facebook.presto.transaction.TransactionManager; import com.facebook.presto.type.TypeCoercer; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Supplier; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -82,6 +85,7 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; import static com.facebook.presto.SystemSessionProperties.isExperimentalFunctionsEnabled; @@ -107,6 +111,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.ImmutableList.toImmutableList; +import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static java.lang.String.format; import static java.util.Collections.emptyList; @@ -128,14 +133,18 @@ public class FunctionAndTypeManager private final BuiltInTypeAndFunctionNamespaceManager builtInTypeAndFunctionNamespaceManager; private final FunctionInvokerProvider functionInvokerProvider; private final Map functionNamespaceManagerFactories = new ConcurrentHashMap<>(); + private final Map typeManagerFactories = new ConcurrentHashMap<>(); private final HandleResolver handleResolver; private final Map> functionNamespaceManagers = new ConcurrentHashMap<>(); + private final Map typeManagers = new ConcurrentHashMap<>(); private final FunctionSignatureMatcher functionSignatureMatcher; private final TypeCoercer typeCoercer; private final LoadingCache functionCache; private final CacheStatsMBean cacheStatsMBean; private final boolean nativeExecution; private final CatalogSchemaName defaultNamespace; + private final AtomicReference servingTypeManager; + private final AtomicReference>> servingTypeManagerParametricTypesSupplier; @Inject public FunctionAndTypeManager( @@ -151,6 +160,7 @@ public FunctionAndTypeManager( this.builtInTypeAndFunctionNamespaceManager = new BuiltInTypeAndFunctionNamespaceManager(blockEncodingSerde, functionsConfig, types, this); this.functionNamespaceManagers.put(JAVA_BUILTIN_NAMESPACE.getCatalogName(), builtInTypeAndFunctionNamespaceManager); this.functionInvokerProvider = new FunctionInvokerProvider(this); + this.typeManagers.put(JAVA_BUILTIN_NAMESPACE.getCatalogName(), builtInTypeAndFunctionNamespaceManager); this.handleResolver = requireNonNull(handleResolver, "handleResolver is null"); // TODO: Provide a more encapsulated way for TransactionManager to register FunctionNamespaceManager transactionManager.registerFunctionNamespaceManager(JAVA_BUILTIN_NAMESPACE.getCatalogName(), builtInTypeAndFunctionNamespaceManager); @@ -164,6 +174,8 @@ public FunctionAndTypeManager( this.typeCoercer = new TypeCoercer(functionsConfig, this); this.nativeExecution = featuresConfig.isNativeExecutionEnabled(); this.defaultNamespace = configureDefaultNamespace(functionsConfig.getDefaultNamespacePrefix()); + this.servingTypeManager = new AtomicReference<>(builtInTypeAndFunctionNamespaceManager); + this.servingTypeManagerParametricTypesSupplier = new AtomicReference<>(this::getServingTypeManagerParametricTypes); } public static FunctionAndTypeManager createTestFunctionAndTypeManager() @@ -234,6 +246,24 @@ public SqlFunctionSupplier getSpecializedFunctionKey(Signature signature) return FunctionAndTypeManager.this.getSpecializedFunctionKey(signature); } + @Override + public Type instantiateParametricType(TypeSignature typeSignature) + { + return FunctionAndTypeManager.this.instantiateParametricType(typeSignature); + } + + @Override + public List getTypes() + { + return FunctionAndTypeManager.this.getTypes(); + } + + @Override + public Collection getParametricTypes() + { + return FunctionAndTypeManager.this.getParametricTypes(); + } + @Override public Collection listBuiltInFunctions() { @@ -319,6 +349,15 @@ public FunctionMetadata getFunctionMetadata(FunctionHandle functionHandle) return functionNamespaceManager.get().getFunctionMetadata(functionHandle); } + @Override + public Type instantiateParametricType(TypeSignature typeSignature) + { + return builtInTypeAndFunctionNamespaceManager.instantiateParametricType( + typeSignature, + this, + servingTypeManagerParametricTypesSupplier.get().get()); + } + @Override public Type getType(TypeSignature signature) { @@ -327,12 +366,12 @@ public Type getType(TypeSignature signature) if (signature.isDistinctType()) { return getDistinctType(signature.getParameters().get(0).getDistinctTypeInfo()); } - Optional type = builtInTypeAndFunctionNamespaceManager.getType(signature.getStandardTypeSignature()); - if (type.isPresent()) { + Type type = servingTypeManager.get().getType(signature.getStandardTypeSignature()); + if (type != null) { if (signature.getTypeSignatureBase().hasTypeName()) { - return new TypeWithName(signature.getTypeSignatureBase().getTypeName(), type.get()); + return new TypeWithName(signature.getTypeSignatureBase().getTypeName(), type); } - return type.get(); + return type; } } @@ -364,6 +403,35 @@ public void addFunctionNamespaceFactory(FunctionNamespaceManagerFactory factory) handleResolver.addFunctionNamespace(factory.getName(), factory.getHandleResolver()); } + public void loadTypeManager(String typeManagerName) + { + requireNonNull(typeManagerName, "typeManagerName is null"); + TypeManagerFactory factory = typeManagerFactories.get(typeManagerName); + checkState(factory != null, "No factory for type manager %s", typeManagerName); + TypeManager typeManager = factory.create(new TypeManagerContext(this)); + + if (typeManagers.putIfAbsent(typeManagerName, typeManager) != null) { + throw new IllegalArgumentException(format("Type manager [%s] is already registered", typeManager)); + } + servingTypeManager.compareAndSet(servingTypeManager.get(), typeManager); + // Reset the parametric types cache + servingTypeManagerParametricTypesSupplier.set(this::getServingTypeManagerParametricTypes); + } + + public void loadTypeManagers() + { + for (String typeManagerName : typeManagerFactories.keySet()) { + loadTypeManager(typeManagerName); + } + } + + public void addTypeManagerFactory(TypeManagerFactory factory) + { + if (typeManagerFactories.putIfAbsent(factory.getName(), factory) != null) { + throw new IllegalArgumentException(format("Type manager '%s' is already registered", factory.getName())); + } + } + public void registerBuiltInFunctions(List functions) { builtInTypeAndFunctionNamespaceManager.registerBuiltInFunctions(functions); @@ -511,7 +579,7 @@ public List getTypes() public Collection getParametricTypes() { - return ImmutableList.copyOf(builtInTypeAndFunctionNamespaceManager.getParametricTypes()); + return builtInTypeAndFunctionNamespaceManager.getParametricTypes(); } public Optional getCommonSuperType(Type firstType, Type secondType) @@ -835,6 +903,12 @@ public CatalogSchemaName configureDefaultNamespace(String defaultNamespacePrefix return new CatalogSchemaName(catalogSchemaNameString[0], catalogSchemaNameString[1]); } + private Map getServingTypeManagerParametricTypes() + { + return servingTypeManager.get().getParametricTypes().stream() + .collect(toImmutableMap(ParametricType::getName, parametricType -> parametricType)); + } + private static class FunctionResolutionCacheKey { private final QualifiedObjectName functionName; diff --git a/presto-main/src/main/java/com/facebook/presto/metadata/SignatureBinder.java b/presto-main/src/main/java/com/facebook/presto/metadata/SignatureBinder.java index 42fdb77c3bdb5..a71844c54b7d4 100644 --- a/presto-main/src/main/java/com/facebook/presto/metadata/SignatureBinder.java +++ b/presto-main/src/main/java/com/facebook/presto/metadata/SignatureBinder.java @@ -13,6 +13,7 @@ */ package com.facebook.presto.metadata; +import com.facebook.presto.UnknownTypeException; import com.facebook.presto.common.type.FunctionType; import com.facebook.presto.common.type.NamedTypeSignature; import com.facebook.presto.common.type.ParameterKind; @@ -532,7 +533,12 @@ private static List expandVarargFormalTypeSignature(List commonSuperType = functionAndTypeManager.getCommonSuperType(originalType, actualType); - if (!commonSuperType.isPresent()) { + Optional commonSuperType; + try { + Type originalType = functionAndTypeManager.getType(new TypeSignature(formalTypeSignature.getBase(), originalTypeTypeParametersBuilder.build())); + commonSuperType = functionAndTypeManager.getCommonSuperType(originalType, actualType); + if (!commonSuperType.isPresent()) { + return SolverReturnStatus.UNSOLVABLE; + } + } + catch (UnknownTypeException e) { return SolverReturnStatus.UNSOLVABLE; } TypeSignature commonSuperTypeSignature = commonSuperType.get().getTypeSignature(); diff --git a/presto-main/src/main/java/com/facebook/presto/server/PluginManager.java b/presto-main/src/main/java/com/facebook/presto/server/PluginManager.java index 274f90bed1204..af0f0f3bee089 100644 --- a/presto-main/src/main/java/com/facebook/presto/server/PluginManager.java +++ b/presto-main/src/main/java/com/facebook/presto/server/PluginManager.java @@ -53,6 +53,7 @@ import com.facebook.presto.spi.tracing.TracerProvider; import com.facebook.presto.spi.ttl.ClusterTtlProviderFactory; import com.facebook.presto.spi.ttl.NodeTtlFetcherFactory; +import com.facebook.presto.spi.type.TypeManagerFactory; import com.facebook.presto.sql.analyzer.AnalyzerProviderManager; import com.facebook.presto.sql.analyzer.QueryPreparerProviderManager; import com.facebook.presto.sql.expressions.ExpressionOptimizerManager; @@ -402,6 +403,11 @@ public void installCoordinatorPlugin(CoordinatorPlugin plugin) log.info("Registering expression optimizer factory %s", expressionOptimizerFactory.getName()); expressionOptimizerManager.addExpressionOptimizerFactory(expressionOptimizerFactory); } + + for (TypeManagerFactory typeManagerFactory : plugin.getTypeManagerFactories()) { + log.info("Registering type manager factory %s", typeManagerFactory.getName()); + metadata.getFunctionAndTypeManager().addTypeManagerFactory(typeManagerFactory); + } } private URLClassLoader buildClassLoader(String plugin) diff --git a/presto-main/src/main/java/com/facebook/presto/server/PrestoServer.java b/presto-main/src/main/java/com/facebook/presto/server/PrestoServer.java index 3b2e9fd11e322..fac8bc79e06b5 100644 --- a/presto-main/src/main/java/com/facebook/presto/server/PrestoServer.java +++ b/presto-main/src/main/java/com/facebook/presto/server/PrestoServer.java @@ -43,6 +43,7 @@ import com.facebook.presto.metadata.Catalog; import com.facebook.presto.metadata.CatalogManager; import com.facebook.presto.metadata.DiscoveryNodeManager; +import com.facebook.presto.metadata.FunctionAndTypeManager; import com.facebook.presto.metadata.InternalNodeManager; import com.facebook.presto.metadata.SessionPropertyManager; import com.facebook.presto.metadata.StaticCatalogStore; @@ -190,6 +191,7 @@ public void run() injector.getInstance(NodeStatusNotificationManager.class).loadNodeStatusNotificationProvider(); injector.getInstance(GracefulShutdownHandler.class).loadNodeStatusNotification(); injector.getInstance(SessionPropertyManager.class).loadSessionPropertyProviders(); + injector.getInstance(FunctionAndTypeManager.class).loadTypeManagers(); PlanCheckerProviderManager planCheckerProviderManager = injector.getInstance(PlanCheckerProviderManager.class); InternalNodeManager nodeManager = injector.getInstance(DiscoveryNodeManager.class); NodeInfo nodeInfo = injector.getInstance(NodeInfo.class); diff --git a/presto-main/src/main/java/com/facebook/presto/sql/analyzer/ExpressionAnalyzer.java b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/ExpressionAnalyzer.java index 3dcc4bce7597a..002b667eb68d9 100644 --- a/presto-main/src/main/java/com/facebook/presto/sql/analyzer/ExpressionAnalyzer.java +++ b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/ExpressionAnalyzer.java @@ -14,6 +14,7 @@ package com.facebook.presto.sql.analyzer; import com.facebook.presto.Session; +import com.facebook.presto.UnknownTypeException; import com.facebook.presto.common.ErrorCode; import com.facebook.presto.common.QualifiedObjectName; import com.facebook.presto.common.Subfield; @@ -889,7 +890,7 @@ protected Type visitGenericLiteral(GenericLiteral node, StackableAstVisitorConte try { type = functionAndTypeResolver.getType(parseTypeSignature(node.getType())); } - catch (IllegalArgumentException e) { + catch (UnknownTypeException e) { throw new SemanticException(TYPE_MISMATCH, node, "Unknown type: " + node.getType()); } @@ -912,7 +913,7 @@ protected Type visitEnumLiteral(EnumLiteral node, StackableAstVisitorContext context) try { type = functionAndTypeResolver.getType(parseTypeSignature(node.getType())); } - catch (IllegalArgumentException e) { + catch (IllegalArgumentException | UnknownTypeException e) { throw new SemanticException(TYPE_MISMATCH, node, "Unknown type: " + node.getType()); } diff --git a/presto-main/src/main/java/com/facebook/presto/sql/analyzer/ExpressionTreeUtils.java b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/ExpressionTreeUtils.java index c1c5b6765e34c..ffe7a7a7c8d5e 100644 --- a/presto-main/src/main/java/com/facebook/presto/sql/analyzer/ExpressionTreeUtils.java +++ b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/ExpressionTreeUtils.java @@ -13,6 +13,7 @@ */ package com.facebook.presto.sql.analyzer; +import com.facebook.presto.UnknownTypeException; import com.facebook.presto.common.type.EnumType; import com.facebook.presto.common.type.Type; import com.facebook.presto.common.type.TypeWithName; @@ -152,7 +153,7 @@ public static Optional tryResolveEnumLiteralType(QualifiedName qua return Optional.of((TypeWithName) baseType); } } - catch (IllegalArgumentException e) { + catch (UnknownTypeException e) { return Optional.empty(); } return Optional.empty(); diff --git a/presto-main/src/main/java/com/facebook/presto/testing/QueryRunner.java b/presto-main/src/main/java/com/facebook/presto/testing/QueryRunner.java index e62447a403e94..cb302fd134bc6 100644 --- a/presto-main/src/main/java/com/facebook/presto/testing/QueryRunner.java +++ b/presto-main/src/main/java/com/facebook/presto/testing/QueryRunner.java @@ -107,6 +107,11 @@ default void loadSessionPropertyProvider(String sessionPropertyProviderName) Lock getExclusiveLock(); + default void loadTypeManager(String typeManagerName) + { + throw new UnsupportedOperationException(); + } + class MaterializedResultWithPlan { private final MaterializedResult materializedResult; diff --git a/presto-main/src/test/java/com/facebook/presto/type/TestBuiltInTypeRegistry.java b/presto-main/src/test/java/com/facebook/presto/type/TestBuiltInTypeRegistry.java index a4f14a3b74095..b5a4b8f49f3d5 100644 --- a/presto-main/src/test/java/com/facebook/presto/type/TestBuiltInTypeRegistry.java +++ b/presto-main/src/test/java/com/facebook/presto/type/TestBuiltInTypeRegistry.java @@ -13,6 +13,7 @@ */ package com.facebook.presto.type; +import com.facebook.presto.UnknownTypeException; import com.facebook.presto.common.type.Type; import com.facebook.presto.common.type.TypeSignature; import com.facebook.presto.metadata.FunctionAndTypeManager; @@ -73,13 +74,13 @@ public void testNonexistentType() { try { functionAndTypeManager.getType(parseTypeSignature("not a real type")); - fail("Expect to throw IllegalArgumentException"); + fail("Expect to throw UnknownTypeException"); } - catch (IllegalArgumentException e) { + catch (UnknownTypeException e) { assertTrue(e.getMessage().matches("Unknown type.*")); } catch (Throwable t) { - fail("Expect to throw IllegalArgumentException, got " + t.getClass()); + fail("Expect to throw UnknownTypeException, got " + t.getClass()); } } diff --git a/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/NativeSidecarPlugin.java b/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/NativeSidecarPlugin.java index 7da7ba4d4fbb9..7ad15da8201ba 100644 --- a/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/NativeSidecarPlugin.java +++ b/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/NativeSidecarPlugin.java @@ -16,10 +16,12 @@ import com.facebook.presto.sidecar.functionNamespace.NativeFunctionNamespaceManagerFactory; import com.facebook.presto.sidecar.nativechecker.NativePlanCheckerProviderFactory; import com.facebook.presto.sidecar.sessionpropertyproviders.NativeSystemSessionPropertyProviderFactory; +import com.facebook.presto.sidecar.typemanager.NativeTypeManagerFactory; import com.facebook.presto.spi.CoordinatorPlugin; import com.facebook.presto.spi.function.FunctionNamespaceManagerFactory; import com.facebook.presto.spi.plan.PlanCheckerProviderFactory; import com.facebook.presto.spi.session.WorkerSessionPropertyProviderFactory; +import com.facebook.presto.spi.type.TypeManagerFactory; import com.google.common.collect.ImmutableList; public class NativeSidecarPlugin @@ -31,6 +33,12 @@ public Iterable getWorkerSessionPropertyPr return ImmutableList.of(new NativeSystemSessionPropertyProviderFactory()); } + @Override + public Iterable getTypeManagerFactories() + { + return ImmutableList.of(new NativeTypeManagerFactory()); + } + @Override public Iterable getPlanCheckerProviderFactories() { diff --git a/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/typemanager/NativeTypeManager.java b/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/typemanager/NativeTypeManager.java new file mode 100644 index 0000000000000..51c46370c46f3 --- /dev/null +++ b/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/typemanager/NativeTypeManager.java @@ -0,0 +1,298 @@ +/* + * 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.sidecar.typemanager; + +import com.facebook.airlift.log.Logger; +import com.facebook.presto.common.type.DistinctTypeInfo; +import com.facebook.presto.common.type.FunctionType; +import com.facebook.presto.common.type.ParametricType; +import com.facebook.presto.common.type.Type; +import com.facebook.presto.common.type.TypeManager; +import com.facebook.presto.common.type.TypeSignature; +import com.facebook.presto.common.type.TypeSignatureParameter; +import com.facebook.presto.common.type.VarcharType; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.util.concurrent.UncheckedExecutionException; +import com.google.inject.Inject; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.function.Function; + +import static com.facebook.presto.common.type.StandardTypes.ARRAY; +import static com.facebook.presto.common.type.StandardTypes.BIGINT; +import static com.facebook.presto.common.type.StandardTypes.BOOLEAN; +import static com.facebook.presto.common.type.StandardTypes.DATE; +import static com.facebook.presto.common.type.StandardTypes.DECIMAL; +import static com.facebook.presto.common.type.StandardTypes.DOUBLE; +import static com.facebook.presto.common.type.StandardTypes.HYPER_LOG_LOG; +import static com.facebook.presto.common.type.StandardTypes.INTEGER; +import static com.facebook.presto.common.type.StandardTypes.INTERVAL_DAY_TO_SECOND; +import static com.facebook.presto.common.type.StandardTypes.INTERVAL_YEAR_TO_MONTH; +import static com.facebook.presto.common.type.StandardTypes.IPADDRESS; +import static com.facebook.presto.common.type.StandardTypes.IPPREFIX; +import static com.facebook.presto.common.type.StandardTypes.JSON; +import static com.facebook.presto.common.type.StandardTypes.MAP; +import static com.facebook.presto.common.type.StandardTypes.REAL; +import static com.facebook.presto.common.type.StandardTypes.ROW; +import static com.facebook.presto.common.type.StandardTypes.SMALLINT; +import static com.facebook.presto.common.type.StandardTypes.TIMESTAMP; +import static com.facebook.presto.common.type.StandardTypes.TIMESTAMP_WITH_TIME_ZONE; +import static com.facebook.presto.common.type.StandardTypes.TINYINT; +import static com.facebook.presto.common.type.StandardTypes.UNKNOWN; +import static com.facebook.presto.common.type.StandardTypes.UUID; +import static com.facebook.presto.common.type.StandardTypes.VARBINARY; +import static com.facebook.presto.common.type.StandardTypes.VARCHAR; +import static com.facebook.presto.common.type.VarcharType.createUnboundedVarcharType; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Throwables.throwIfUnchecked; +import static com.google.common.collect.ImmutableList.toImmutableList; +import static java.util.Objects.requireNonNull; + +public class NativeTypeManager + implements TypeManager +{ + private static final Logger log = Logger.get(NativeTypeManager.class); + + private static final Set NATIVE_ENGINE_SUPPORTED_TYPES = + ImmutableSet.of( + BIGINT, + REAL, + VARBINARY, + TIMESTAMP, + TINYINT, + BOOLEAN, + DATE, + INTEGER, + DOUBLE, + SMALLINT, + HYPER_LOG_LOG, + JSON, + TIMESTAMP_WITH_TIME_ZONE, + UUID, + IPADDRESS, + IPPREFIX, + INTERVAL_DAY_TO_SECOND, + INTERVAL_YEAR_TO_MONTH, + VARCHAR, + UNKNOWN); + + private static final Set NATIVE_ENGINE_SUPPORTED_PARAMETRIC_TYPES = + ImmutableSet.of( + ARRAY, + DECIMAL, + MAP, + ROW, + FunctionType.NAME); + + private final TypeManager typeManager; + private final LoadingCache parametricTypeCache; + private final ConcurrentMap types = new ConcurrentHashMap<>(); + private final ConcurrentMap parametricTypes = new ConcurrentHashMap<>(); + + @Inject + public NativeTypeManager(TypeManager typeManager) + { + this.typeManager = requireNonNull(typeManager, "typeManager is null"); + parametricTypeCache = CacheBuilder.newBuilder() + .maximumSize(1000) + .build(CacheLoader.from(this::instantiateParametricType)); + addAllTypes( + filterSupportedTypes(NATIVE_ENGINE_SUPPORTED_TYPES, typeManager.getTypes(), Type::getDisplayName), + filterSupportedTypes( + NATIVE_ENGINE_SUPPORTED_PARAMETRIC_TYPES, + new ArrayList<>(typeManager.getParametricTypes()), + ParametricType::getName)); + } + + @Override + public Type getType(TypeSignature typeSignature) + { + // Todo: Fix this hack, native execution does not support parameterized varchar type signatures. + if (typeSignature.getBase().equals(VARCHAR)) { + typeSignature = createUnboundedVarcharType().getTypeSignature(); + } + Type type = types.get(typeSignature); + if (type != null) { + return type; + } + try { + return parametricTypeCache.getUnchecked(new ExactTypeSignature(typeSignature)); + } + catch (UncheckedExecutionException e) { + throwIfUnchecked(e.getCause()); + throw new RuntimeException(e.getCause()); + } + } + + @Override + public Collection getParametricTypes() + { + return parametricTypes.values(); + } + + @Override + public List getTypes() + { + return ImmutableList.copyOf(types.values()); + } + + @Override + public Type getParameterizedType(String baseTypeName, List typeParameters) + { + throw new UnsupportedOperationException(); + } + + @Override + public boolean canCoerce(Type actualType, Type expectedType) + { + throw new UnsupportedOperationException(); + } + + private void addAllTypes(List typesList, List parametricTypesList) + { + typesList.forEach(this::addType); + // todo: Fix this hack + // Native engine does not support parameterized varchar, and varchar isn't in the lists of types returned from the engine + addType(VarcharType.VARCHAR); + + parametricTypesList.forEach(this::addParametricType); + } + + private Type instantiateParametricType(ExactTypeSignature exactTypeSignature) + { + return typeManager.instantiateParametricType(exactTypeSignature.getTypeSignature()); + } + + private void addType(Type type) + { + requireNonNull(type, "type is null"); + Type existingType = types.putIfAbsent(type.getTypeSignature(), type); + checkState(existingType == null || existingType.equals(type), "Type %s is already registered", type); + } + + private void addParametricType(ParametricType parametricType) + { + String name = parametricType.getName().toLowerCase(Locale.ENGLISH); + checkArgument(!parametricTypes.containsKey(name), "Parametric type already registered: %s", name); + parametricTypes.putIfAbsent(name, parametricType); + } + + private static List filterSupportedTypes( + Set actualTypes, + List types, + Function typeSignatureExtractor) + { + return types.stream() + .filter(type -> actualTypes.contains(typeSignatureExtractor.apply(type))) + .collect(toImmutableList()); + } + + /** + * TypeSignature has overridden equals(). Here, we compare exact signature of any underlying distinct + * types. Some distinct types may have extra information on their lazily loaded parents, and same parent + * information is compared in equals(). This is needed to cache types in parametricTypesCache. + */ + private static class ExactTypeSignature + { + private final TypeSignature typeSignature; + + public ExactTypeSignature(TypeSignature typeSignature) + { + this.typeSignature = typeSignature; + } + + public TypeSignature getTypeSignature() + { + return typeSignature; + } + + @Override + public int hashCode() + { + return Objects.hash(typeSignature); + } + + @Override + public boolean equals(Object o) + { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ExactTypeSignature other = (ExactTypeSignature) o; + return equals(typeSignature, other.typeSignature); + } + + private static boolean equals(TypeSignature left, TypeSignature right) + { + if (!left.equals(right)) { + return false; + } + + if (left.isDistinctType() && right.isDistinctType()) { + return equals(left.getDistinctTypeInfo(), right.getDistinctTypeInfo()); + } + int index = 0; + for (TypeSignatureParameter leftParameter : left.getParameters()) { + TypeSignatureParameter rightParameter = right.getParameters().get(index++); + if (!leftParameter.getKind().equals(rightParameter.getKind())) { + return false; + } + + switch (leftParameter.getKind()) { + case TYPE: + if (!equals(leftParameter.getTypeSignature(), rightParameter.getTypeSignature())) { + return false; + } + break; + case NAMED_TYPE: + if (!equals(leftParameter.getNamedTypeSignature().getTypeSignature(), rightParameter.getNamedTypeSignature().getTypeSignature())) { + return false; + } + break; + case DISTINCT_TYPE: + if (!equals(leftParameter.getDistinctTypeInfo(), rightParameter.getDistinctTypeInfo())) { + return false; + } + break; + } + } + return true; + } + + private static boolean equals(DistinctTypeInfo left, DistinctTypeInfo right) + { + return Objects.equals(left.getName(), right.getName()) && + Objects.equals(left.getBaseType(), right.getBaseType()) && + Objects.equals(left.isOrderable(), right.isOrderable()) && + Objects.equals(left.getTopMostAncestor(), right.getTopMostAncestor()) && + Objects.equals(left.getOtherAncestors(), right.getOtherAncestors()); + } + } +} diff --git a/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/typemanager/NativeTypeManagerFactory.java b/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/typemanager/NativeTypeManagerFactory.java new file mode 100644 index 0000000000000..7a76d8500ef5c --- /dev/null +++ b/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/typemanager/NativeTypeManagerFactory.java @@ -0,0 +1,45 @@ +/* + * 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.sidecar.typemanager; + +import com.facebook.airlift.bootstrap.Bootstrap; +import com.facebook.presto.common.type.TypeManager; +import com.facebook.presto.spi.type.TypeManagerContext; +import com.facebook.presto.spi.type.TypeManagerFactory; +import com.google.inject.Injector; + +public class NativeTypeManagerFactory + implements TypeManagerFactory +{ + public static final String NAME = "native"; + + @Override + public String getName() + { + return NAME; + } + + @Override + public TypeManager create(TypeManagerContext context) + { + Bootstrap app = new Bootstrap( + new NativeTypeManagerModule(context.getTypeManager())); + + Injector injector = app + .doNotInitializeLogging() + .noStrictConfig() + .initialize(); + return injector.getInstance(NativeTypeManager.class); + } +} diff --git a/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/typemanager/NativeTypeManagerModule.java b/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/typemanager/NativeTypeManagerModule.java new file mode 100644 index 0000000000000..7af6127c681d9 --- /dev/null +++ b/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/typemanager/NativeTypeManagerModule.java @@ -0,0 +1,39 @@ +/* + * 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.sidecar.typemanager; + +import com.facebook.presto.common.type.TypeManager; +import com.google.inject.Binder; +import com.google.inject.Module; +import com.google.inject.Scopes; + +import static java.util.Objects.requireNonNull; + +public class NativeTypeManagerModule + implements Module +{ + private final TypeManager typeManager; + + public NativeTypeManagerModule(TypeManager typeManager) + { + this.typeManager = requireNonNull(typeManager, "typeManager is null"); + } + + @Override + public void configure(Binder binder) + { + binder.bind(TypeManager.class).toInstance(typeManager); + binder.bind(NativeTypeManager.class).in(Scopes.SINGLETON); + } +} diff --git a/presto-native-sidecar-plugin/src/test/java/com/facebook/presto/sidecar/NativeSidecarPluginQueryRunnerUtils.java b/presto-native-sidecar-plugin/src/test/java/com/facebook/presto/sidecar/NativeSidecarPluginQueryRunnerUtils.java index 994d824195600..28a82820d394a 100644 --- a/presto-native-sidecar-plugin/src/test/java/com/facebook/presto/sidecar/NativeSidecarPluginQueryRunnerUtils.java +++ b/presto-native-sidecar-plugin/src/test/java/com/facebook/presto/sidecar/NativeSidecarPluginQueryRunnerUtils.java @@ -15,6 +15,7 @@ import com.facebook.presto.sidecar.functionNamespace.NativeFunctionNamespaceManagerFactory; import com.facebook.presto.sidecar.sessionpropertyproviders.NativeSystemSessionPropertyProviderFactory; +import com.facebook.presto.sidecar.typemanager.NativeTypeManagerFactory; import com.facebook.presto.testing.QueryRunner; import com.google.common.collect.ImmutableMap; @@ -32,5 +33,6 @@ public static void setupNativeSidecarPlugin(QueryRunner queryRunner) ImmutableMap.of( "supported-function-languages", "CPP", "function-implementation-type", "CPP")); + queryRunner.loadTypeManager(NativeTypeManagerFactory.NAME); } } diff --git a/presto-native-sidecar-plugin/src/test/java/com/facebook/presto/sidecar/TestNativeSystemSessionPropertyProviderConfig.java b/presto-native-sidecar-plugin/src/test/java/com/facebook/presto/sidecar/sessionpropertyproviders/TestNativeSystemSessionPropertyProviderConfig.java similarity index 92% rename from presto-native-sidecar-plugin/src/test/java/com/facebook/presto/sidecar/TestNativeSystemSessionPropertyProviderConfig.java rename to presto-native-sidecar-plugin/src/test/java/com/facebook/presto/sidecar/sessionpropertyproviders/TestNativeSystemSessionPropertyProviderConfig.java index 6784928044478..7cb12c8480699 100644 --- a/presto-native-sidecar-plugin/src/test/java/com/facebook/presto/sidecar/TestNativeSystemSessionPropertyProviderConfig.java +++ b/presto-native-sidecar-plugin/src/test/java/com/facebook/presto/sidecar/sessionpropertyproviders/TestNativeSystemSessionPropertyProviderConfig.java @@ -11,9 +11,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.facebook.presto.sidecar; +package com.facebook.presto.sidecar.sessionpropertyproviders; -import com.facebook.presto.sidecar.sessionpropertyproviders.NativeSystemSessionPropertyProviderConfig; import com.google.common.collect.ImmutableMap; import io.airlift.units.Duration; import org.testng.annotations.Test; diff --git a/presto-spi/src/main/java/com/facebook/presto/spi/CoordinatorPlugin.java b/presto-spi/src/main/java/com/facebook/presto/spi/CoordinatorPlugin.java index ca8ea46d58aa6..6b82a6ae2b64e 100644 --- a/presto-spi/src/main/java/com/facebook/presto/spi/CoordinatorPlugin.java +++ b/presto-spi/src/main/java/com/facebook/presto/spi/CoordinatorPlugin.java @@ -17,6 +17,7 @@ import com.facebook.presto.spi.plan.PlanCheckerProviderFactory; import com.facebook.presto.spi.session.WorkerSessionPropertyProviderFactory; import com.facebook.presto.spi.sql.planner.ExpressionOptimizerFactory; +import com.facebook.presto.spi.type.TypeManagerFactory; import static java.util.Collections.emptyList; @@ -46,4 +47,9 @@ default Iterable getExpressionOptimizerFactories() { return emptyList(); } + + default Iterable getTypeManagerFactories() + { + return emptyList(); + } } diff --git a/presto-spi/src/main/java/com/facebook/presto/spi/StandardErrorCode.java b/presto-spi/src/main/java/com/facebook/presto/spi/StandardErrorCode.java index 90856f013d874..07be6b8d2b186 100644 --- a/presto-spi/src/main/java/com/facebook/presto/spi/StandardErrorCode.java +++ b/presto-spi/src/main/java/com/facebook/presto/spi/StandardErrorCode.java @@ -74,6 +74,7 @@ public enum StandardErrorCode VIEW_NOT_FOUND(0x0000_0030, USER_ERROR), INVALID_LIMIT_CLAUSE(0x0000_0031, USER_ERROR), COLUMN_NOT_FOUND(0x0000_0032, USER_ERROR), + UNKNOWN_TYPE(0x0000_0033, USER_ERROR), GENERIC_INTERNAL_ERROR(0x0001_0000, INTERNAL_ERROR), TOO_MANY_REQUESTS_FAILED(0x0001_0001, INTERNAL_ERROR, true), diff --git a/presto-spi/src/main/java/com/facebook/presto/spi/type/TypeManagerContext.java b/presto-spi/src/main/java/com/facebook/presto/spi/type/TypeManagerContext.java new file mode 100644 index 0000000000000..075c3ba2414d6 --- /dev/null +++ b/presto-spi/src/main/java/com/facebook/presto/spi/type/TypeManagerContext.java @@ -0,0 +1,33 @@ +/* + * 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.spi.type; + +import com.facebook.presto.common.type.TypeManager; + +import static java.util.Objects.requireNonNull; + +public class TypeManagerContext +{ + private final TypeManager typeManager; + + public TypeManagerContext(TypeManager typeManager) + { + this.typeManager = requireNonNull(typeManager, "typeManager is null"); + } + + public TypeManager getTypeManager() + { + return typeManager; + } +} diff --git a/presto-spi/src/main/java/com/facebook/presto/spi/type/TypeManagerFactory.java b/presto-spi/src/main/java/com/facebook/presto/spi/type/TypeManagerFactory.java new file mode 100644 index 0000000000000..7f82a527ea864 --- /dev/null +++ b/presto-spi/src/main/java/com/facebook/presto/spi/type/TypeManagerFactory.java @@ -0,0 +1,23 @@ +/* + * 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.spi.type; + +import com.facebook.presto.common.type.TypeManager; + +public interface TypeManagerFactory +{ + String getName(); + + TypeManager create(TypeManagerContext context); +} diff --git a/presto-tests/src/main/java/com/facebook/presto/tests/DistributedQueryRunner.java b/presto-tests/src/main/java/com/facebook/presto/tests/DistributedQueryRunner.java index b3f25630cb078..e8006ee02268c 100644 --- a/presto-tests/src/main/java/com/facebook/presto/tests/DistributedQueryRunner.java +++ b/presto-tests/src/main/java/com/facebook/presto/tests/DistributedQueryRunner.java @@ -994,6 +994,14 @@ public void loadSessionPropertyProvider(String sessionPropertyProviderName) } } + @Override + public void loadTypeManager(String typeManagerName) + { + for (TestingPrestoServer server : servers) { + server.getMetadata().getFunctionAndTypeManager().loadTypeManager(typeManagerName); + } + } + private static void closeUnchecked(AutoCloseable closeable) { try {