Use SQL for group related tables in schema upgrades

We want to get rid of most references of group related tables so that
we can simply drop those tables as soon as groups were successfully
migrated to NoteDb.

Change-Id: I59667ee235cba391559e523326eedb8323ebd6a9
This commit is contained in:
Alice Kober-Sotzek
2017-08-25 18:26:22 +02:00
parent e7f5e1975f
commit 64bf9e933b
3 changed files with 75 additions and 26 deletions

View File

@@ -14,17 +14,17 @@
package com.google.gerrit.server.schema;
import com.google.common.collect.Streams;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit.Key;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Comparator;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -36,21 +36,45 @@ public class Schema_151 extends SchemaVersion {
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
List<AccountGroup> accountGroups = db.accountGroups().all().toList();
for (AccountGroup accountGroup : accountGroups) {
ResultSet<AccountGroupMemberAudit> groupMemberAudits =
db.accountGroupMembersAudit().byGroup(accountGroup.getId());
Optional<Timestamp> firstTimeMentioned =
Streams.stream(groupMemberAudits)
.map(AccountGroupMemberAudit::getKey)
.map(Key::getAddedOn)
.min(Comparator.naturalOrder());
Timestamp createdOn =
firstTimeMentioned.orElseGet(() -> AccountGroup.auditCreationInstantTs());
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
try (PreparedStatement groupUpdate =
prepareStatement(db, "UPDATE account_groups SET created_on = ? WHERE group_id = ?");
PreparedStatement addedOnRetrieval =
prepareStatement(
db,
"SELECT added_on FROM account_group_members_audit WHERE group_id = ?"
+ " ORDER BY added_on ASC")) {
List<AccountGroup.Id> accountGroups = getAllGroupIds(db);
for (AccountGroup.Id groupId : accountGroups) {
Optional<Timestamp> firstTimeMentioned = getFirstTimeMentioned(addedOnRetrieval, groupId);
Timestamp createdOn = firstTimeMentioned.orElseGet(AccountGroup::auditCreationInstantTs);
accountGroup.setCreatedOn(createdOn);
groupUpdate.setTimestamp(1, createdOn);
groupUpdate.setInt(2, groupId.get());
groupUpdate.executeUpdate();
}
}
}
private static Optional<Timestamp> getFirstTimeMentioned(
PreparedStatement addedOnRetrieval, AccountGroup.Id groupId) throws SQLException {
addedOnRetrieval.setInt(1, groupId.get());
try (ResultSet resultSet = addedOnRetrieval.executeQuery()) {
if (resultSet.first()) {
return Optional.of(resultSet.getTimestamp(1));
}
}
return Optional.empty();
}
private static List<AccountGroup.Id> getAllGroupIds(ReviewDb db) throws SQLException {
try (Statement stmt = newStatement(db);
ResultSet rs = stmt.executeQuery("SELECT group_id FROM account_groups")) {
List<AccountGroup.Id> groupIds = new ArrayList<>();
while (rs.next()) {
groupIds.add(new AccountGroup.Id(rs.getInt(1)));
}
return groupIds;
}
db.accountGroups().update(accountGroups);
}
}

View File

@@ -20,11 +20,12 @@ import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
public class Schema_87 extends SchemaVersion {
@@ -35,16 +36,37 @@ public class Schema_87 extends SchemaVersion {
@Override
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
for (AccountGroup.Id id : scanSystemGroups(db)) {
AccountGroup group = db.accountGroups().get(id);
if (group != null && SystemGroupBackend.isSystemGroup(group.getGroupUUID())) {
db.accountGroups().delete(Collections.singleton(group));
db.accountGroupNames().deleteKeys(Collections.singleton(group.getNameKey()));
try (PreparedStatement uuidRetrieval =
prepareStatement(db, "SELECT group_uuid FROM account_groups WHERE group_id = ?");
PreparedStatement groupDeletion =
prepareStatement(db, "DELETE FROM account_groups WHERE group_id = ?");
PreparedStatement groupNameDeletion =
prepareStatement(db, "DELETE FROM account_group_names WHERE group_id = ?")) {
for (AccountGroup.Id id : scanSystemGroups(db)) {
Optional<AccountGroup.UUID> groupUuid = getUuid(uuidRetrieval, id);
if (groupUuid.filter(SystemGroupBackend::isSystemGroup).isPresent()) {
groupDeletion.setInt(1, id.get());
groupDeletion.executeUpdate();
groupNameDeletion.setInt(1, id.get());
groupNameDeletion.executeUpdate();
}
}
}
}
private Set<AccountGroup.Id> scanSystemGroups(ReviewDb db) throws SQLException {
private static Optional<AccountGroup.UUID> getUuid(
PreparedStatement uuidRetrieval, AccountGroup.Id id) throws SQLException {
uuidRetrieval.setInt(1, id.get());
try (ResultSet uuidResults = uuidRetrieval.executeQuery()) {
if (uuidResults.first()) {
Optional.of(new AccountGroup.UUID(uuidResults.getString(1)));
}
}
return Optional.empty();
}
private static Set<AccountGroup.Id> scanSystemGroups(ReviewDb db) throws SQLException {
try (Statement stmt = newStatement(db);
ResultSet rs =
stmt.executeQuery("SELECT group_id FROM account_groups WHERE group_type = 'SYSTEM'")) {

View File

@@ -15,6 +15,7 @@
package com.google.gerrit.server.schema;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.TruthJUnit.assume;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.TimeUtil;
@@ -28,6 +29,7 @@ import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.group.CreateGroup;
import com.google.gerrit.testutil.SchemaUpgradeTestEnvironment;
import com.google.gerrit.testutil.TestUpdateUI;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;
@@ -53,6 +55,7 @@ public class Schema_150_to_151_Test {
public void setUp() throws Exception {
testEnv.getInjector().injectMembers(this);
db = testEnv.getDb();
assume().that(db instanceof JdbcSchema).isTrue();
}
@Test