From 9e3f330be63f344e718f56f180effc84be3f21c6 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 21 Oct 2014 14:10:47 +0200 Subject: [PATCH] SONAR-5753 Add migration to populate UUID columns --- .../db/migrations/DatabaseMigrations.java | 4 +- .../PopulateProjectsUuidColumnsMigration.java | 113 ++++++++++++ ...ulateProjectsUuidColumnsMigrationTest.java | 171 ++++++++++++++++++ .../migrate_developer.xml | 18 ++ .../migrate_library.xml | 10 + .../migrate_projects.xml | 82 +++++++++ .../migrate_provisioned_project.xml | 10 + .../migrate_view.xml | 18 ++ .../not_migrate_technical_projects-result.xml | 19 ++ .../not_migrate_technical_projects.xml | 19 ++ .../schema.sql | 55 ++++++ .../705_populate_projects_uuid_columns.rb | 32 ++++ .../core/persistence/DatabaseVersion.java | 2 +- .../org/sonar/core/persistence/MyBatis.java | 3 +- .../persistence/migration/v50/Component.java | 121 +++++++++++++ .../migration/v50/Migration50Mapper.java | 74 ++++++++ .../migration/v50/package-info.java | 24 +++ .../migration/v50/Migration50Mapper.xml | 7 + .../org/sonar/core/persistence/rows-h2.sql | 1 + .../migration/v50/ComponentTest.java | 37 ++++ 20 files changed, 817 insertions(+), 3 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigration.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest.java create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_developer.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_library.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_projects.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_provisioned_project.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_view.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/not_migrate_technical_projects-result.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/not_migrate_technical_projects.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/schema.sql create mode 100644 server/sonar-web/src/main/webapp/WEB-INF/db/migrate/705_populate_projects_uuid_columns.rb create mode 100644 sonar-core/src/main/java/org/sonar/core/persistence/migration/v50/Component.java create mode 100644 sonar-core/src/main/java/org/sonar/core/persistence/migration/v50/Migration50Mapper.java create mode 100644 sonar-core/src/main/java/org/sonar/core/persistence/migration/v50/package-info.java create mode 100644 sonar-core/src/main/resources/org/sonar/core/persistence/migration/v50/Migration50Mapper.xml create mode 100644 sonar-core/src/test/java/org/sonar/core/persistence/migration/v50/ComponentTest.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java index f5ef2c46688..f81424d5c6b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java +++ b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java @@ -29,6 +29,7 @@ import org.sonar.server.db.migrations.v45.AddMissingCustomRuleParametersMigratio import org.sonar.server.db.migrations.v45.AddMissingRuleParameterDefaultValuesMigration; import org.sonar.server.db.migrations.v45.DeleteMeasuresOnDeletedProfilesMigration; import org.sonar.server.db.migrations.v50.InsertProjectsAuthorizationUpdatedAtMigration; +import org.sonar.server.db.migrations.v50.PopulateProjectsUuidColumnsMigration; import java.util.List; @@ -63,7 +64,8 @@ public interface DatabaseMigrations { AddMissingCustomRuleParametersMigration.class, // 5.0 - InsertProjectsAuthorizationUpdatedAtMigration.class + InsertProjectsAuthorizationUpdatedAtMigration.class, + PopulateProjectsUuidColumnsMigration.class ); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigration.java b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigration.java new file mode 100644 index 00000000000..222bd793fa9 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigration.java @@ -0,0 +1,113 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.db.migrations.v50; + +import com.google.common.base.Splitter; +import com.google.common.base.Strings; +import org.sonar.api.resources.Scopes; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.migration.v50.Component; +import org.sonar.core.persistence.migration.v50.Migration50Mapper; +import org.sonar.server.db.DbClient; +import org.sonar.server.db.migrations.DatabaseMigration; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static com.google.common.collect.Maps.newHashMap; + +/** + * Used in the Active Record Migration 705 + * + * @since 5.0 + */ +public class PopulateProjectsUuidColumnsMigration implements DatabaseMigration { + + private final DbClient db; + + public PopulateProjectsUuidColumnsMigration(DbClient db) { + this.db = db; + } + + @Override + public void execute() { + DbSession session = db.openSession(true); + try { + Migration50Mapper mapper = session.getMapper(Migration50Mapper.class); + + for (Component project : mapper.selectEnabledRootTrkProjects()) { + Map uuidByComponentId = newHashMap(); + Map componentsBySnapshotId = newHashMap(); + + List components = mapper.selectComponentChildrenForProjects(project.getId()); + components.add(project); + for (Component component : components) { + componentsBySnapshotId.put(component.getSnapshotId(), component); + + component.setUuid(getOrCreateUuid(component.getId(), uuidByComponentId)); + component.setProjectUuid(getOrCreateUuid(project.getId(), uuidByComponentId)); + } + + for (Component component : components) { + String snapshotPath = component.getSnapshotPath(); + StringBuilder moduleUuidPath = new StringBuilder(); + Component lastModule = null; + if (!Strings.isNullOrEmpty(snapshotPath)) { + for (String s : Splitter.on(".").omitEmptyStrings().split(snapshotPath)) { + Long snapshotId = Long.valueOf(s); + Component currentComponent = componentsBySnapshotId.get(snapshotId); + if (currentComponent.getScope().equals(Scopes.PROJECT)) { + lastModule = currentComponent; + moduleUuidPath.append(currentComponent.getUuid()).append("."); + } + } + } + if (moduleUuidPath.length() > 0) { + component.setModuleUuidPath(moduleUuidPath.toString()); + } + + // Module UUID should contains direct module of a component, but it should be null on the first module + if (lastModule != null && !lastModule.getId().equals(project.getId())) { + component.setModuleUuid(getOrCreateUuid(lastModule.getId(), uuidByComponentId)); + } + + mapper.updateComponentUuids(component); + } + } + + session.commit(); + } finally { + session.close(); + } + } + + private static String getOrCreateUuid(Long componentId, Map uuidByComponentId) { + String uuid = uuidByComponentId.get(componentId); + if (uuid == null) { + String newUuid = UUID.randomUUID().toString(); + uuidByComponentId.put(componentId, newUuid); + return newUuid; + } + return uuid; + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest.java b/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest.java new file mode 100644 index 00000000000..9c1fcdb67b5 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest.java @@ -0,0 +1,171 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.db.migrations.v50; + +import com.google.common.collect.ImmutableSet; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.TestDatabase; +import org.sonar.core.persistence.migration.v50.Component; +import org.sonar.core.persistence.migration.v50.Migration50Mapper; +import org.sonar.server.db.DbClient; +import org.sonar.server.db.migrations.DatabaseMigration; + +import static org.fest.assertions.Assertions.assertThat; + +public class PopulateProjectsUuidColumnsMigrationTest { + + @ClassRule + public static TestDatabase db = new TestDatabase().schema(PopulateProjectsUuidColumnsMigrationTest.class, "schema.sql"); + + DbSession session; + + DbClient dbClient; + + Migration50Mapper mapper; + + DatabaseMigration migration; + + @Before + public void setUp() throws Exception { + db.executeUpdateSql("truncate table projects"); + db.executeUpdateSql("truncate table snapshots"); + dbClient = new DbClient(db.database(), db.myBatis()); + session = dbClient.openSession(false); + mapper = session.getMapper(Migration50Mapper.class); + migration = new PopulateProjectsUuidColumnsMigration(dbClient); + } + + @After + public void tearDown() throws Exception { + session.close(); + } + + @Test + public void migrate_projects() throws Exception { + db.prepareDbUnit(getClass(), "migrate_projects.xml"); + + migration.execute(); + session.commit(); + + Component root = mapper.selectComponentByKey("org.struts:struts"); + assertThat(root.getUuid()).isNotNull(); + assertThat(root.getProjectUuid()).isEqualTo(root.getUuid()); + assertThat(root.getModuleUuid()).isNull(); + assertThat(root.getModuleUuidPath()).isNull(); + + Component module = mapper.selectComponentByKey("org.struts:struts-core"); + assertThat(module.getUuid()).isNotNull(); + assertThat(module.getProjectUuid()).isEqualTo(root.getUuid()); + assertThat(module.getModuleUuid()).isNull(); + assertThat(module.getModuleUuidPath()).isEqualTo(root.getUuid() + "."); + + Component subModule = mapper.selectComponentByKey("org.struts:struts-db"); + assertThat(subModule.getUuid()).isNotNull(); + assertThat(subModule.getProjectUuid()).isEqualTo(root.getUuid()); + assertThat(subModule.getModuleUuid()).isEqualTo(module.getUuid()); + assertThat(subModule.getModuleUuidPath()).isEqualTo(root.getUuid() + "." + module.getUuid() + "."); + + Component directory = mapper.selectComponentByKey("org.struts:struts-core:src/org/struts"); + assertThat(directory.getUuid()).isNotNull(); + assertThat(directory.getProjectUuid()).isEqualTo(root.getUuid()); + assertThat(directory.getModuleUuid()).isEqualTo(subModule.getUuid()); + assertThat(directory.getModuleUuidPath()).isEqualTo(root.getUuid() + "." + module.getUuid() + "." + subModule.getUuid() + "."); + + Component file = mapper.selectComponentByKey("org.struts:struts-core:src/org/struts/RequestContext.java"); + assertThat(file.getUuid()).isNotNull(); + assertThat(file.getProjectUuid()).isEqualTo(root.getUuid()); + assertThat(file.getModuleUuid()).isEqualTo(subModule.getUuid()); + assertThat(file.getModuleUuidPath()).isEqualTo(root.getUuid() + "." + module.getUuid() + "." + subModule.getUuid() + "."); + + // Verify that each generated uuid is unique + assertThat(ImmutableSet.of(root.getUuid(), module.getUuid(), subModule.getUuid(), directory.getUuid(), file.getUuid())).hasSize(5); + } + + @Test + public void migrate_provisioned_project() throws Exception { + db.prepareDbUnit(getClass(), "migrate_provisioned_project.xml"); + + migration.execute(); + session.commit(); + + Component root = mapper.selectComponentByKey("org.struts:struts"); + assertThat(root.getUuid()).isNotNull(); + assertThat(root.getProjectUuid()).isEqualTo(root.getUuid()); + assertThat(root.getModuleUuid()).isNull(); + assertThat(root.getModuleUuidPath()).isNull(); + } + + @Test + public void migrate_library() throws Exception { + db.prepareDbUnit(getClass(), "migrate_library.xml"); + + migration.execute(); + session.commit(); + + Component root = mapper.selectComponentByKey("org.hamcrest:hamcrest-library"); + assertThat(root.getUuid()).isNotNull(); + assertThat(root.getProjectUuid()).isEqualTo(root.getUuid()); + assertThat(root.getModuleUuid()).isNull(); + assertThat(root.getModuleUuidPath()).isNull(); + } + + @Test + public void not_migrate_view() throws Exception { + db.prepareDbUnit(getClass(), "migrate_view.xml"); + + migration.execute(); + session.commit(); + + Component root = mapper.selectComponentByKey("view"); + assertThat(root.getUuid()).isNull(); + assertThat(root.getProjectUuid()).isNull(); + assertThat(root.getModuleUuid()).isNull(); + assertThat(root.getModuleUuidPath()).isNull(); + } + + @Test + public void not_migrate_developer() throws Exception { + db.prepareDbUnit(getClass(), "migrate_developer.xml"); + + migration.execute(); + session.commit(); + + Component root = mapper.selectComponentByKey("DEV:developer@company.net"); + assertThat(root.getUuid()).isNull(); + assertThat(root.getProjectUuid()).isNull(); + assertThat(root.getModuleUuid()).isNull(); + assertThat(root.getModuleUuidPath()).isNull(); + } + + @Test + public void not_migrate_technical_projects() throws Exception { + db.prepareDbUnit(getClass(), "not_migrate_technical_projects.xml"); + + migration.execute(); + + db.assertDbUnit(getClass(), "not_migrate_technical_projects.xml"); + } + +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_developer.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_developer.xml new file mode 100644 index 00000000000..9d518e84c76 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_developer.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_library.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_library.xml new file mode 100644 index 00000000000..4740588290e --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_library.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_projects.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_projects.xml new file mode 100644 index 00000000000..14ba41f91d4 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_projects.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_provisioned_project.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_provisioned_project.xml new file mode 100644 index 00000000000..a38323d7a19 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_provisioned_project.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_view.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_view.xml new file mode 100644 index 00000000000..79021a863b9 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/migrate_view.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/not_migrate_technical_projects-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/not_migrate_technical_projects-result.xml new file mode 100644 index 00000000000..302f21763a1 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/not_migrate_technical_projects-result.xml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/not_migrate_technical_projects.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/not_migrate_technical_projects.xml new file mode 100644 index 00000000000..302f21763a1 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/not_migrate_technical_projects.xml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/schema.sql b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/schema.sql new file mode 100644 index 00000000000..22b95030079 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationTest/schema.sql @@ -0,0 +1,55 @@ +CREATE TABLE "PROJECTS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "KEE" VARCHAR(400), + "ROOT_ID" INTEGER, + "UUID" VARCHAR(50), + "PROJECT_UUID" VARCHAR(50), + "MODULE_UUID" VARCHAR(50), + "MODULE_UUID_PATH" VARCHAR(4000), + "NAME" VARCHAR(256), + "DESCRIPTION" VARCHAR(2000), + "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE, + "SCOPE" VARCHAR(3), + "QUALIFIER" VARCHAR(10), + "DEPRECATED_KEE" VARCHAR(400), + "PATH" VARCHAR(2000), + "LANGUAGE" VARCHAR(20), + "COPY_RESOURCE_ID" INTEGER, + "LONG_NAME" VARCHAR(256), + "PERSON_ID" INTEGER, + "CREATED_AT" TIMESTAMP, + "AUTHORIZATION_UPDATED_AT" TIMESTAMP +); + +CREATE TABLE "SNAPSHOTS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "CREATED_AT" TIMESTAMP, + "BUILD_DATE" TIMESTAMP, + "PROJECT_ID" INTEGER NOT NULL, + "PARENT_SNAPSHOT_ID" INTEGER, + "STATUS" VARCHAR(4) NOT NULL DEFAULT 'U', + "PURGE_STATUS" INTEGER, + "ISLAST" BOOLEAN NOT NULL DEFAULT FALSE, + "SCOPE" VARCHAR(3), + "QUALIFIER" VARCHAR(10), + "ROOT_SNAPSHOT_ID" INTEGER, + "VERSION" VARCHAR(500), + "PATH" VARCHAR(500), + "DEPTH" INTEGER, + "ROOT_PROJECT_ID" INTEGER, + "PERIOD1_MODE" VARCHAR(100), + "PERIOD1_PARAM" VARCHAR(100), + "PERIOD1_DATE" TIMESTAMP, + "PERIOD2_MODE" VARCHAR(100), + "PERIOD2_PARAM" VARCHAR(100), + "PERIOD2_DATE" TIMESTAMP, + "PERIOD3_MODE" VARCHAR(100), + "PERIOD3_PARAM" VARCHAR(100), + "PERIOD3_DATE" TIMESTAMP, + "PERIOD4_MODE" VARCHAR(100), + "PERIOD4_PARAM" VARCHAR(100), + "PERIOD4_DATE" TIMESTAMP, + "PERIOD5_MODE" VARCHAR(100), + "PERIOD5_PARAM" VARCHAR(100), + "PERIOD5_DATE" TIMESTAMP +); diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/705_populate_projects_uuid_columns.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/705_populate_projects_uuid_columns.rb new file mode 100644 index 00000000000..a08d370720b --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/705_populate_projects_uuid_columns.rb @@ -0,0 +1,32 @@ +# +# SonarQube, open source software quality management tool. +# Copyright (C) 2008-2014 SonarSource +# mailto:contact AT sonarsource DOT com +# +# SonarQube is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# SonarQube is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +# +# SonarQube 5.0 +# SONAR-5753 +# +class PopulateProjectsUuidColumns < ActiveRecord::Migration + + def self.up + execute_java_migration('org.sonar.server.db.migrations.v50.PopulateProjectsUuidColumnsMigration') + end + +end + diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java index b3abd5d623e..de50ab9b538 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java @@ -33,7 +33,7 @@ import java.util.List; */ public class DatabaseVersion implements BatchComponent, ServerComponent { - public static final int LAST_VERSION = 704; + public static final int LAST_VERSION = 705; /** * List of all the tables. * This list is hardcoded because we didn't succeed in using java.sql.DatabaseMetaData#getTables() in the same way diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java index 6f9ebbe4461..fba96a99c1b 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java @@ -58,6 +58,7 @@ import org.sonar.core.notification.db.NotificationQueueMapper; import org.sonar.core.permission.*; import org.sonar.core.persistence.migration.v44.Migration44Mapper; import org.sonar.core.persistence.migration.v45.Migration45Mapper; +import org.sonar.core.persistence.migration.v50.Migration50Mapper; import org.sonar.core.properties.PropertiesMapper; import org.sonar.core.properties.PropertyDto; import org.sonar.core.purge.PurgeMapper; @@ -180,7 +181,7 @@ public class MyBatis implements BatchComponent, ServerComponent { MeasureMapper.class, MetricMapper.class, QualityGateMapper.class, QualityGateConditionMapper.class, ComponentMapper.class, SnapshotMapper.class, ProjectQgateAssociationMapper.class, AnalysisReportMapper.class, - Migration45Mapper.class + Migration45Mapper.class, Migration50Mapper.class }; loadMappers(conf, mappers); configureLogback(mappers); diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/migration/v50/Component.java b/sonar-core/src/main/java/org/sonar/core/persistence/migration/v50/Component.java new file mode 100644 index 00000000000..b16a9d1e651 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/persistence/migration/v50/Component.java @@ -0,0 +1,121 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.core.persistence.migration.v50; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public class Component { + + private Long id; + private Long projectId; + private Long snapshotId; + private String snapshotPath; + private String scope; + + private String uuid; + private String projectUuid; + private String moduleUuid; + private String moduleUuidPath; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + /** + * Can be null on provisioned projects or library + */ + @CheckForNull + public Long getProjectId() { + return projectId; + } + + public void setProjectId(@Nullable Long projectId) { + this.projectId = projectId; + } + + /** + * Can be null on provisioned projects or library + */ + @CheckForNull + public Long getSnapshotId() { + return snapshotId; + } + + public void setSnapshotId(@Nullable Long snapshotId) { + this.snapshotId = snapshotId; + } + + @CheckForNull + public String getSnapshotPath() { + return snapshotPath; + } + + public void setSnapshotPath(@Nullable String snapshotPath) { + this.snapshotPath = snapshotPath; + } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getProjectUuid() { + return projectUuid; + } + + public void setProjectUuid(String projectUuid) { + this.projectUuid = projectUuid; + } + + @CheckForNull + public String getModuleUuid() { + return moduleUuid; + } + + public void setModuleUuid(@Nullable String moduleUuid) { + this.moduleUuid = moduleUuid; + } + + @CheckForNull + public String getModuleUuidPath() { + return moduleUuidPath; + } + + public void setModuleUuidPath(@Nullable String moduleUuidPath) { + this.moduleUuidPath = moduleUuidPath; + } +} diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/migration/v50/Migration50Mapper.java b/sonar-core/src/main/java/org/sonar/core/persistence/migration/v50/Migration50Mapper.java new file mode 100644 index 00000000000..72e3f492250 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/persistence/migration/v50/Migration50Mapper.java @@ -0,0 +1,74 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.core.persistence.migration.v50; + +import org.apache.ibatis.annotations.*; +import org.apache.ibatis.mapping.ResultSetType; +import org.apache.ibatis.mapping.StatementType; + +import java.util.List; + +public interface Migration50Mapper { + + @Select("SELECT " + + " p.id AS \"id\", " + + " s.root_project_id AS \"projectId\", " + + " s.id AS \"snapshotId\", " + + " s.path AS \"snapshotPath\", " + + " p.scope AS \"scope\" " + + "FROM projects p " + + " LEFT OUTER JOIN snapshots s ON s.project_id = p.id AND s.islast = ${_true} " + + " WHERE p.scope = 'PRJ' AND p.qualifier <> 'VW' AND p.qualifier <> 'DEV' AND p.root_id IS NULL AND p.enabled=${_true}") + @Result(javaType = Component.class) + @Options(statementType = StatementType.PREPARED, resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 200) + List selectEnabledRootTrkProjects(); + + @Select("SELECT " + + " p.id AS \"id\", " + + " s.root_project_id AS \"projectId\", " + + " s.id AS \"snapshotId\", " + + " s.path AS \"snapshotPath\", " + + " p.scope AS \"scope\" " + + "FROM projects root " + + " INNER JOIN snapshots root_snapshot ON root_snapshot.project_id = root.id AND root_snapshot.islast = ${_true} " + + " INNER JOIN snapshots s ON s.root_snapshot_id = root_snapshot.id AND s.islast = ${_true} " + + " INNER JOIN projects p ON p.id = s.project_id" + + " WHERE root.id = #{id}") + @Result(javaType = Component.class) + List selectComponentChildrenForProjects(@Param("id") Long projectId); + + @Select("SELECT " + + " p.id AS \"id\", " + + " p.uuid AS \"uuid\", " + + " p.project_uuid AS \"projectUuid\", " + + " p.module_uuid AS \"moduleUuid\", " + + " p.module_uuid_path AS \"moduleUuidPath\" " + + "FROM projects p " + + " WHERE p.kee = #{key}") + @Result(javaType = Component.class) + Component selectComponentByKey(@Param("key") String key); + + @Update("UPDATE projects " + + " SET uuid=#{uuid}, project_uuid=#{projectUuid}, module_uuid=#{moduleUuid}, module_uuid_path=#{moduleUuidPath} " + + " WHERE id=#{id}") + void updateComponentUuids(Component component); + +} diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/migration/v50/package-info.java b/sonar-core/src/main/java/org/sonar/core/persistence/migration/v50/package-info.java new file mode 100644 index 00000000000..af7d784eb29 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/persistence/migration/v50/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +@ParametersAreNonnullByDefault +package org.sonar.core.persistence.migration.v50; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/migration/v50/Migration50Mapper.xml b/sonar-core/src/main/resources/org/sonar/core/persistence/migration/v50/Migration50Mapper.xml new file mode 100644 index 00000000000..1db97943867 --- /dev/null +++ b/sonar-core/src/main/resources/org/sonar/core/persistence/migration/v50/Migration50Mapper.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql index b039308d5bb..6bd7b5bd800 100644 --- a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql +++ b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql @@ -263,6 +263,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('701'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('702'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('703'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('704'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('705'); INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null); ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2; diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/migration/v50/ComponentTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/migration/v50/ComponentTest.java new file mode 100644 index 00000000000..cea162271a0 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/persistence/migration/v50/ComponentTest.java @@ -0,0 +1,37 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.core.persistence.migration.v50; + +import org.junit.Test; + +import static com.google.code.beanmatchers.BeanMatchers.hasValidGettersAndSetters; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; + +public class ComponentTest { + + @Test + public void test_bean() throws Exception { + assertThat(Component.class, allOf( + hasValidGettersAndSetters())); + } + +} -- 2.39.5