Skip to content

Commit 7e3740d

Browse files
authored
Merge pull request #3698 from cloudfoundry/flyway-upgrade
Flyway upgrade
2 parents 1121045 + a8027a5 commit 7e3740d

16 files changed

+162
-47
lines changed

dependencies.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ versions.braveVersion = "6.3.0"
1515
versions.opensaml = "4.0.1"
1616

1717
// Versions we're overriding from the Spring Boot Bom (Dependabot does not issue PRs to bump these versions, so we need to manually bump them)
18-
ext["mariadb.version"] = "2.7.12" // Bumping to v3 breaks some pipeline jobs (and compatibility with Amazon Aurora MySQL), so pinning to v2 for now. v2 (current version) is stable and will be supported until about September 2025 (https://mariadb.com/kb/en/about-mariadb-connector-j/).
19-
ext["flyway.version"] = "7.15.0" // the next major (v8)'s community edition drops support with MySQL 5.7, which UAA still needs to support. Can bump to v8 once we solve this issue.
20-
ext["hsqldb.version"] = "2.7.4" // HSQL-DB used for tests but not supported for productive usage
2118
ext["selenium.version"] = "${versions.seleniumVersion}" // Selenium for integration tests only
2219

2320
// Dependencies (some rely on shared versions, some are shared between projects)
@@ -37,6 +34,9 @@ libraries.commonsIo = "commons-io:commons-io:2.20.0"
3734
libraries.dumbster = "dumbster:dumbster:1.6"
3835
libraries.eclipseJgit = "org.eclipse.jgit:org.eclipse.jgit:7.3.0.202506031305-r"
3936
libraries.flywayCore = "org.flywaydb:flyway-core"
37+
libraries.flywayHsqlDb = "org.flywaydb:flyway-database-hsqldb"
38+
libraries.flywayMySql = "org.flywaydb:flyway-mysql"
39+
libraries.flywayPostgresql = "org.flywaydb:flyway-database-postgresql"
4040
libraries.greenmail = "com.icegreen:greenmail:2.1.5"
4141
libraries.guava = "com.google.guava:guava:${versions.guavaVersion}"
4242
libraries.guavaTestLib = "com.google.guava:guava-testlib:${versions.guavaVersion}"

server/build.gradle

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ dependencies {
6060
}
6161

6262
implementation(libraries.hibernateValidator)
63-
implementation(libraries.flywayCore)
64-
implementation(libraries.mariaJdbcDriver)
63+
implementation(libraries.flywayHsqlDb)
64+
implementation(libraries.flywayMySql)
65+
implementation(libraries.flywayPostgresql)
6566
implementation(libraries.hsqldb)
6667

6768
implementation(libraries.snakeyaml)
@@ -94,6 +95,7 @@ dependencies {
9495
testImplementation(libraries.mockitoJunit5)
9596

9697
testImplementation(libraries.postgresql)
98+
testImplementation(libraries.mariaJdbcDriver)
9799

98100
testImplementation(libraries.tomcatElApi)
99101
testImplementation(libraries.tomcatJasperEl)

server/src/main/java/org/cloudfoundry/identity/uaa/db/DatabaseInformation1_5_3.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* *****************************************************************************
3-
* Cloud Foundry
3+
* Cloud Foundry
44
* Copyright (c) [2009-2016] Pivotal Software, Inc. All Rights Reserved.
55
*
66
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -13,20 +13,18 @@
1313
*******************************************************************************/
1414
package org.cloudfoundry.identity.uaa.db;
1515

16+
import org.springframework.jdbc.core.RowMapper;
17+
1618
import java.sql.ResultSet;
1719
import java.sql.SQLException;
18-
import java.util.Arrays;
19-
import java.util.Collections;
2020
import java.util.List;
2121

22-
import org.springframework.jdbc.core.RowMapper;
23-
2422
/**
2523
* Created by fhanik on 3/5/14.
2624
*/
2725
public class DatabaseInformation1_5_3 {
2826

29-
public static List<String> tableNames = Collections.unmodifiableList(Arrays.asList(
27+
public static final List<String> tableNames = List.of(
3028
"users",
3129
"sec_audit",
3230
"oauth_client_details",
@@ -35,8 +33,7 @@ public class DatabaseInformation1_5_3 {
3533
"oauth_code",
3634
"authz_approvals",
3735
"external_group_mapping"
38-
39-
));
36+
);
4037

4138
public static boolean processColumn(ColumnInfo column) {
4239
return (!column.columnName.equals(column.columnName.toLowerCase())) &&

server/src/main/java/org/cloudfoundry/identity/uaa/db/beans/DatabaseConfiguration.java

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.cloudfoundry.identity.uaa.resources.jdbc.LimitSqlAdapter;
66
import org.cloudfoundry.identity.uaa.resources.jdbc.MySqlLimitSqlAdapter;
77
import org.cloudfoundry.identity.uaa.resources.jdbc.PostgresLimitSqlAdapter;
8+
import org.jspecify.annotations.NonNull;
89
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
910
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
1011
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
@@ -34,7 +35,7 @@
3435
* can be overridden by users, or in {@link DatabasePlatform} when they are static.
3536
* <p>
3637
* Note that we reference property sources directly here, without relying on Boot auto-discovery. We do this so
37-
* that all configuration is visible from a single place.
38+
* that all configurations are visible from a single place.
3839
* <p>
3940
* The following beans and configurations are wired by Spring Boot auto-configuration.
4041
* <p>
@@ -93,11 +94,40 @@ JdbcUrlCustomizer jdbcUrlAddTimeoutCustomizer(DatabaseProperties databasePropert
9394
return url -> {
9495
DatabasePlatform databasePlatform = databaseProperties.getDatabasePlatform();
9596
var timeout = Duration.ofSeconds(databaseProperties.getConnecttimeout());
96-
String connectorCharacter = url.contains("?") ? "&" : "?";
97-
return url + connectorCharacter + "connectTimeout=" + databasePlatform.getJdbcUrlTimeoutValue(timeout);
97+
return url + getConnectorCharacter(url) + "connectTimeout=" + databasePlatform.getJdbcUrlTimeoutValue(timeout);
9898
};
9999
}
100100

101+
/**
102+
* Use lower case table names with the mariadb driver
103+
* and allow connection to mysql scheme urls
104+
*/
105+
@Bean
106+
@Profile("mysql")
107+
JdbcUrlCustomizer jdbcUrlMariaDbSchemeCustomizer(DatabaseProperties databaseProperties) {
108+
return url -> {
109+
if (!url.startsWith("jdbc:mysql")) {
110+
return url;
111+
}
112+
if (!databaseProperties.getDriverClassName().contains("mariadb")) {
113+
return url;
114+
}
115+
116+
// this is a mysql scheme url with the mariadb driver
117+
if (!url.contains("permitMysqlScheme=")) {
118+
url += getConnectorCharacter(url) + "permitMysqlScheme=true";
119+
}
120+
if (!url.contains("lower_case_table_names")) {
121+
url += getConnectorCharacter(url) + "lower_case_table_names=1";
122+
}
123+
return url;
124+
};
125+
}
126+
127+
private static @NonNull String getConnectorCharacter(String url) {
128+
return url.contains("?") ? "&" : "?";
129+
}
130+
101131
@Bean
102132
public MBeanExporter dataSourceMBeanExporter(DataSource dataSource) {
103133
MBeanExporter exporter = new MBeanExporter();
@@ -129,7 +159,7 @@ LimitSqlAdapter limitSqlAdapter() {
129159

130160
@Configuration
131161
@Profile("postgresql")
132-
// The property source location is already inferred by the profile but we make it explicit
162+
// The property source location is already inferred by the profile, but we make it explicit
133163
@PropertySource("classpath:application-postgresql.properties")
134164
public static class PostgresConfiguration {
135165

@@ -142,7 +172,7 @@ LimitSqlAdapter limitSqlAdapter() {
142172

143173
@Configuration
144174
@Profile("mysql")
145-
// The property source location is already inferred by the profile but we make it explicit
175+
// The property source location is already inferred by the profile, but we make it explicit
146176
@PropertySource("classpath:application-mysql.properties")
147177
public static class MysqlConfiguration {
148178

server/src/main/java/org/cloudfoundry/identity/uaa/db/beans/FlywayConfiguration.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.cloudfoundry.identity.uaa.db.FixFailedBackportMigrations_4_0_4;
44
import org.flywaydb.core.Flyway;
5+
import org.springframework.context.ApplicationContext;
56
import org.springframework.context.annotation.Bean;
67
import org.springframework.context.annotation.Condition;
78
import org.springframework.context.annotation.ConditionContext;
@@ -22,16 +23,20 @@ public class FlywayConfiguration {
2223
* We need to maintain backwards compatibility due to {@link FixFailedBackportMigrations_4_0_4}
2324
*/
2425
static final String VERSION_TABLE = "schema_version";
26+
static final String FLYWAY_CLEAN_DISABLED = "spring.flyway.clean-disabled";
2527

2628
@Bean
27-
public Flyway baseFlyway(DataSource dataSource, DatabaseProperties databaseProperties) {
29+
public Flyway baseFlyway(ApplicationContext context, DataSource dataSource, DatabaseProperties databaseProperties) {
30+
boolean cleanDisabled = context.getEnvironment().getProperty(FLYWAY_CLEAN_DISABLED, "true").equalsIgnoreCase("true");
31+
2832
return Flyway.configure()
2933
.baselineOnMigrate(true)
3034
.dataSource(dataSource)
3135
.locations("classpath:org/cloudfoundry/identity/uaa/db/" + databaseProperties.getDatabasePlatform().type + "/")
3236
.baselineVersion("1.5.2")
3337
.validateOnMigrate(false)
3438
.table(VERSION_TABLE)
39+
.cleanDisabled(cleanDisabled)
3540
.load();
3641
}
3742

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
CREATE UNIQUE INDEX concurrently IF NOT EXISTS users_unique_key_lower ON users (LOWER(origin),LOWER(username),LOWER(identity_zone_id));
1+
-- Create index without CONCURRENTLY to allow execution within a transaction
2+
-- CONCURRENTLY cannot be used inside a transaction, which causes hangs with newer Flyway versions
3+
-- The IF NOT EXISTS clause prevents errors if the index already exists
4+
CREATE UNIQUE INDEX IF NOT EXISTS users_unique_key_lower ON users (LOWER(origin),LOWER(username),LOWER(identity_zone_id));
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
CREATE INDEX CONCURRENTLY IF NOT EXISTS users_key_lower_wo_origin ON users (LOWER(username),LOWER(identity_zone_id));
1+
-- Create index without CONCURRENTLY to allow execution within a transaction
2+
-- CONCURRENTLY cannot be used inside a transaction, which causes hangs with newer Flyway versions
3+
-- The IF NOT EXISTS clause prevents errors if the index already exists
4+
CREATE INDEX IF NOT EXISTS users_key_lower_wo_origin ON users (LOWER(username),LOWER(identity_zone_id));
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
CREATE INDEX CONCURRENTLY IF NOT EXISTS alias_in_zone on identity_provider (identity_zone_id, alias_zid) WHERE alias_zid IS NOT NULL;
1+
-- Create index without CONCURRENTLY to allow execution within a transaction
2+
-- CONCURRENTLY cannot be used inside a transaction, which causes hangs with newer Flyway versions
3+
-- The IF NOT EXISTS clause prevents errors if the index already exists
4+
CREATE INDEX IF NOT EXISTS alias_in_zone on identity_provider (identity_zone_id, alias_zid) WHERE alias_zid IS NOT NULL;
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
CREATE INDEX CONCURRENTLY IF NOT EXISTS active_and_type_in_zone on identity_provider (identity_zone_id, active, type);
1+
-- Create index without CONCURRENTLY to allow execution within a transaction
2+
-- CONCURRENTLY cannot be used inside a transaction, which causes hangs with newer Flyway versions
3+
-- The IF NOT EXISTS clause prevents errors if the index already exists
4+
CREATE INDEX IF NOT EXISTS active_and_type_in_zone on identity_provider (identity_zone_id, active, type);
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
CREATE INDEX CONCURRENTLY IF NOT EXISTS group_membership_idz_origin_idx ON group_membership(identity_zone_id, origin);
1+
-- Create index without CONCURRENTLY to allow execution within a transaction
2+
-- CONCURRENTLY cannot be used inside a transaction, which causes hangs with newer Flyway versions
3+
-- The IF NOT EXISTS clause prevents errors if the index already exists
4+
CREATE INDEX IF NOT EXISTS group_membership_idz_origin_idx ON group_membership(identity_zone_id, origin);

0 commit comments

Comments
 (0)