From 68f4cd392a450d9deedf22da2f7887611ebb519e Mon Sep 17 00:00:00 2001 From: Ricardo Martin Date: Mon, 14 Jul 2025 12:03:56 +0200 Subject: [PATCH] Check if PK for DATABASECHANGELOG already exists Closes #41082 (cherry picked from commit 164274ac51b748cd9c3a94ad28fbb3a85384b2ae) Signed-off-by: rmartinc --- .../conn/CustomChangeLogHistoryService.java | 41 ++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/conn/CustomChangeLogHistoryService.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/conn/CustomChangeLogHistoryService.java index ad0e7fae3a3..22f2cea7d24 100644 --- a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/conn/CustomChangeLogHistoryService.java +++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/conn/CustomChangeLogHistoryService.java @@ -40,7 +40,12 @@ import liquibase.database.core.MySQLDatabase; import liquibase.exception.DatabaseException; import liquibase.executor.jvm.ChangelogJdbcMdcListener; import liquibase.logging.LogFactory; +import liquibase.snapshot.InvalidExampleException; +import liquibase.snapshot.SnapshotGeneratorFactory; import liquibase.statement.core.AddPrimaryKeyStatement; +import liquibase.structure.core.PrimaryKey; +import liquibase.structure.core.Schema; +import liquibase.structure.core.Table; /** * @@ -62,12 +67,11 @@ public class CustomChangeLogHistoryService extends StandardChangeLogHistoryServi if (serviceInitialized) return; - AddPrimaryKeyStatement pkStatement = new AddPrimaryKeyStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), - ColumnConfig.arrayFromNames("ID, AUTHOR, FILENAME"), "PK_DATABASECHANGELOG"); - ChangelogJdbcMdcListener.execute(getDatabase(), ex -> ex.execute(pkStatement)); - getDatabase().commit(); - serviceInitialized = true; + + if (!existsDatabaseChangelogPK()) { + createDatabaseChangelogPK(); + } } @Override @@ -136,4 +140,31 @@ public class CustomChangeLogHistoryService extends StandardChangeLogHistoryServi public int getPriority() { return super.getPriority() + 1; // Ensure bigger priority than StandardChangeLogHistoryService } + + private boolean existsDatabaseChangelogPK() throws DatabaseException { + try { + PrimaryKey example = new PrimaryKey(); + Table table = new Table(); + table.setSchema(new Schema(getLiquibaseCatalogName(), getLiquibaseSchemaName())); + table.setName(getDatabaseChangeLogTableName()); + example.setTable(table); + return SnapshotGeneratorFactory.getInstance().has(example, getDatabase()); + } catch (InvalidExampleException e) { + throw new DatabaseException(e); + } + } + + private void createDatabaseChangelogPK() throws DatabaseException { + AddPrimaryKeyStatement pkStatement = new AddPrimaryKeyStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), + ColumnConfig.arrayFromNames("ID, AUTHOR, FILENAME"), "PK_DATABASECHANGELOG"); + try { + ChangelogJdbcMdcListener.execute(getDatabase(), ex -> ex.execute(pkStatement)); + getDatabase().commit(); + } catch (DatabaseException e) { + // if PK already exists just ignore the exception + if (!existsDatabaseChangelogPK()) { + throw e; + } + } + } }