Merge changes from topic "sql-for-group-db-access-in-schema-upgrades"
* changes: Use SQL for group related tables in schema upgrade tests Use SQL for group related tables in schema upgrades
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'")) {
|
||||
|
||||
@@ -15,27 +15,29 @@
|
||||
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;
|
||||
import com.google.gerrit.extensions.api.groups.GroupInput;
|
||||
import com.google.gerrit.extensions.common.GroupInfo;
|
||||
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup.Id;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
|
||||
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.server.OrmException;
|
||||
import com.google.gwtorm.server.ResultSet;
|
||||
import com.google.gwtorm.jdbc.JdbcSchema;
|
||||
import com.google.inject.Inject;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Month;
|
||||
import java.time.ZoneOffset;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -48,11 +50,40 @@ public class Schema_150_to_151_Test {
|
||||
@Inject private Schema_151 schema151;
|
||||
|
||||
private ReviewDb db;
|
||||
private Connection connection;
|
||||
private PreparedStatement createdOnRetrieval;
|
||||
private PreparedStatement createdOnUpdate;
|
||||
private PreparedStatement auditEntryDeletion;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
testEnv.getInjector().injectMembers(this);
|
||||
db = testEnv.getDb();
|
||||
assume().that(db instanceof JdbcSchema).isTrue();
|
||||
|
||||
connection = ((JdbcSchema) db).getConnection();
|
||||
createdOnRetrieval =
|
||||
connection.prepareStatement("SELECT created_on FROM account_groups WHERE group_id = ?");
|
||||
createdOnUpdate =
|
||||
connection.prepareStatement("UPDATE account_groups SET created_on = ? WHERE group_id = ?");
|
||||
auditEntryDeletion =
|
||||
connection.prepareStatement("DELETE FROM account_group_members_audit WHERE group_id = ?");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (auditEntryDeletion != null) {
|
||||
auditEntryDeletion.close();
|
||||
}
|
||||
if (createdOnUpdate != null) {
|
||||
createdOnUpdate.close();
|
||||
}
|
||||
if (createdOnRetrieval != null) {
|
||||
createdOnRetrieval.close();
|
||||
}
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -63,8 +94,8 @@ public class Schema_150_to_151_Test {
|
||||
|
||||
schema151.migrateData(db, new TestUpdateUI());
|
||||
|
||||
AccountGroup group = db.accountGroups().get(groupId);
|
||||
assertThat(group.getCreatedOn()).isAtLeast(testStartTime);
|
||||
Timestamp createdOn = getCreatedOn(groupId);
|
||||
assertThat(createdOn).isAtLeast(testStartTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -75,8 +106,8 @@ public class Schema_150_to_151_Test {
|
||||
|
||||
schema151.migrateData(db, new TestUpdateUI());
|
||||
|
||||
AccountGroup group = db.accountGroups().get(groupId);
|
||||
assertThat(group.getCreatedOn()).isEqualTo(AccountGroup.auditCreationInstantTs());
|
||||
Timestamp createdOn = getCreatedOn(groupId);
|
||||
assertThat(createdOn).isEqualTo(AccountGroup.auditCreationInstantTs());
|
||||
}
|
||||
|
||||
private AccountGroup.Id createGroup(String name) throws Exception {
|
||||
@@ -87,16 +118,26 @@ public class Schema_150_to_151_Test {
|
||||
return new Id(groupInfo.groupId);
|
||||
}
|
||||
|
||||
private void setCreatedOnToVeryOldTimestamp(Id groupId) throws OrmException {
|
||||
AccountGroup group = db.accountGroups().get(groupId);
|
||||
private Timestamp getCreatedOn(Id groupId) throws Exception {
|
||||
createdOnRetrieval.setInt(1, groupId.get());
|
||||
try (ResultSet results = createdOnRetrieval.executeQuery()) {
|
||||
if (results.first()) {
|
||||
return results.getTimestamp(1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setCreatedOnToVeryOldTimestamp(Id groupId) throws Exception {
|
||||
createdOnUpdate.setInt(1, groupId.get());
|
||||
Instant instant = LocalDateTime.of(1800, Month.JANUARY, 1, 0, 0).toInstant(ZoneOffset.UTC);
|
||||
group.setCreatedOn(Timestamp.from(instant));
|
||||
db.accountGroups().update(ImmutableList.of(group));
|
||||
createdOnUpdate.setTimestamp(1, Timestamp.from(instant));
|
||||
createdOnUpdate.setInt(2, groupId.get());
|
||||
createdOnUpdate.executeUpdate();
|
||||
}
|
||||
|
||||
private void removeAuditEntriesFor(AccountGroup.Id groupId) throws Exception {
|
||||
ResultSet<AccountGroupMemberAudit> groupMemberAudits =
|
||||
db.accountGroupMembersAudit().byGroup(groupId);
|
||||
db.accountGroupMembersAudit().delete(groupMemberAudits);
|
||||
auditEntryDeletion.setInt(1, groupId.get());
|
||||
auditEntryDeletion.executeUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user