Schema_151: Attempt to add created_on column if it doesn't exist
If the created_on column does not exist, attempt to create it.
This allows the direct migration from 2.14 to 2.16 to succeed
without requiring an intermediate migration to 2.15.
Bug: Issue 10248
Change-Id: I626f1e26d43b60c3fd62ef3ef9ce3d7047c1a383
diff --git a/java/com/google/gerrit/server/schema/Schema_151.java b/java/com/google/gerrit/server/schema/Schema_151.java
index 41d8a32..bab9f41 100644
--- a/java/com/google/gerrit/server/schema/Schema_151.java
+++ b/java/com/google/gerrit/server/schema/Schema_151.java
@@ -14,11 +14,15 @@
package com.google.gerrit.server.schema;
+import com.google.common.annotations.VisibleForTesting;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -26,6 +30,7 @@
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import java.util.Optional;
/** A schema which adds the 'created on' field to groups. */
@@ -37,6 +42,13 @@
@Override
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
+ Connection connection = ((JdbcSchema) db).getConnection();
+ if (!createdOnColumnExists(connection)) {
+ try (Statement stmt = connection.createStatement()) {
+ stmt.execute("ALTER TABLE account_groups ADD COLUMN created_on TIMESTAMP NULL");
+ }
+ }
+
try (PreparedStatement groupUpdate =
prepareStatement(db, "UPDATE account_groups SET created_on = ? WHERE group_id = ?");
PreparedStatement addedOnRetrieval =
@@ -56,6 +68,20 @@
}
}
+ @VisibleForTesting
+ public static boolean createdOnColumnExists(Connection connection) throws SQLException {
+ DatabaseMetaData metaData = connection.getMetaData();
+ boolean toUpper = metaData.storesUpperCaseIdentifiers();
+ return metaData
+ .getColumns(
+ null, null, convertCase(toUpper, "account_groups"), convertCase(toUpper, "created_on"))
+ .next();
+ }
+
+ private static String convertCase(boolean toUpper, String input) {
+ return toUpper ? input.toUpperCase(Locale.US) : input;
+ }
+
private static Optional<Timestamp> getFirstTimeMentioned(
PreparedStatement addedOnRetrieval, AccountGroup.Id groupId) throws SQLException {
addedOnRetrieval.setInt(1, groupId.get());
diff --git a/javatests/com/google/gerrit/server/schema/Schema_150_to_151_Test.java b/javatests/com/google/gerrit/server/schema/Schema_150_to_151_Test.java
index 4d5db6d..2e268ee 100644
--- a/javatests/com/google/gerrit/server/schema/Schema_150_to_151_Test.java
+++ b/javatests/com/google/gerrit/server/schema/Schema_150_to_151_Test.java
@@ -16,6 +16,7 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.TruthJUnit.assume;
+import static com.google.gerrit.server.schema.Schema_151.createdOnColumnExists;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
@@ -151,6 +152,17 @@
assertThat(createdOn).isEqualTo(AccountGroup.auditCreationInstantTs());
}
+ @Test
+ public void createdOnIsAddedWhenItIsMissing() throws Exception {
+ assertThat(createdOnColumnExists(connection)).isTrue();
+ try (Statement deleteColumn = connection.createStatement()) {
+ deleteColumn.execute("ALTER TABLE account_groups DROP COLUMN created_on");
+ }
+ assertThat(createdOnColumnExists(connection)).isFalse();
+ schema151.migrateData(db, new TestUpdateUI());
+ assertThat(createdOnColumnExists(connection)).isTrue();
+ }
+
private AccountGroup.Id createGroupInReviewDb(String name) throws Exception {
AccountGroup group =
new AccountGroup(