diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/dao/CatalogDao.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/dao/CatalogDao.java new file mode 100644 index 000000000..9a0524d89 --- /dev/null +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/dao/CatalogDao.java @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.polaris.core.persistence.dao; + +public interface CatalogDao {} diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/dao/NamespaceDao.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/dao/NamespaceDao.java new file mode 100644 index 000000000..c249b841c --- /dev/null +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/dao/NamespaceDao.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.polaris.core.persistence.dao; + +import java.util.List; +import org.apache.iceberg.catalog.Namespace; +import org.apache.polaris.core.entity.NamespaceEntity; +import org.apache.polaris.core.entity.PolarisEntity; +import org.apache.polaris.core.entity.PolarisEntityCore; + +public interface NamespaceDao { + void save(NamespaceEntity namespace, List catalogPath); + + void update(NamespaceEntity namespace, List catalogPath); + + NamespaceEntity get(String namespaceId); + + NamespaceEntity get(Namespace namespace); + + boolean delete(List catalogPath, PolarisEntity leafEntity, boolean cleanup); +} diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAuthzTestBase.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAuthzTestBase.java index c51081fc7..15847a3af 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAuthzTestBase.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAuthzTestBase.java @@ -68,6 +68,7 @@ import org.apache.polaris.core.persistence.PolarisEntityManager; import org.apache.polaris.core.persistence.PolarisMetaStoreManager; import org.apache.polaris.core.persistence.PolarisMetaStoreSession; +import org.apache.polaris.core.persistence.dao.NamespaceDao; import org.apache.polaris.core.persistence.resolver.PolarisResolutionManifest; import org.apache.polaris.service.admin.PolarisAdminService; import org.apache.polaris.service.catalog.BasePolarisCatalog; @@ -77,6 +78,7 @@ import org.apache.polaris.service.config.DefaultConfigurationStore; import org.apache.polaris.service.config.RealmEntityManagerFactory; import org.apache.polaris.service.context.PolarisCallContextCatalogFactory; +import org.apache.polaris.service.persistence.fdb.dao.FdbNamespaceDao; import org.apache.polaris.service.storage.PolarisStorageIntegrationProviderImpl; import org.apache.polaris.service.task.TaskExecutor; import org.assertj.core.api.Assertions; @@ -177,6 +179,7 @@ public Map getConfigOverrides() { protected PrincipalEntity principalEntity; protected RealmContext realmContext; protected AuthenticatedPolarisPrincipal authenticatedRoot; + protected NamespaceDao namespaceDao; @BeforeAll public static void setUpMocks() { @@ -194,6 +197,7 @@ public void before(TestInfo testInfo) { metaStoreManager = managerFactory.getOrCreateMetaStoreManager(realmContext); metaStoreSession = managerFactory.getOrCreateSessionSupplier(realmContext).get(); entityManager = realmEntityManagerFactory.getOrCreateEntityManager(realmContext); + namespaceDao = new FdbNamespaceDao(metaStoreManager, metaStoreSession); PrincipalEntity rootEntity = new PrincipalEntity( @@ -409,7 +413,8 @@ private void initBaseCatalog() { passthroughView, securityContext, Mockito.mock(), - fileIOFactory); + fileIOFactory, + namespaceDao); this.baseCatalog.initialize( CATALOG_NAME, ImmutableMap.of( @@ -422,7 +427,7 @@ public static class TestPolarisCallContextCatalogFactory extends PolarisCallContextCatalogFactory { public TestPolarisCallContextCatalogFactory() { - super(null, null, null, null, null, null, null); + super(null, null, null, null, null, null, null, null); } @Inject @@ -433,7 +438,8 @@ public TestPolarisCallContextCatalogFactory( PolarisConfigurationStore configurationStore, PolarisDiagnostics diagnostics, TaskExecutor taskExecutor, - FileIOFactory fileIOFactory) { + FileIOFactory fileIOFactory, + NamespaceDao namespaceDao) { super( entityManager, metaStoreManager, @@ -441,7 +447,8 @@ public TestPolarisCallContextCatalogFactory( configurationStore, diagnostics, taskExecutor, - fileIOFactory); + fileIOFactory, + namespaceDao); } @Override diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/BasePolarisCatalogTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/BasePolarisCatalogTest.java index 977411769..ee8e6cf13 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/BasePolarisCatalogTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/BasePolarisCatalogTest.java @@ -87,6 +87,7 @@ import org.apache.polaris.core.persistence.PolarisMetaStoreSession; import org.apache.polaris.core.persistence.bootstrap.RootCredentialsSet; import org.apache.polaris.core.persistence.cache.EntityCache; +import org.apache.polaris.core.persistence.dao.NamespaceDao; import org.apache.polaris.core.storage.PolarisCredentialProperty; import org.apache.polaris.core.storage.PolarisStorageIntegration; import org.apache.polaris.core.storage.PolarisStorageIntegrationProvider; @@ -101,6 +102,7 @@ import org.apache.polaris.service.catalog.io.MeasuredFileIOFactory; import org.apache.polaris.service.config.RealmEntityManagerFactory; import org.apache.polaris.service.exception.IcebergExceptionMapper; +import org.apache.polaris.service.persistence.fdb.dao.FdbNamespaceDao; import org.apache.polaris.service.storage.PolarisStorageIntegrationProviderImpl; import org.apache.polaris.service.task.TableCleanupTaskHandler; import org.apache.polaris.service.task.TaskExecutor; @@ -161,6 +163,7 @@ public Map getConfigOverrides() { private RealmContext realmContext; private PolarisMetaStoreManager metaStoreManager; private PolarisMetaStoreSession metaStoreSession; + private NamespaceDao namespaceDao; private PolarisAdminService adminService; private PolarisEntityManager entityManager; private FileIOFactory fileIOFactory; @@ -186,6 +189,7 @@ public void before(TestInfo testInfo) { realmContext = () -> realmName; metaStoreManager = managerFactory.getOrCreateMetaStoreManager(realmContext); metaStoreSession = managerFactory.getOrCreateSessionSupplier(realmContext).get(); + namespaceDao = new FdbNamespaceDao(metaStoreManager, metaStoreSession); entityManager = entityManagerFactory.getOrCreateEntityManager(realmContext); PrincipalEntity rootEntity = @@ -273,7 +277,8 @@ public void before(TestInfo testInfo) { passthroughView, securityContext, taskExecutor, - fileIOFactory); + fileIOFactory, + namespaceDao); this.catalog.initialize( CATALOG_NAME, ImmutableMap.of( @@ -528,7 +533,8 @@ public void testValidateNotificationFailToCreateFileIO() throws IOException { passthroughView, securityContext, Mockito.mock(), - fileIoFactory); + fileIoFactory, + namespaceDao); catalog.initialize( CATALOG_NAME, ImmutableMap.of( @@ -856,7 +862,8 @@ public void testUpdateNotificationCreateTableWithLocalFilePrefix() { passthroughView, securityContext, taskExecutor, - fileIOFactory); + fileIOFactory, + namespaceDao); catalog.initialize( catalogWithoutStorage, ImmutableMap.of( @@ -921,7 +928,8 @@ public void testUpdateNotificationCreateTableWithHttpPrefix() { passthroughView, securityContext, taskExecutor, - fileIOFactory); + fileIOFactory, + namespaceDao); catalog.initialize( catalogName, ImmutableMap.of( @@ -1454,7 +1462,8 @@ public void testDropTableWithPurgeDisabled() { passthroughView, securityContext, Mockito.mock(), - fileIOFactory); + fileIOFactory, + namespaceDao); noPurgeCatalog.initialize( noPurgeCatalogName, ImmutableMap.of( @@ -1539,7 +1548,8 @@ public void testFileIOWrapper() { passthroughView, securityContext, Mockito.mock(), - measured); + measured, + namespaceDao); catalog.initialize( CATALOG_NAME, ImmutableMap.of( diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/BasePolarisCatalogViewTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/BasePolarisCatalogViewTest.java index c86cf9926..4eb0d5c37 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/BasePolarisCatalogViewTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/BasePolarisCatalogViewTest.java @@ -54,12 +54,14 @@ import org.apache.polaris.core.persistence.PolarisEntityManager; import org.apache.polaris.core.persistence.PolarisMetaStoreManager; import org.apache.polaris.core.persistence.PolarisMetaStoreSession; +import org.apache.polaris.core.persistence.dao.NamespaceDao; import org.apache.polaris.service.admin.PolarisAdminService; import org.apache.polaris.service.catalog.BasePolarisCatalog; import org.apache.polaris.service.catalog.PolarisPassthroughResolutionView; import org.apache.polaris.service.catalog.io.DefaultFileIOFactory; import org.apache.polaris.service.catalog.io.FileIOFactory; import org.apache.polaris.service.config.RealmEntityManagerFactory; +import org.apache.polaris.service.persistence.fdb.dao.FdbNamespaceDao; import org.apache.polaris.service.storage.PolarisStorageIntegrationProviderImpl; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -101,6 +103,7 @@ public Map getConfigOverrides() { private PolarisMetaStoreManager metaStoreManager; private PolarisMetaStoreSession metaStoreSession; + private NamespaceDao namespaceDao; @BeforeAll public static void setUpMocks() { @@ -127,6 +130,7 @@ public void before(TestInfo testInfo) { metaStoreManager = managerFactory.getOrCreateMetaStoreManager(realmContext); metaStoreSession = managerFactory.getOrCreateSessionSupplier(realmContext).get(); + namespaceDao = new FdbNamespaceDao(metaStoreManager, metaStoreSession); PrincipalEntity rootEntity = new PrincipalEntity( @@ -187,7 +191,8 @@ public void before(TestInfo testInfo) { passthroughView, securityContext, Mockito.mock(), - fileIOFactory); + fileIOFactory, + namespaceDao); this.catalog.initialize( CATALOG_NAME, ImmutableMap.of( diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisCatalogHandlerWrapperAuthzTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisCatalogHandlerWrapperAuthzTest.java index 6ba5cef12..bbece1131 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisCatalogHandlerWrapperAuthzTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisCatalogHandlerWrapperAuthzTest.java @@ -136,7 +136,8 @@ private CallContextCatalogFactory newCatalogFactory() { configurationStore, diagServices, Mockito.mock(), - fileIOFactory); + fileIOFactory, + namespaceDao); } /** @@ -1711,8 +1712,8 @@ public void testSendNotificationSufficientPrivileges() { configurationStore, diagServices, Mockito.mock(), - new DefaultFileIOFactory( - realmEntityManagerFactory, managerFactory, configurationStore)) { + new DefaultFileIOFactory(realmEntityManagerFactory, managerFactory, configurationStore), + namespaceDao) { @Override public Catalog createCallContextCatalog( RealmContext realmContext, diff --git a/service/common/src/main/java/org/apache/polaris/service/catalog/BasePolarisCatalog.java b/service/common/src/main/java/org/apache/polaris/service/catalog/BasePolarisCatalog.java index 743749bcb..12707242e 100644 --- a/service/common/src/main/java/org/apache/polaris/service/catalog/BasePolarisCatalog.java +++ b/service/common/src/main/java/org/apache/polaris/service/catalog/BasePolarisCatalog.java @@ -94,6 +94,7 @@ import org.apache.polaris.core.persistence.PolarisMetaStoreSession; import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper; import org.apache.polaris.core.persistence.ResolvedPolarisEntity; +import org.apache.polaris.core.persistence.dao.NamespaceDao; import org.apache.polaris.core.persistence.resolver.PolarisResolutionManifest; import org.apache.polaris.core.persistence.resolver.PolarisResolutionManifestCatalogView; import org.apache.polaris.core.persistence.resolver.ResolverPath; @@ -165,6 +166,7 @@ public class BasePolarisCatalog extends BaseMetastoreViewCatalog private final FileIOFactory fileIOFactory; private final long catalogId; private final String catalogName; + private final NamespaceDao namespaceDao; private String ioImplClassName; private FileIO catalogFileIO; @@ -191,7 +193,8 @@ public BasePolarisCatalog( PolarisResolutionManifestCatalogView resolvedEntityView, SecurityContext securityContext, TaskExecutor taskExecutor, - FileIOFactory fileIOFactory) { + FileIOFactory fileIOFactory, + NamespaceDao namespaceDao) { this.realmContext = realmContext; this.entityManager = entityManager; this.metaStoreManager = metaStoreManager; @@ -208,6 +211,7 @@ public BasePolarisCatalog( (AuthenticatedPolarisPrincipal) securityContext.getUserPrincipal(); this.catalogId = catalogEntity.getId(); this.catalogName = catalogEntity.getName(); + this.namespaceDao = namespaceDao; } @Override @@ -523,17 +527,8 @@ private void createNamespaceInternal( } else { LOGGER.debug("Skipping location overlap validation for namespace '{}'", namespace); } - PolarisEntity returnedEntity = - PolarisEntity.of( - getMetaStoreManager() - .createEntityIfNotExists( - metaStoreSession, - PolarisEntity.toCoreList(resolvedParent.getRawFullPath()), - entity)); - if (returnedEntity == null) { - throw new AlreadyExistsException( - "Cannot create namespace %s. Namespace already exists", namespace); - } + + namespaceDao.save(entity, PolarisEntity.toCoreList(resolvedParent.getRawFullPath())); } private String resolveNamespaceLocation(Namespace namespace, Map properties) { @@ -633,22 +628,15 @@ public boolean dropNamespace(Namespace namespace) throws NamespaceNotEmptyExcept PolarisEntity leafEntity = resolvedEntities.getRawLeafEntity(); // drop if exists and is empty - PolarisMetaStoreManager.DropEntityResult dropEntityResult = - getMetaStoreManager() - .dropEntityIfExists( - metaStoreSession, - PolarisEntity.toCoreList(catalogPath), - leafEntity, - Map.of(), - configurationStore.getConfiguration( - realmContext, PolarisConfiguration.CLEANUP_ON_NAMESPACE_DROP)); - - if (!dropEntityResult.isSuccess() && dropEntityResult.failedBecauseNotEmpty()) { + try { + return namespaceDao.delete( + PolarisEntity.toCoreList(catalogPath), + leafEntity, + configurationStore.getConfiguration( + realmContext, PolarisConfiguration.CLEANUP_ON_NAMESPACE_DROP)); + } catch (NamespaceNotEmptyException e) { throw new NamespaceNotEmptyException("Namespace %s is not empty", namespace); } - - // return status of drop operation - return dropEntityResult.isSuccess(); } @Override @@ -678,17 +666,7 @@ public boolean setProperties(Namespace namespace, Map properties } List parentPath = resolvedEntities.getRawFullPath(); - PolarisEntity returnedEntity = - Optional.ofNullable( - getMetaStoreManager() - .updateEntityPropertiesIfNotChanged( - metaStoreSession, PolarisEntity.toCoreList(parentPath), updatedEntity) - .getEntity()) - .map(PolarisEntity::new) - .orElse(null); - if (returnedEntity == null) { - throw new RuntimeException("Concurrent modification of namespace: " + namespace); - } + namespaceDao.update(NamespaceEntity.of(updatedEntity), PolarisEntity.toCoreList(parentPath)); return true; } diff --git a/service/common/src/main/java/org/apache/polaris/service/context/PolarisCallContextCatalogFactory.java b/service/common/src/main/java/org/apache/polaris/service/context/PolarisCallContextCatalogFactory.java index 85773a3bc..245e8535e 100644 --- a/service/common/src/main/java/org/apache/polaris/service/context/PolarisCallContextCatalogFactory.java +++ b/service/common/src/main/java/org/apache/polaris/service/context/PolarisCallContextCatalogFactory.java @@ -36,6 +36,7 @@ import org.apache.polaris.core.persistence.PolarisEntityManager; import org.apache.polaris.core.persistence.PolarisMetaStoreManager; import org.apache.polaris.core.persistence.PolarisMetaStoreSession; +import org.apache.polaris.core.persistence.dao.NamespaceDao; import org.apache.polaris.core.persistence.resolver.PolarisResolutionManifest; import org.apache.polaris.service.catalog.BasePolarisCatalog; import org.apache.polaris.service.catalog.io.FileIOFactory; @@ -58,6 +59,7 @@ public class PolarisCallContextCatalogFactory implements CallContextCatalogFacto private final PolarisDiagnostics diagnostics; private final TaskExecutor taskExecutor; private final FileIOFactory fileIOFactory; + private final NamespaceDao namespaceDao; @Inject public PolarisCallContextCatalogFactory( @@ -67,7 +69,8 @@ public PolarisCallContextCatalogFactory( PolarisConfigurationStore configurationStore, PolarisDiagnostics diagnostics, TaskExecutor taskExecutor, - FileIOFactory fileIOFactory) { + FileIOFactory fileIOFactory, + NamespaceDao namespaceDao) { this.entityManager = entityManager; this.metaStoreManager = metaStoreManager; this.metaStoreSession = metaStoreSession; @@ -75,6 +78,7 @@ public PolarisCallContextCatalogFactory( this.diagnostics = diagnostics; this.taskExecutor = taskExecutor; this.fileIOFactory = fileIOFactory; + this.namespaceDao = namespaceDao; } @Override @@ -102,7 +106,8 @@ public Catalog createCallContextCatalog( resolvedManifest, securityContext, taskExecutor, - fileIOFactory); + fileIOFactory, + namespaceDao); CatalogEntity catalog = CatalogEntity.of(baseCatalogEntity); Map catalogProperties = new HashMap<>(catalog.getPropertiesAsMap()); diff --git a/service/common/src/main/java/org/apache/polaris/service/persistence/fdb/dao/FdbNamespaceDao.java b/service/common/src/main/java/org/apache/polaris/service/persistence/fdb/dao/FdbNamespaceDao.java new file mode 100644 index 000000000..42967c190 --- /dev/null +++ b/service/common/src/main/java/org/apache/polaris/service/persistence/fdb/dao/FdbNamespaceDao.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.polaris.service.persistence.fdb.dao; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import org.apache.iceberg.catalog.Namespace; +import org.apache.iceberg.exceptions.AlreadyExistsException; +import org.apache.iceberg.exceptions.NamespaceNotEmptyException; +import org.apache.polaris.core.entity.NamespaceEntity; +import org.apache.polaris.core.entity.PolarisEntity; +import org.apache.polaris.core.entity.PolarisEntityCore; +import org.apache.polaris.core.persistence.PolarisMetaStoreManager; +import org.apache.polaris.core.persistence.PolarisMetaStoreSession; +import org.apache.polaris.core.persistence.dao.NamespaceDao; + +@ApplicationScoped +public class FdbNamespaceDao implements NamespaceDao { + private final PolarisMetaStoreManager metaStoreManager; + private final PolarisMetaStoreSession metaStoreSession; + + @Inject + public FdbNamespaceDao( + PolarisMetaStoreManager metaStoreManager, PolarisMetaStoreSession metaStoreSession) { + this.metaStoreManager = metaStoreManager; + this.metaStoreSession = metaStoreSession; + } + + @Override + public void save(NamespaceEntity namespace, List catalogPath) { + var returnedEntity = + PolarisEntity.of( + metaStoreManager.createEntityIfNotExists(metaStoreSession, catalogPath, namespace)); + + if (returnedEntity == null) { + throw new AlreadyExistsException( + "Cannot create namespace %s. Namespace already exists", namespace); + } + } + + @Override + public void update(NamespaceEntity namespace, List catalogPath) { + var returnedEntity = + Optional.ofNullable( + metaStoreManager + .updateEntityPropertiesIfNotChanged(metaStoreSession, catalogPath, namespace) + .getEntity()) + .map(PolarisEntity::new) + .orElse(null); + if (returnedEntity == null) { + throw new RuntimeException("Concurrent modification of namespace: " + namespace); + } + } + + @Override + public NamespaceEntity get(String namespaceId) { + // todo + return null; + } + + @Override + public NamespaceEntity get(Namespace namespace) { + // todo + return null; + } + + @Override + public boolean delete( + List catalogPath, PolarisEntity leafEntity, boolean cleanup) { + var dropEntityResult = + metaStoreManager.dropEntityIfExists( + metaStoreSession, catalogPath, leafEntity, Map.of(), cleanup); + if (!dropEntityResult.isSuccess() && dropEntityResult.failedBecauseNotEmpty()) { + throw new NamespaceNotEmptyException("Namespace is not empty"); + } + + return dropEntityResult.isSuccess(); + } +} diff --git a/service/common/src/main/java/org/apache/polaris/service/persistence/postgres/dao/PostgresNamespaceDao.java b/service/common/src/main/java/org/apache/polaris/service/persistence/postgres/dao/PostgresNamespaceDao.java new file mode 100644 index 000000000..13c98ebde --- /dev/null +++ b/service/common/src/main/java/org/apache/polaris/service/persistence/postgres/dao/PostgresNamespaceDao.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.polaris.service.persistence.postgres.dao; + +import java.util.List; +import org.apache.iceberg.catalog.Namespace; +import org.apache.polaris.core.entity.NamespaceEntity; +import org.apache.polaris.core.entity.PolarisEntity; +import org.apache.polaris.core.entity.PolarisEntityCore; +import org.apache.polaris.core.persistence.dao.NamespaceDao; + +public class PostgresNamespaceDao implements NamespaceDao { + @Override + public void save(NamespaceEntity namespace, List catalogPath) { + // jdbc implementation, we could use JPA like EclipseLink as well. + // execute("INSERT INTO %s (catalog_name, namespace, property, value) VALUES (?, ?, ?, ?)"); + } + + @Override + public void update(NamespaceEntity namespace, List catalogPath) { + // execute("update %s set ? = ? where id = ?"); + } + + @Override + public NamespaceEntity get(String namespaceId) { + return null; + } + + @Override + public NamespaceEntity get(Namespace namespace) { + return null; + } + + @Override + public boolean delete( + List catalogPath, PolarisEntity leafEntity, boolean cleanup) { + return false; + } +} diff --git a/service/common/src/test/java/org/apache/polaris/service/catalog/io/FileIOFactoryTest.java b/service/common/src/test/java/org/apache/polaris/service/catalog/io/FileIOFactoryTest.java index 8aa0522f4..49fdbf0c5 100644 --- a/service/common/src/test/java/org/apache/polaris/service/catalog/io/FileIOFactoryTest.java +++ b/service/common/src/test/java/org/apache/polaris/service/catalog/io/FileIOFactoryTest.java @@ -45,6 +45,7 @@ import org.apache.polaris.service.TestServices; import org.apache.polaris.service.catalog.BasePolarisCatalog; import org.apache.polaris.service.catalog.PolarisPassthroughResolutionView; +import org.apache.polaris.service.persistence.fdb.dao.FdbNamespaceDao; import org.apache.polaris.service.task.TaskFileIOSupplier; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.AfterEach; @@ -210,6 +211,11 @@ BasePolarisCatalog createCatalog(TestServices services) { services.metaStoreManagerFactory().getOrCreateSessionSupplier(realmContext).get(), services.securityContext(), CATALOG_NAME); + var metastoreManager = + services.metaStoreManagerFactory().getOrCreateMetaStoreManager(realmContext); + var metastoreSession = + services.metaStoreManagerFactory().getOrCreateSessionSupplier(realmContext).get(); + var namespaceDao = new FdbNamespaceDao(metastoreManager, metastoreSession); BasePolarisCatalog polarisCatalog = new BasePolarisCatalog( services.realmContext(), @@ -221,7 +227,8 @@ BasePolarisCatalog createCatalog(TestServices services) { passthroughView, services.securityContext(), services.taskExecutor(), - services.fileIOFactory()); + services.fileIOFactory(), + namespaceDao); polarisCatalog.initialize( CATALOG_NAME, ImmutableMap.of( diff --git a/service/common/src/testFixtures/java/org/apache/polaris/service/TestServices.java b/service/common/src/testFixtures/java/org/apache/polaris/service/TestServices.java index 5b0808869..ed3e9eef1 100644 --- a/service/common/src/testFixtures/java/org/apache/polaris/service/TestServices.java +++ b/service/common/src/testFixtures/java/org/apache/polaris/service/TestServices.java @@ -51,6 +51,7 @@ import org.apache.polaris.service.context.CallContextCatalogFactory; import org.apache.polaris.service.context.PolarisCallContextCatalogFactory; import org.apache.polaris.service.persistence.InMemoryPolarisMetaStoreManagerFactory; +import org.apache.polaris.service.persistence.fdb.dao.FdbNamespaceDao; import org.apache.polaris.service.storage.PolarisStorageIntegrationProviderImpl; import org.apache.polaris.service.task.TaskExecutor; import org.assertj.core.util.TriFunction; @@ -153,7 +154,8 @@ public TestServices build() { configurationStore, polarisDiagnostics, Mockito.mock(TaskExecutor.class), - fileIOFactory); + fileIOFactory, + new FdbNamespaceDao(metaStoreManager, metaStoreSession)); IcebergRestCatalogApiService service = new IcebergCatalogAdapter(