diff --git a/presto-main/src/main/java/com/facebook/presto/metadata/BuiltInFunctionNamespaceManager.java b/presto-main/src/main/java/com/facebook/presto/metadata/BuiltInFunctionNamespaceManager.java index 3f05b71a1d311..07737b9c97640 100644 --- a/presto-main/src/main/java/com/facebook/presto/metadata/BuiltInFunctionNamespaceManager.java +++ b/presto-main/src/main/java/com/facebook/presto/metadata/BuiltInFunctionNamespaceManager.java @@ -361,7 +361,7 @@ public class BuiltInFunctionNamespaceManager implements FunctionNamespaceManager { public static final CatalogSchemaName DEFAULT_NAMESPACE = new CatalogSchemaName("presto", "default"); - public static final String NAME = "_builtin"; + public static final String ID = "builtin"; private final TypeManager typeManager; private final LoadingCache specializedFunctionKeyCache; @@ -705,7 +705,7 @@ public void dropFunction(QualifiedFunctionName functionName, Optional functionNamespaceManagerFactories = new ConcurrentHashMap<>(); private final HandleResolver handleResolver; - private final Map> functionNamespaces = new ConcurrentHashMap<>(); + private final Map functionNamespaces = new ConcurrentHashMap<>(); + private final Map> functionNamespaceManagers = new ConcurrentHashMap<>(); private final boolean listNonBuiltInFunctions; @@ -111,14 +112,15 @@ public FunctionManager( this.typeManager = requireNonNull(typeManager, "typeManager is null"); this.transactionManager = requireNonNull(transactionManager, "transactionManager is null"); this.builtInFunctionNamespaceManager = new BuiltInFunctionNamespaceManager(typeManager, blockEncodingSerde, featuresConfig, this); - this.functionNamespaces.put(DEFAULT_NAMESPACE.asCatalogSchemaPrefix(), builtInFunctionNamespaceManager); + this.functionNamespaces.put(DEFAULT_NAMESPACE.asCatalogSchemaPrefix(), BuiltInFunctionNamespaceManager.ID); + this.functionNamespaceManagers.put(BuiltInFunctionNamespaceManager.ID, builtInFunctionNamespaceManager); this.functionInvokerProvider = new FunctionInvokerProvider(this); this.handleResolver = handleResolver; if (typeManager instanceof TypeRegistry) { ((TypeRegistry) typeManager).setFunctionManager(this); } // TODO: Provide a more encapsulated way for TransactionManager to register FunctionNamespaceManager - transactionManager.registerFunctionNamespaceManager(BuiltInFunctionNamespaceManager.NAME, builtInFunctionNamespaceManager); + transactionManager.registerFunctionNamespaceManager(BuiltInFunctionNamespaceManager.ID, builtInFunctionNamespaceManager); this.listNonBuiltInFunctions = featuresConfig.isListNonBuiltInFunctions(); } @@ -129,17 +131,24 @@ public FunctionManager(TypeManager typeManager, BlockEncodingSerde blockEncoding this(typeManager, createTestTransactionManager(), blockEncodingSerde, featuresConfig, new HandleResolver()); } - public void loadFunctionNamespaces(String functionNamespaceManagerName, List catalogSchemaPrefixes, Map properties) + public void loadFunctionNamespaceManager( + String functionNamespaceManagerName, + String functionNamespaceManagerId, + List catalogSchemaPrefixes, + Map properties) { - requireNonNull(functionNamespaceManagerName, "connectorName is null"); + requireNonNull(functionNamespaceManagerName, "functionNamespaceManagerName is null"); FunctionNamespaceManagerFactory factory = functionNamespaceManagerFactories.get(functionNamespaceManagerName); - checkState(factory != null, "No function namespace manager for %s", functionNamespaceManagerName); + checkState(factory != null, "No factory for function namespace manager %s", functionNamespaceManagerName); FunctionNamespaceManager functionNamespaceManager = factory.create(properties); - transactionManager.registerFunctionNamespaceManager(functionNamespaceManagerName, functionNamespaceManager); + transactionManager.registerFunctionNamespaceManager(functionNamespaceManagerId, functionNamespaceManager); + if (functionNamespaceManagers.putIfAbsent(functionNamespaceManagerId, functionNamespaceManager) != null) { + throw new IllegalArgumentException(format("Function namespace manager [%s] is already registered", functionNamespaceManagerId)); + } for (String catalogSchemaPrefix : catalogSchemaPrefixes) { - if (functionNamespaces.putIfAbsent(CatalogSchemaPrefix.of(catalogSchemaPrefix), functionNamespaceManager) != null) { - throw new IllegalArgumentException(format("Function namespace manager '%s' already registered to handle function namespace '%s'", factory.getName(), catalogSchemaPrefix)); + if (functionNamespaces.putIfAbsent(CatalogSchemaPrefix.of(catalogSchemaPrefix), functionNamespaceManagerId) != null) { + throw new IllegalArgumentException(format("Function namespace [%s] is already registered to function namespace manager [%s]", catalogSchemaPrefix, functionNamespaceManagerId)); } } } @@ -164,11 +173,11 @@ public void registerBuiltInFunctions(List functions) public List listFunctions() { - Set> functionNamespaceManagers = listNonBuiltInFunctions ? - ImmutableSet.copyOf(functionNamespaces.values()) : + Collection> managers = listNonBuiltInFunctions ? + functionNamespaceManagers.values() : ImmutableSet.of(builtInFunctionNamespaceManager); - return functionNamespaceManagers.stream() + return managers.stream() .flatMap(manager -> manager.listFunctions().stream()) .filter(function -> !function.isHidden()) .collect(toImmutableList()); @@ -220,17 +229,18 @@ public FunctionHandle resolveFunction(Optional transactionId, Qua public FunctionHandle resolveFunction(Optional transactionId, QualifiedFunctionName functionName, List parameterTypes) { - Optional> functionNamespaceManager = getServingFunctionNamespaceManager(functionName.getFunctionNamespace()); - if (!functionNamespaceManager.isPresent()) { + Optional functionNamespaceManagerId = getServingFunctionNamespaceManagerId(functionName.getFunctionNamespace()); + if (!functionNamespaceManagerId.isPresent()) { throw new PrestoException(FUNCTION_NOT_FOUND, constructFunctionNotFoundErrorMessage(functionName, parameterTypes, ImmutableList.of())); } Optional transactionHandle = transactionId - .map(id -> transactionManager.getFunctionNamespaceTransaction(id, functionNamespaceManager.get().getName())); - Collection candidates = functionNamespaceManager.get().getFunctions(transactionHandle, functionName); + .map(id -> transactionManager.getFunctionNamespaceTransaction(id, functionNamespaceManagerId.get())); + FunctionNamespaceManager functionNamespaceManager = functionNamespaceManagers.get(functionNamespaceManagerId.get()); + Collection candidates = functionNamespaceManager.getFunctions(transactionHandle, functionName); try { - return lookupFunction(functionNamespaceManager.get(), transactionHandle, functionName, parameterTypes, candidates); + return lookupFunction(functionNamespaceManager, transactionHandle, functionName, parameterTypes, candidates); } catch (PrestoException e) { if (e.getErrorCode().getCode() != FUNCTION_NOT_FOUND.toErrorCode().getCode()) { @@ -240,7 +250,7 @@ public FunctionHandle resolveFunction(Optional transactionId, Qua Optional match = matchFunctionWithCoercion(candidates, parameterTypes); if (match.isPresent()) { - return functionNamespaceManager.get().getFunctionHandle(transactionHandle, match.get()); + return functionNamespaceManager.getFunctionHandle(transactionHandle, match.get()); } if (functionName.getFunctionName().startsWith(MAGIC_LITERAL_FUNCTION_PREFIX)) { @@ -378,22 +388,27 @@ private FunctionHandle lookupFunction( } private Optional> getServingFunctionNamespaceManager(CatalogSchemaName functionNamespace) + { + return getServingFunctionNamespaceManagerId(functionNamespace).map(functionNamespaceManagers::get); + } + + private Optional getServingFunctionNamespaceManagerId(CatalogSchemaName functionNamespace) { if (functionNamespace.equals(DEFAULT_NAMESPACE)) { - return Optional.of(builtInFunctionNamespaceManager); + return Optional.of(BuiltInFunctionNamespaceManager.ID); } CatalogSchemaPrefix bestMatch = null; - FunctionNamespaceManager servingFunctionNamespaceManager = null; + String servingFunctionNamespaceManagerId = null; - for (Map.Entry> entry : functionNamespaces.entrySet()) { + for (Map.Entry entry : functionNamespaces.entrySet()) { CatalogSchemaPrefix prefix = entry.getKey(); if (prefix.includes(functionNamespace) && (bestMatch == null || bestMatch.includes(prefix))) { bestMatch = prefix; - servingFunctionNamespaceManager = entry.getValue(); + servingFunctionNamespaceManagerId = entry.getValue(); } } - return Optional.ofNullable(servingFunctionNamespaceManager); + return Optional.ofNullable(servingFunctionNamespaceManagerId); } private String constructFunctionNotFoundErrorMessage(QualifiedFunctionName functionName, List parameterTypes, Collection candidates) diff --git a/presto-main/src/main/java/com/facebook/presto/metadata/StaticFunctionNamespaceStore.java b/presto-main/src/main/java/com/facebook/presto/metadata/StaticFunctionNamespaceStore.java index f28fd7342bf58..d5004d5f077fb 100644 --- a/presto-main/src/main/java/com/facebook/presto/metadata/StaticFunctionNamespaceStore.java +++ b/presto-main/src/main/java/com/facebook/presto/metadata/StaticFunctionNamespaceStore.java @@ -27,6 +27,7 @@ import static com.facebook.presto.util.PropertiesUtil.loadProperties; import static com.google.common.base.Preconditions.checkState; +import static com.google.common.io.Files.getNameWithoutExtension; public class StaticFunctionNamespaceStore { @@ -61,14 +62,19 @@ public void loadFunctionNamespaceManagers() private void loadFunctionNamespaceManager(File file) throws Exception { - log.info("-- Loading function namespace from %s --", file); + String functionNamespaceManagerId = getNameWithoutExtension(file.getName()); + + log.info("-- Loading function namespace manager from %s --", file); Map properties = new HashMap<>(loadProperties(file)); + String functionNamespaceManagerName = properties.remove("function-namespace-manager.name"); checkState(functionNamespaceManagerName != null, "Function namespace configuration %s does not contain function-namespace-manager.name", file.getAbsoluteFile()); + String functionNamespaces = properties.remove("serving-namespaces"); checkState(functionNamespaces != null, "Function namespace configuration %s does not contain serving-namespaces", file.getAbsoluteFile()); - functionManager.loadFunctionNamespaces(functionNamespaceManagerName, SPLITTER.splitToList(functionNamespaces), properties); - log.info("-- Added function namespace %s managed by function manager %s --", functionNamespaces, functionNamespaceManagerName); + + functionManager.loadFunctionNamespaceManager(functionNamespaceManagerName, functionNamespaceManagerId, SPLITTER.splitToList(functionNamespaces), properties); + log.info("-- Added function namespaces [%s] using function namespace manager [%s] --", functionNamespaces, functionNamespaceManagerId); } private static List listFiles(File dir) diff --git a/presto-main/src/main/java/com/facebook/presto/testing/InMemoryFunctionNamespaceManager.java b/presto-main/src/main/java/com/facebook/presto/testing/InMemoryFunctionNamespaceManager.java index 1b46b28e25b03..605b5820905c1 100644 --- a/presto-main/src/main/java/com/facebook/presto/testing/InMemoryFunctionNamespaceManager.java +++ b/presto-main/src/main/java/com/facebook/presto/testing/InMemoryFunctionNamespaceManager.java @@ -42,8 +42,6 @@ public class InMemoryFunctionNamespaceManager extends AbstractSqlInvokedFunctionNamespaceManager { - private static final String NAME = "_in_memory"; - private final Map latestFunctions = new ConcurrentHashMap<>(); public InMemoryFunctionNamespaceManager(SqlInvokedFunctionNamespaceManagerConfig config) @@ -51,12 +49,6 @@ public InMemoryFunctionNamespaceManager(SqlInvokedFunctionNamespaceManagerConfig super(config); } - @Override - public String getName() - { - return NAME; - } - @Override public synchronized void createFunction(SqlInvokedFunction function, boolean replace) { diff --git a/presto-main/src/main/java/com/facebook/presto/transaction/InMemoryTransactionManager.java b/presto-main/src/main/java/com/facebook/presto/transaction/InMemoryTransactionManager.java index 991c98e531c94..02f18f5cc2c9c 100644 --- a/presto-main/src/main/java/com/facebook/presto/transaction/InMemoryTransactionManager.java +++ b/presto-main/src/main/java/com/facebook/presto/transaction/InMemoryTransactionManager.java @@ -235,16 +235,16 @@ public ConnectorTransactionHandle getConnectorTransaction(TransactionId transact } @Override - public synchronized void registerFunctionNamespaceManager(String functionNamespaceManagerName, FunctionNamespaceManager functionNamespaceManager) + public synchronized void registerFunctionNamespaceManager(String functionNamespaceManagerId, FunctionNamespaceManager functionNamespaceManager) { - checkArgument(!functionNamespaceManagers.containsKey(functionNamespaceManagerName), "FunctionNamespaceManager %s is already registered", functionNamespaceManagerName); - functionNamespaceManagers.put(functionNamespaceManagerName, functionNamespaceManager); + checkArgument(!functionNamespaceManagers.containsKey(functionNamespaceManagerId), "FunctionNamespaceManager %s is already registered", functionNamespaceManagerId); + functionNamespaceManagers.put(functionNamespaceManagerId, functionNamespaceManager); } @Override - public FunctionNamespaceTransactionHandle getFunctionNamespaceTransaction(TransactionId transactionId, String functionNamespaceManagerName) + public FunctionNamespaceTransactionHandle getFunctionNamespaceTransaction(TransactionId transactionId, String functionNamespaceManagerId) { - return getTransactionMetadata(transactionId).getFunctionNamespaceTransaction(functionNamespaceManagerName).getTransactionHandle(); + return getTransactionMetadata(transactionId).getFunctionNamespaceTransaction(functionNamespaceManagerId).getTransactionHandle(); } private void checkConnectorWrite(TransactionId transactionId, ConnectorId connectorId) @@ -472,14 +472,14 @@ private synchronized CatalogMetadata getTransactionCatalogMetadata(ConnectorId c return catalogMetadata; } - private synchronized FunctionNamespaceTransactionMetadata getFunctionNamespaceTransaction(String functionNamespaceManagerName) + private synchronized FunctionNamespaceTransactionMetadata getFunctionNamespaceTransaction(String functionNamespaceManagerId) { checkOpenTransaction(); return functionNamespaceTransactions.computeIfAbsent( - functionNamespaceManagerName, name -> { - verify(name != null, "Unknown function namespace manager: %s", name); - FunctionNamespaceManager functionNamespaceManager = functionNamespaceManagers.get(name); + functionNamespaceManagerId, id -> { + verify(id != null, "Unknown function namespace manager: %s", id); + FunctionNamespaceManager functionNamespaceManager = functionNamespaceManagers.get(id); FunctionNamespaceTransactionHandle transactionHandle = functionNamespaceManager.beginTransaction(); return new FunctionNamespaceTransactionMetadata(functionNamespaceManager, transactionHandle); }); diff --git a/presto-spi/src/main/java/com/facebook/presto/spi/function/FunctionNamespaceManager.java b/presto-spi/src/main/java/com/facebook/presto/spi/function/FunctionNamespaceManager.java index a70c93ac1fab3..035a9e155aa55 100644 --- a/presto-spi/src/main/java/com/facebook/presto/spi/function/FunctionNamespaceManager.java +++ b/presto-spi/src/main/java/com/facebook/presto/spi/function/FunctionNamespaceManager.java @@ -23,8 +23,6 @@ @Experimental public interface FunctionNamespaceManager { - String getName(); - /** * Start a transaction. */