diff --git a/bom/build.gradle.kts b/bom/build.gradle.kts index 11859b32c90..4fc33d96c23 100644 --- a/bom/build.gradle.kts +++ b/bom/build.gradle.kts @@ -46,6 +46,7 @@ dependencies { api(project(":polaris-jpa-model")) api(project(":polaris-quarkus-admin")) + api(project(":polaris-quarkus-test-commons")) api(project(":polaris-quarkus-defaults")) api(project(":polaris-quarkus-server")) api(project(":polaris-quarkus-service")) diff --git a/extension/persistence/relational-jdbc/build.gradle.kts b/extension/persistence/relational-jdbc/build.gradle.kts index 0895d21ec0b..82f67c8a5ad 100644 --- a/extension/persistence/relational-jdbc/build.gradle.kts +++ b/extension/persistence/relational-jdbc/build.gradle.kts @@ -17,7 +17,10 @@ * under the License. */ -plugins { id("polaris-server") } +plugins { + id("polaris-server") + alias(libs.plugins.jandex) +} dependencies { implementation(project(":polaris-core")) diff --git a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/DatabaseType.java b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/DatabaseType.java new file mode 100644 index 00000000000..cdf6ddc43d2 --- /dev/null +++ b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/DatabaseType.java @@ -0,0 +1,49 @@ +/* + * 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.extension.persistence.relational.jdbc; + +import java.util.Locale; + +public enum DatabaseType { + POSTGRES("postgres"), + H2("h2"); + + private final String displayName; // Store the user-friendly name + + DatabaseType(String displayName) { + this.displayName = displayName; + } + + // Method to get the user-friendly display name + public String getDisplayName() { + return displayName; + } + + public static DatabaseType fromDisplayName(String displayName) { + return switch (displayName.toLowerCase(Locale.ROOT)) { + case "h2" -> DatabaseType.H2; + case "postgresql" -> DatabaseType.POSTGRES; + default -> throw new IllegalStateException("Unsupported DatabaseType: '" + displayName + "'"); + }; + } + + public String getInitScriptResource() { + return String.format("%s/schema-v1.sql", this.getDisplayName()); + } +} diff --git a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/DatasourceOperations.java b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/DatasourceOperations.java index 4884dde4ee5..6fec8e67fe6 100644 --- a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/DatasourceOperations.java +++ b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/DatasourceOperations.java @@ -35,13 +35,9 @@ import java.util.function.Predicate; import javax.sql.DataSource; import org.apache.polaris.extension.persistence.relational.jdbc.models.Converter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class DatasourceOperations { - private static final Logger LOGGER = LoggerFactory.getLogger(DatasourceOperations.class); - private static final String ALREADY_EXISTS_STATE_POSTGRES = "42P07"; private static final String CONSTRAINT_VIOLATION_SQL_CODE = "23505"; private final DataSource datasource; @@ -189,10 +185,6 @@ public boolean isConstraintViolation(SQLException e) { return CONSTRAINT_VIOLATION_SQL_CODE.equals(e.getSQLState()); } - public boolean isAlreadyExistsException(SQLException e) { - return ALREADY_EXISTS_STATE_POSTGRES.equals(e.getSQLState()); - } - private Connection borrowConnection() throws SQLException { return datasource.getConnection(); } diff --git a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcBasePersistenceImpl.java b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcBasePersistenceImpl.java index 24bb927027b..ea99ed98dae 100644 --- a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcBasePersistenceImpl.java +++ b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcBasePersistenceImpl.java @@ -23,6 +23,7 @@ import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; import java.sql.SQLException; +import java.sql.Statement; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -86,44 +87,14 @@ public void writeEntity( @Nonnull PolarisBaseEntity entity, boolean nameOrParentChanged, PolarisBaseEntity originalEntity) { - ModelEntity modelEntity = ModelEntity.fromEntity(entity); - String query; - if (originalEntity == null) { - try { - query = generateInsertQuery(modelEntity, realmId); - datasourceOperations.executeUpdate(query); - } catch (SQLException e) { - if ((datasourceOperations.isConstraintViolation(e) - || datasourceOperations.isAlreadyExistsException(e))) { - throw new EntityAlreadyExistsException(entity, e); - } else { - throw new RuntimeException( - String.format("Failed to write entity due to %s", e.getMessage()), e); - } - } - } else { - Map params = - Map.of( - "id", - originalEntity.getId(), - "catalog_id", - originalEntity.getCatalogId(), - "entity_version", - originalEntity.getEntityVersion(), - "realm_id", - realmId); - query = generateUpdateQuery(modelEntity, params); - try { - int rowsUpdated = datasourceOperations.executeUpdate(query); - if (rowsUpdated == 0) { - throw new RetryOnConcurrencyException( - "Entity '%s' id '%s' concurrently modified; expected version %s", - entity.getName(), entity.getId(), originalEntity.getEntityVersion()); - } - } catch (SQLException e) { - throw new RuntimeException( - String.format("Failed to write entity due to %s", e.getMessage()), e); - } + try { + datasourceOperations.runWithinTransaction( + statement -> { + persistEntity(callCtx, entity, originalEntity, statement); + return true; + }); + } catch (SQLException e) { + throw new RuntimeException("Error persisting entity", e); } } @@ -137,70 +108,21 @@ public void writeEntities( statement -> { for (int i = 0; i < entities.size(); i++) { PolarisBaseEntity entity = entities.get(i); - ModelEntity modelEntity = ModelEntity.fromEntity(entity); + PolarisBaseEntity originalEntity = + originalEntities != null ? originalEntities.get(i) : null; // first, check if the entity has already been created, in which case we will simply // return it. PolarisBaseEntity entityFound = lookupEntity( callCtx, entity.getCatalogId(), entity.getId(), entity.getTypeCode()); - if (entityFound != null) { + if (entityFound != null && originalEntity == null) { // probably the client retried, simply return it // TODO: Check correctness of returning entityFound vs entity here. It may have // already been updated after the creation. continue; } - // lookup by name - EntityNameLookupRecord exists = - lookupEntityIdAndSubTypeByName( - callCtx, - entity.getCatalogId(), - entity.getParentId(), - entity.getTypeCode(), - entity.getName()); - if (exists != null) { - throw new EntityAlreadyExistsException(entity); - } - String query; - if (originalEntities == null || originalEntities.get(i) == null) { - try { - query = generateInsertQuery(modelEntity, realmId); - statement.executeUpdate(query); - } catch (SQLException e) { - if ((datasourceOperations.isConstraintViolation(e) - || datasourceOperations.isAlreadyExistsException(e))) { - throw new EntityAlreadyExistsException(entity, e); - } else { - throw new RuntimeException( - String.format("Failed to write entity due to %s", e.getMessage()), e); - } - } - } else { - Map params = - Map.of( - "id", - originalEntities.get(i).getId(), - "catalog_id", - originalEntities.get(i).getCatalogId(), - "entity_version", - originalEntities.get(i).getEntityVersion(), - "realm_id", - realmId); - query = generateUpdateQuery(modelEntity, params); - try { - int rowsUpdated = statement.executeUpdate(query); - if (rowsUpdated == 0) { - throw new RetryOnConcurrencyException( - "Entity '%s' id '%s' concurrently modified; expected version %s", - entity.getName(), - entity.getId(), - originalEntities.get(i).getEntityVersion()); - } - } catch (SQLException e) { - throw new RuntimeException( - String.format("Failed to write entity due to %s", e.getMessage()), e); - } - } + persistEntity(callCtx, entity, originalEntity, statement); } return true; }); @@ -212,6 +134,56 @@ public void writeEntities( } } + private void persistEntity( + @Nonnull PolarisCallContext callCtx, + @Nonnull PolarisBaseEntity entity, + PolarisBaseEntity originalEntity, + Statement statement) + throws SQLException { + ModelEntity modelEntity = ModelEntity.fromEntity(entity); + if (originalEntity == null) { + try { + statement.executeUpdate(generateInsertQuery(modelEntity, realmId)); + } catch (SQLException e) { + if (datasourceOperations.isConstraintViolation(e)) { + PolarisBaseEntity existingEntity = + lookupEntityByName( + callCtx, + entity.getCatalogId(), + entity.getParentId(), + entity.getTypeCode(), + entity.getName()); + throw new EntityAlreadyExistsException(existingEntity, e); + } else { + throw new RuntimeException( + String.format("Failed to write entity due to %s", e.getMessage()), e); + } + } + } else { + Map params = + Map.of( + "id", + originalEntity.getId(), + "catalog_id", + originalEntity.getCatalogId(), + "entity_version", + originalEntity.getEntityVersion(), + "realm_id", + realmId); + try { + int rowsUpdated = statement.executeUpdate(generateUpdateQuery(modelEntity, params)); + if (rowsUpdated == 0) { + throw new RetryOnConcurrencyException( + "Entity '%s' id '%s' concurrently modified; expected version %s", + originalEntity.getName(), originalEntity.getId(), originalEntity.getEntityVersion()); + } + } catch (SQLException e) { + throw new RuntimeException( + String.format("Failed to write entity due to %s", e.getMessage()), e); + } + } + } + @Override public void writeToGrantRecords( @Nonnull PolarisCallContext callCtx, @Nonnull PolarisGrantRecord grantRec) { @@ -492,6 +464,8 @@ public PolarisGrantRecord lookupGrantRecord( throw new IllegalStateException( String.format( "More than one grant record %s for a given Grant record", results.getFirst())); + } else if (results.isEmpty()) { + return null; } return results.getFirst(); } catch (SQLException e) { diff --git a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcMetaStoreManagerFactory.java b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcMetaStoreManagerFactory.java index 07ac7f97252..0f981a99b2e 100644 --- a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcMetaStoreManagerFactory.java +++ b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcMetaStoreManagerFactory.java @@ -21,7 +21,9 @@ import io.smallrye.common.annotation.Identifier; import jakarta.annotation.Nullable; import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; +import java.sql.Connection; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; @@ -37,6 +39,7 @@ import org.apache.polaris.core.entity.PolarisEntitySubType; import org.apache.polaris.core.entity.PolarisEntityType; import org.apache.polaris.core.entity.PolarisPrincipalSecrets; +import org.apache.polaris.core.persistence.AtomicOperationMetaStoreManager; import org.apache.polaris.core.persistence.BasePersistence; import org.apache.polaris.core.persistence.MetaStoreManagerFactory; import org.apache.polaris.core.persistence.PolarisMetaStoreManager; @@ -46,7 +49,6 @@ import org.apache.polaris.core.persistence.dao.entity.BaseResult; import org.apache.polaris.core.persistence.dao.entity.EntityResult; import org.apache.polaris.core.persistence.dao.entity.PrincipalSecretsResult; -import org.apache.polaris.core.persistence.transactional.TransactionalMetaStoreManagerImpl; import org.apache.polaris.core.storage.PolarisStorageIntegrationProvider; import org.apache.polaris.core.storage.cache.StorageCredentialCache; import org.slf4j.Logger; @@ -68,10 +70,9 @@ public class JdbcMetaStoreManagerFactory implements MetaStoreManagerFactory { final Map entityCacheMap = new HashMap<>(); final Map> sessionSupplierMap = new HashMap<>(); protected final PolarisDiagnostics diagServices = new PolarisDefaultDiagServiceImpl(); - // TODO: Pending discussion of if we should have one Database per realm or 1 schema per realm - // or realm should be a primary key on all the tables. - @Inject DataSource dataSource; + @Inject PolarisStorageIntegrationProvider storageIntegrationProvider; + @Inject Instance dataSource; protected JdbcMetaStoreManagerFactory() {} @@ -86,7 +87,7 @@ protected PrincipalSecretsGenerator secretsGenerator( } protected PolarisMetaStoreManager createNewMetaStoreManager() { - return new TransactionalMetaStoreManagerImpl(); + return new AtomicOperationMetaStoreManager(); } private void initializeForRealm( @@ -106,12 +107,16 @@ private void initializeForRealm( } private DatasourceOperations getDatasourceOperations(boolean isBootstrap) { - DatasourceOperations databaseOperations = new DatasourceOperations(dataSource); + DatasourceOperations databaseOperations = new DatasourceOperations(dataSource.get()); if (isBootstrap) { - // TODO: see if we need to take script from Quarkus or can we just - // use the script committed in the repo. try { - databaseOperations.executeScript("scripts/postgres/schema-v1-postgres.sql"); + DatabaseType databaseType; + try (Connection connection = dataSource.get().getConnection()) { + String productName = connection.getMetaData().getDatabaseProductName(); + databaseType = DatabaseType.fromDisplayName(productName); + } + databaseOperations.executeScript( + String.format("%s/schema-v1.sql", databaseType.getDisplayName())); } catch (SQLException e) { throw new RuntimeException( String.format("Error executing sql script: %s", e.getMessage()), e); diff --git a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/models/ModelEntity.java b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/models/ModelEntity.java index 5ec7bbf95ae..948f9a86937 100644 --- a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/models/ModelEntity.java +++ b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/models/ModelEntity.java @@ -152,8 +152,11 @@ public ModelEntity fromResultSet(ResultSet r) throws SQLException { .purgeTimestamp(r.getObject("purge_timestamp", Long.class)) .toPurgeTimestamp(r.getObject("to_purge_timestamp", Long.class)) .lastUpdateTimestamp(r.getObject("last_update_timestamp", Long.class)) - .properties(r.getObject("properties", String.class)) - .internalProperties(r.getObject("internal_properties", String.class)) + .properties( + r.getString("properties")) // required for extracting when the underlying type is JSONB + .internalProperties( + r.getString( + "internal_properties")) // required for extracting when the underlying type is JSONB .grantRecordsVersion(r.getObject("grant_records_version", Integer.class)) .build(); } diff --git a/extension/persistence/relational-jdbc/src/main/resources/h2/schema-v1-h2.sql b/extension/persistence/relational-jdbc/src/main/resources/h2/schema-v1.sql similarity index 100% rename from extension/persistence/relational-jdbc/src/main/resources/h2/schema-v1-h2.sql rename to extension/persistence/relational-jdbc/src/main/resources/h2/schema-v1.sql diff --git a/scripts/postgres/schema-v1-postgresql.sql b/extension/persistence/relational-jdbc/src/main/resources/postgres/schema-v1.sql similarity index 92% rename from scripts/postgres/schema-v1-postgresql.sql rename to extension/persistence/relational-jdbc/src/main/resources/postgres/schema-v1.sql index 3e18d9e30a1..12da8f7a840 100644 --- a/scripts/postgres/schema-v1-postgresql.sql +++ b/extension/persistence/relational-jdbc/src/main/resources/postgres/schema-v1.sql @@ -15,16 +15,12 @@ -- KIND, either express or implied. See the License for the -- specific language governing permissions and limitations -- under the License. --- --- Note: Database and schema creation is not included in this script. Please create the database and --- schema before running this script. for example in psql: --- CREATE DATABASE polaris_db; --- \c polaris_db --- CREATE SCHEMA polaris_schema; --- set search_path to polaris_schema; +CREATE SCHEMA IF NOT EXISTS POLARIS_SCHEMA; +SET search_path TO POLARIS_SCHEMA; CREATE TABLE IF NOT EXISTS entities ( + realm_id TEXT NOT NULL, catalog_id BIGINT NOT NULL, id BIGINT NOT NULL, parent_id BIGINT NOT NULL, @@ -49,6 +45,7 @@ CREATE INDEX IF NOT EXISTS idx_entities ON entities (realm_id, catalog_id, id); COMMENT ON TABLE entities IS 'all the entities'; +COMMENT ON COLUMN entities.realm_id IS 'realm_id used for multi-tenancy'; COMMENT ON COLUMN entities.catalog_id IS 'catalog id'; COMMENT ON COLUMN entities.id IS 'entity id'; COMMENT ON COLUMN entities.parent_id IS 'entity id of parent'; @@ -65,7 +62,7 @@ COMMENT ON COLUMN entities.internal_properties IS 'entities internal properties COMMENT ON COLUMN entities.grant_records_version IS 'the version of grant records change on the entity'; CREATE TABLE IF NOT EXISTS grant_records ( - realm_id INT NOT NULL, + realm_id TEXT NOT NULL, securable_catalog_id BIGINT NOT NULL, securable_id BIGINT NOT NULL, grantee_catalog_id BIGINT NOT NULL, @@ -84,7 +81,7 @@ COMMENT ON COLUMN grant_records.privilege_code IS 'privilege code'; CREATE TABLE IF NOT EXISTS principal_authentication_data ( - realm_id INT NOT NULL, + realm_id TEXT NOT NULL, principal_id BIGINT NOT NULL, principal_client_id VARCHAR(255) NOT NULL, main_secret_hash VARCHAR(255) NOT NULL, diff --git a/extension/persistence/relational-jdbc/src/test/java/org/apache/polaris/extension/persistence/impl/relational/jdbc/AtomicMetastoreManagerWithJdbcBasePersistenceImplTest.java b/extension/persistence/relational-jdbc/src/test/java/org/apache/polaris/extension/persistence/impl/relational/jdbc/AtomicMetastoreManagerWithJdbcBasePersistenceImplTest.java index cdc31685b7c..72ef15913bb 100644 --- a/extension/persistence/relational-jdbc/src/test/java/org/apache/polaris/extension/persistence/impl/relational/jdbc/AtomicMetastoreManagerWithJdbcBasePersistenceImplTest.java +++ b/extension/persistence/relational-jdbc/src/test/java/org/apache/polaris/extension/persistence/impl/relational/jdbc/AtomicMetastoreManagerWithJdbcBasePersistenceImplTest.java @@ -31,6 +31,7 @@ import org.apache.polaris.core.persistence.AtomicOperationMetaStoreManager; import org.apache.polaris.core.persistence.BasePolarisMetaStoreManagerTest; import org.apache.polaris.core.persistence.PolarisTestMetaStoreManager; +import org.apache.polaris.extension.persistence.relational.jdbc.DatabaseType; import org.apache.polaris.extension.persistence.relational.jdbc.DatasourceOperations; import org.apache.polaris.extension.persistence.relational.jdbc.JdbcBasePersistenceImpl; import org.h2.jdbcx.JdbcConnectionPool; @@ -49,9 +50,13 @@ protected PolarisTestMetaStoreManager createPolarisTestMetaStoreManager() { PolarisDiagnostics diagServices = new PolarisDefaultDiagServiceImpl(); DatasourceOperations datasourceOperations = new DatasourceOperations(createH2DataSource()); try { - datasourceOperations.executeScript("h2/schema-v1-h2.sql"); + datasourceOperations.executeScript( + String.format("%s/schema-v1.sql", DatabaseType.H2.getDisplayName())); } catch (SQLException e) { - throw new RuntimeException(String.format("Error executing h2 script: %s", e.getMessage()), e); + throw new RuntimeException( + String.format( + "Error executing %s script: %s", DatabaseType.H2.getDisplayName(), e.getMessage()), + e); } JdbcBasePersistenceImpl basePersistence = diff --git a/gradle/projects.main.properties b/gradle/projects.main.properties index 8debf105594..6161eee47b0 100644 --- a/gradle/projects.main.properties +++ b/gradle/projects.main.properties @@ -30,6 +30,7 @@ polaris-quarkus-service=quarkus/service polaris-quarkus-server=quarkus/server polaris-quarkus-spark-tests=quarkus/spark-tests polaris-quarkus-admin=quarkus/admin +polaris-quarkus-test-commons=quarkus/test-commons polaris-quarkus-run-script=quarkus/run-script polaris-eclipselink=extension/persistence/eclipselink polaris-jpa-model=extension/persistence/jpa-model diff --git a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationTest.java b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationTest.java index 2ab3f9325d6..e5c8619e1cf 100644 --- a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationTest.java +++ b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationTest.java @@ -99,7 +99,9 @@ import org.apache.polaris.service.it.ext.PolarisIntegrationTestExtension; import org.apache.polaris.service.types.GenericTable; import org.assertj.core.api.Assertions; +import org.assertj.core.api.Assumptions; import org.assertj.core.api.InstanceOfAssertFactories; +import org.assertj.core.configuration.PreferredAssumptionException; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -178,6 +180,10 @@ static void setup( externalCatalogBase = testRootUri.resolve("external-catalog"); } + static { + Assumptions.setPreferredAssumptionException(PreferredAssumptionException.JUNIT5); + } + @AfterAll static void close() throws Exception { client.close(); diff --git a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogViewIntegrationBase.java b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogViewIntegrationBase.java index 8dc48837bf7..c5df1c5d8a1 100644 --- a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogViewIntegrationBase.java +++ b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogViewIntegrationBase.java @@ -37,9 +37,10 @@ import org.apache.polaris.service.it.env.PolarisApiEndpoints; import org.apache.polaris.service.it.env.PolarisClient; import org.apache.polaris.service.it.ext.PolarisIntegrationTestExtension; +import org.assertj.core.api.Assumptions; +import org.assertj.core.configuration.PreferredAssumptionException; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; @@ -57,6 +58,9 @@ */ @ExtendWith(PolarisIntegrationTestExtension.class) public abstract class PolarisRestCatalogViewIntegrationBase extends ViewCatalogTests { + static { + Assumptions.setPreferredAssumptionException(PreferredAssumptionException.JUNIT5); + } private static ClientCredentials adminCredentials; private static PolarisApiEndpoints endpoints; @@ -80,7 +84,7 @@ static void close() throws Exception { @BeforeEach public void before(TestInfo testInfo) { - Assumptions.assumeFalse(shouldSkip()); + Assumptions.assumeThat(shouldSkip()).isFalse(); String principalName = client.newEntityName("snowman-rest"); String principalRoleName = client.newEntityName("rest-admin"); diff --git a/quarkus/admin/build.gradle.kts b/quarkus/admin/build.gradle.kts index 357acfd9455..7b19a132a72 100644 --- a/quarkus/admin/build.gradle.kts +++ b/quarkus/admin/build.gradle.kts @@ -44,14 +44,17 @@ dependencies { implementation(project(":polaris-api-iceberg-service")) runtimeOnly(project(":polaris-eclipselink")) + runtimeOnly(project(":polaris-relational-jdbc")) runtimeOnly("org.postgresql:postgresql") + implementation("io.quarkus:quarkus-jdbc-postgresql") implementation(enforcedPlatform(libs.quarkus.bom)) implementation("io.quarkus:quarkus-picocli") implementation("io.quarkus:quarkus-container-image-docker") implementation("org.jboss.slf4j:slf4j-jboss-logmanager") + testImplementation(project(":polaris-quarkus-test-commons")) testFixturesApi(project(":polaris-core")) testFixturesApi(enforcedPlatform(libs.quarkus.bom)) diff --git a/quarkus/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcAdminProfile.java b/quarkus/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcAdminProfile.java new file mode 100644 index 00000000000..a64002983d2 --- /dev/null +++ b/quarkus/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcAdminProfile.java @@ -0,0 +1,41 @@ +/* + * 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.admintool.relational.jdbc; + +import static org.apache.polaris.admintool.PostgresTestResourceLifecycleManager.INIT_SCRIPT; + +import java.util.List; +import java.util.Map; +import org.apache.polaris.test.commons.PostgresRelationalJdbcLifeCycleManagement; +import org.apache.polaris.test.commons.RelationalJdbcProfile; + +public class RelationalJdbcAdminProfile extends RelationalJdbcProfile { + @Override + public Map getConfigOverrides() { + return Map.of(); + } + + @Override + public List testResources() { + return List.of( + new TestResourceEntry( + PostgresRelationalJdbcLifeCycleManagement.class, + Map.of(INIT_SCRIPT, "org/apache/polaris/admintool/init.sql"))); + } +} diff --git a/quarkus/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcBootstrapCommandTest.java b/quarkus/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcBootstrapCommandTest.java new file mode 100644 index 00000000000..dcd5eb14083 --- /dev/null +++ b/quarkus/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcBootstrapCommandTest.java @@ -0,0 +1,25 @@ +/* + * 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.admintool.relational.jdbc; + +import io.quarkus.test.junit.TestProfile; +import org.apache.polaris.admintool.BootstrapCommandTestBase; + +@TestProfile(RelationalJdbcAdminProfile.class) +public class RelationalJdbcBootstrapCommandTest extends BootstrapCommandTestBase {} diff --git a/quarkus/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcPurgeCommandTest.java b/quarkus/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcPurgeCommandTest.java new file mode 100644 index 00000000000..43163f531b7 --- /dev/null +++ b/quarkus/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcPurgeCommandTest.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.admintool.relational.jdbc; + +import io.quarkus.test.junit.TestProfile; +import java.util.Map; +import org.apache.polaris.admintool.PurgeCommandTestBase; +import org.testcontainers.shaded.com.google.common.collect.ImmutableMap; + +@TestProfile(RelationalJdbcPurgeCommandTest.Profile.class) +public class RelationalJdbcPurgeCommandTest extends PurgeCommandTestBase { + public static class Profile extends RelationalJdbcAdminProfile { + @Override + public Map getConfigOverrides() { + return ImmutableMap.builder() + .putAll(super.getConfigOverrides()) + .put("pre-bootstrap", "true") + .build(); + } + } +} diff --git a/quarkus/server/build.gradle.kts b/quarkus/server/build.gradle.kts index 61c1b466603..70112fd06dc 100644 --- a/quarkus/server/build.gradle.kts +++ b/quarkus/server/build.gradle.kts @@ -50,6 +50,8 @@ dependencies { runtimeOnly(project(":polaris-eclipselink")) runtimeOnly("org.postgresql:postgresql") + runtimeOnly(project(":polaris-relational-jdbc")) + runtimeOnly("io.quarkus:quarkus-jdbc-postgresql") // enforce the Quarkus _platform_ here, to get a consistent and validated set of dependencies implementation(enforcedPlatform(libs.quarkus.bom)) diff --git a/quarkus/service/build.gradle.kts b/quarkus/service/build.gradle.kts index eb729b02040..97b3daa0ded 100644 --- a/quarkus/service/build.gradle.kts +++ b/quarkus/service/build.gradle.kts @@ -23,11 +23,6 @@ plugins { id("polaris-quarkus") } -configurations.all { - // exclude junit4 dependency for this module - exclude(group = "junit", module = "junit") -} - dependencies { implementation(project(":polaris-core")) implementation(project(":polaris-api-management-service")) @@ -113,6 +108,12 @@ dependencies { testImplementation("software.amazon.awssdk:kms") testImplementation("software.amazon.awssdk:dynamodb") + runtimeOnly(project(":polaris-relational-jdbc")) + runtimeOnly("io.quarkus:quarkus-jdbc-postgresql") { + exclude(group = "org.antlr", module = "antlr4-runtime") + exclude(group = "org.scala-lang", module = "scala-library") + exclude(group = "org.scala-lang", module = "scala-reflect") + } testImplementation(platform(libs.quarkus.bom)) testImplementation("io.quarkus:quarkus-junit5") testImplementation("io.quarkus:quarkus-junit5-mockito") @@ -122,6 +123,13 @@ dependencies { testImplementation(libs.threeten.extra) testImplementation(libs.hawkular.agent.prometheus.scraper) + + testImplementation(project(":polaris-quarkus-test-commons")) + testImplementation("io.quarkus:quarkus-junit5") + testImplementation(platform(libs.testcontainers.bom)) + testImplementation("org.testcontainers:testcontainers") + testImplementation("org.testcontainers:postgresql") + testImplementation("org.postgresql:postgresql") } tasks.withType(Test::class.java).configureEach { diff --git a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusApplicationIT.java b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusApplicationIT.java new file mode 100644 index 00000000000..dd718db7322 --- /dev/null +++ b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusApplicationIT.java @@ -0,0 +1,28 @@ +/* + * 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.quarkus.it.relational.jdbc; + +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.quarkus.test.junit.TestProfile; +import org.apache.polaris.service.it.test.PolarisApplicationIntegrationTest; +import org.apache.polaris.test.commons.RelationalJdbcProfile; + +@TestProfile(RelationalJdbcProfile.class) +@QuarkusIntegrationTest +public class JdbcQuarkusApplicationIT extends PolarisApplicationIntegrationTest {} diff --git a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusManagementServiceIT.java b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusManagementServiceIT.java new file mode 100644 index 00000000000..0961889fd60 --- /dev/null +++ b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusManagementServiceIT.java @@ -0,0 +1,28 @@ +/* + * 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.quarkus.it.relational.jdbc; + +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.quarkus.test.junit.TestProfile; +import org.apache.polaris.service.it.test.PolarisManagementServiceIntegrationTest; +import org.apache.polaris.test.commons.RelationalJdbcProfile; + +@TestProfile(RelationalJdbcProfile.class) +@QuarkusIntegrationTest +public class JdbcQuarkusManagementServiceIT extends PolarisManagementServiceIntegrationTest {} diff --git a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusViewFileIT.java b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusViewFileIT.java new file mode 100644 index 00000000000..7471032a520 --- /dev/null +++ b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusViewFileIT.java @@ -0,0 +1,28 @@ +/* + * 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.quarkus.it.relational.jdbc; + +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.quarkus.test.junit.TestProfile; +import org.apache.polaris.service.it.test.PolarisRestCatalogViewFileIntegrationTest; +import org.apache.polaris.test.commons.RelationalJdbcProfile; + +@TestProfile(RelationalJdbcProfile.class) +@QuarkusIntegrationTest +public class JdbcQuarkusViewFileIT extends PolarisRestCatalogViewFileIntegrationTest {} diff --git a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcRestCatalogIT.java b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcRestCatalogIT.java new file mode 100644 index 00000000000..59b35fe912c --- /dev/null +++ b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcRestCatalogIT.java @@ -0,0 +1,28 @@ +/* + * 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.quarkus.it.relational.jdbc; + +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.quarkus.test.junit.TestProfile; +import org.apache.polaris.service.it.test.PolarisRestCatalogIntegrationTest; +import org.apache.polaris.test.commons.RelationalJdbcProfile; + +@TestProfile(RelationalJdbcProfile.class) +@QuarkusIntegrationTest +public class JdbcRestCatalogIT extends PolarisRestCatalogIntegrationTest {} diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogTest.java index 210a792e2bc..832ac32bdb9 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogTest.java @@ -127,6 +127,7 @@ import org.apache.polaris.service.types.TableUpdateNotification; import org.assertj.core.api.Assertions; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.assertj.core.configuration.PreferredAssumptionException; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; @@ -146,6 +147,10 @@ @TestProfile(IcebergCatalogTest.Profile.class) public abstract class IcebergCatalogTest extends CatalogTests { + static { + org.assertj.core.api.Assumptions.setPreferredAssumptionException( + PreferredAssumptionException.JUNIT5); + } public static class Profile implements QuarkusTestProfile { diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogViewTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogViewTest.java index 8d7708dd73e..5123ea0e17c 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogViewTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogViewTest.java @@ -68,6 +68,8 @@ import org.apache.polaris.service.catalog.io.FileIOFactory; import org.apache.polaris.service.config.RealmEntityManagerFactory; import org.apache.polaris.service.storage.PolarisStorageIntegrationProviderImpl; +import org.assertj.core.api.Assumptions; +import org.assertj.core.configuration.PreferredAssumptionException; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -78,6 +80,9 @@ @QuarkusTest @TestProfile(IcebergCatalogViewTest.Profile.class) public class IcebergCatalogViewTest extends ViewCatalogTests { + static { + Assumptions.setPreferredAssumptionException(PreferredAssumptionException.JUNIT5); + } public static class Profile implements QuarkusTestProfile { diff --git a/quarkus/test-commons/build.gradle.kts b/quarkus/test-commons/build.gradle.kts new file mode 100644 index 00000000000..b3813c90be5 --- /dev/null +++ b/quarkus/test-commons/build.gradle.kts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +plugins { + alias(libs.plugins.jandex) + id("java-test-fixtures") +} + +configurations.all { + exclude(group = "org.antlr", module = "antlr4-runtime") + exclude(group = "org.scala-lang", module = "scala-library") + exclude(group = "org.scala-lang", module = "scala-reflect") +} + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +dependencies { + implementation(enforcedPlatform(libs.quarkus.bom)) + implementation("io.quarkus:quarkus-junit5") + implementation(platform(libs.testcontainers.bom)) + implementation("org.testcontainers:testcontainers") + implementation("org.testcontainers:postgresql") +} diff --git a/quarkus/test-commons/src/main/java/org/apache/polaris/test/commons/PostgresRelationalJdbcLifeCycleManagement.java b/quarkus/test-commons/src/main/java/org/apache/polaris/test/commons/PostgresRelationalJdbcLifeCycleManagement.java new file mode 100644 index 00000000000..a85a70909e0 --- /dev/null +++ b/quarkus/test-commons/src/main/java/org/apache/polaris/test/commons/PostgresRelationalJdbcLifeCycleManagement.java @@ -0,0 +1,86 @@ +/* + * 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.test.commons; + +import io.quarkus.test.common.DevServicesContext; +import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; +import java.util.Map; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.utility.DockerImageName; + +public class PostgresRelationalJdbcLifeCycleManagement + implements QuarkusTestResourceLifecycleManager, DevServicesContext.ContextAware { + public static final String INIT_SCRIPT = "init-script"; + + private PostgreSQLContainer postgres; + private String initScript; + private DevServicesContext context; + + @Override + public void init(Map initArgs) { + initScript = initArgs.get(INIT_SCRIPT); + } + + @Override + @SuppressWarnings("resource") + public Map start() { + postgres = + new PostgreSQLContainer<>(DockerImageName.parse("postgres:17")) + .withDatabaseName("polaris_db") + .withUsername("polaris") + .withPassword("polaris"); + + if (initScript != null) { + postgres.withInitScript(initScript); + } + + context.containerNetworkId().ifPresent(postgres::withNetworkMode); + postgres.start(); + return Map.of( + "polaris.persistence.type", + "relational-jdbc", + "quarkus.datasource.db-kind", + "pgsql", + "quarkus.datasource.jdbc.url", + postgres.getJdbcUrl(), + "quarkus.datasource.username", + postgres.getUsername(), + "quarkus.datasource.password", + postgres.getPassword(), + "quarkus.datasource.jdbc.initial-size", + "10"); + } + + @Override + public void stop() { + if (postgres != null) { + try { + postgres.stop(); + } finally { + postgres = null; + } + } + } + + @Override + public void setIntegrationTestContext(DevServicesContext context) { + this.context = context; + } +} diff --git a/quarkus/test-commons/src/main/java/org/apache/polaris/test/commons/RelationalJdbcProfile.java b/quarkus/test-commons/src/main/java/org/apache/polaris/test/commons/RelationalJdbcProfile.java new file mode 100644 index 00000000000..38f7bd61a03 --- /dev/null +++ b/quarkus/test-commons/src/main/java/org/apache/polaris/test/commons/RelationalJdbcProfile.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.test.commons; + +import io.quarkus.test.junit.QuarkusTestProfile; +import java.util.List; +import java.util.Map; + +public class RelationalJdbcProfile implements QuarkusTestProfile { + @Override + public Map getConfigOverrides() { + return Map.of("polaris.persistence.auto-bootstrap-types", "relational-jdbc"); + } + + @Override + public List testResources() { + return List.of( + new QuarkusTestProfile.TestResourceEntry( + PostgresRelationalJdbcLifeCycleManagement.class, Map.of())); + } +}