diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2018-02-12 10:44:44 +0100 |
---|---|---|
committer | Stas Vilchik <stas.vilchik@sonarsource.com> | 2018-02-20 10:06:52 +0100 |
commit | 209c36aefa2c16b5b156b21604664ff32ef13a86 (patch) | |
tree | 42ab8ac9b571ba44af64d0020aab9a7e09a09bb3 /server/sonar-db-migration | |
parent | fff2b9bcc5e0668dfc36a8a34000aac0ae9c10e7 (diff) | |
download | sonarqube-209c36aefa2c16b5b156b21604664ff32ef13a86.tar.gz sonarqube-209c36aefa2c16b5b156b21604664ff32ef13a86.zip |
SONAR-10411 Do not persist name of provided project links
Diffstat (limited to 'server/sonar-db-migration')
16 files changed, 791 insertions, 10 deletions
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilder.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilder.java index f5adc72ba9a..ef381ab3f82 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilder.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilder.java @@ -19,7 +19,6 @@ */ package org.sonar.server.platform.db.migration.sql; -import java.util.Arrays; import java.util.List; import org.sonar.db.dialect.Dialect; import org.sonar.db.dialect.H2; @@ -29,19 +28,16 @@ import org.sonar.db.dialect.Oracle; import org.sonar.db.dialect.PostgreSql; import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.sonar.server.platform.db.migration.def.Validations.validateTableName; -/** - * Limitation: only tables with auto-generated ID column can - * be renamed as the Oracle implementation assumes that - * the sequence and trigger related to ID column exist. - */ public class RenameTableBuilder { private final Dialect dialect; private String name; private String newName; + private boolean autoGeneratedId = true; public RenameTableBuilder(Dialect dialect) { this.dialect = dialect; @@ -57,6 +53,18 @@ public class RenameTableBuilder { return this; } + /** + * When a table has no auto generated id, this parameter has to be set to false. + * On Oracle, it will allow to not try to drop and recreate the trigger. + * On other databases, this method is useless. + * + * Default value is true. + */ + public RenameTableBuilder setAutoGeneratedId(boolean autoGeneratedId) { + this.autoGeneratedId = autoGeneratedId; + return this; + } + public List<String> build() { validateTableName(name); validateTableName(newName); @@ -73,11 +81,13 @@ public class RenameTableBuilder { case MsSql.ID: return singletonList("EXEC sp_rename '" + name + "', '" + newName + "'"); case Oracle.ID: - return Arrays.asList( + String renameSqlCommand = "RENAME " + name + " TO " + newName; + return autoGeneratedId ? asList( "DROP TRIGGER " + name + "_idt", - "RENAME " + name + " TO " + newName, + renameSqlCommand, "RENAME " + name + "_seq TO " + newName + "_seq", - CreateTableBuilder.createOracleTriggerForTable(newName)); + CreateTableBuilder.createOracleTriggerForTable(newName)) + : singletonList(renameSqlCommand); default: throw new IllegalArgumentException("Unsupported dialect id " + dialect.getId()); } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2.java new file mode 100644 index 00000000000..d1be6af38fc --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2.java @@ -0,0 +1,77 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.platform.db.migration.version.v71; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.sql.CreateTableBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +import static org.sonar.server.platform.db.migration.def.BigIntegerColumnDef.newBigIntegerColumnDefBuilder; +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE; +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; + +public class CreateTableProjectLinks2 extends DdlChange { + + private static final String TABLE_NAME = "project_links2"; + + public CreateTableProjectLinks2(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + context.execute(new CreateTableBuilder(getDialect(), TABLE_NAME) + .addPkColumn(newVarcharColumnDefBuilder() + .setColumnName("uuid") + .setLimit(UUID_SIZE) + .setIsNullable(false) + .build()) + .addColumn(newVarcharColumnDefBuilder() + .setColumnName("project_uuid") + .setLimit(UUID_SIZE) + .setIsNullable(false) + .build()) + .addColumn(newVarcharColumnDefBuilder() + .setColumnName("link_type") + .setLimit(20) + .setIsNullable(false) + .build()) + .addColumn(newVarcharColumnDefBuilder() + .setColumnName("name") + .setLimit(128) + .setIsNullable(true) + .build()) + .addColumn(newVarcharColumnDefBuilder() + .setColumnName("href") + .setLimit(2048) + .setIsNullable(false) + .build()) + .addColumn(newBigIntegerColumnDefBuilder() + .setColumnName("created_at") + .setIsNullable(false) + .build()) + .addColumn(newBigIntegerColumnDefBuilder() + .setColumnName("updated_at") + .setIsNullable(false) + .build()) + .build()); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71.java index a1cdf16d6e3..1e18627e81c 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71.java @@ -35,6 +35,11 @@ public class DbVersion71 implements DbVersion { .add(2005, "Create table DEPRECATED_RULE_KEYS", CreateDeprecatedRuleKeysTable.class) .add(2006, "Clean orphans in Compute Engine child tables", CleanCeChildTablesOrphans.class) .add(2007, "Update PERMISSION_TEMPLATES.KEYS ", UpdatePermissionTooLongTemplateKeys.class) + .add(2008, "Make scope not nullable in rules", MakeScopeNotNullableInRules.class) + .add(2009, "Create table PROJECT_LINKS2", CreateTableProjectLinks2.class) + .add(2010, "Populate table PROJECT_LINKS2", PopulateTableProjectLinks2.class) + .add(2011, "Drop table PROJECT_LINKS", DropTableProjectLinks.class) + .add(2012, "Rename table PROJECT_LINKS2 to PROJECT_LINKS", RenameTableProjectLinks2ToProjectLinks.class) ; } } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinks.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinks.java new file mode 100644 index 00000000000..ca2950b8bdb --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinks.java @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.platform.db.migration.version.v71; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.sql.DropTableBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +public class DropTableProjectLinks extends DdlChange { + + private static final String TABLE_NAME = "project_links"; + + public DropTableProjectLinks(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + context.execute(new DropTableBuilder(getDialect(), TABLE_NAME).build()); + } + +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2.java new file mode 100644 index 00000000000..a42f8694604 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2.java @@ -0,0 +1,112 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.platform.db.migration.version.v71; + +import com.google.common.collect.ImmutableList; +import java.sql.SQLException; +import java.util.List; +import org.sonar.api.utils.System2; +import org.sonar.core.util.UuidFactory; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.step.DataChange; +import org.sonar.server.platform.db.migration.step.MassUpdate; + +/** + * Populate PROJECT_LINK2 data from PROJECT_LINK table and take the opportunity to do some cleanup : + * - Ignore link that are not set on project (only take component with qualifier TRK and scope PRJ) + * - Do not set a name on provided links (SONAR-10411) + * - Do not copy link on Developer Connection (SONAR-10299) + */ +public class PopulateTableProjectLinks2 extends DataChange { + + private static final String TYPE_HOME_PAGE = "homepage"; + private static final String TYPE_CI = "ci"; + private static final String TYPE_ISSUE_TRACKER = "issue"; + private static final String TYPE_SOURCES = "scm"; + private static final String TYPE_SOURCES_DEV = "scm_dev"; + private static final List<String> PROVIDED_TYPES = ImmutableList.of(TYPE_HOME_PAGE, TYPE_CI, TYPE_ISSUE_TRACKER, TYPE_SOURCES); + + private static final String SCOPE_PROJECT = "PRJ"; + private static final String QUALIFIER_PROJECT = "TRK"; + + private final UuidFactory uuidFactory; + private final System2 system2; + + public PopulateTableProjectLinks2(Database db, UuidFactory uuidFactory, System2 system2) { + super(db); + this.uuidFactory = uuidFactory; + this.system2 = system2; + } + + @Override + public void execute(Context context) throws SQLException { + long now = system2.now(); + MassUpdate massUpdate = context.prepareMassUpdate(); + massUpdate.select("SELECT" + + " p.component_uuid, p.link_type, p.name, p.href" + + " from project_links p" + + // Join on projects in order to sanitize orphans (if any) + " inner join projects prj on prj.uuid=p.component_uuid and prj.scope=? and prj.qualifier=? " + + " left outer join project_links2 p2" + + " on p2.project_uuid=p.component_uuid " + + " and p2.href=p.href" + + " and p2.link_type=p.link_type" + + " and (p2.name=p.name or (p2.name is null and p.link_type in (?, ?, ?, ?)))" + + " where" + + " p2.uuid is null" + + " order by p.id") + .setString(1, SCOPE_PROJECT) + .setString(2, QUALIFIER_PROJECT) + .setString(3, TYPE_HOME_PAGE) + .setString(4, TYPE_CI) + .setString(5, TYPE_ISSUE_TRACKER) + .setString(6, TYPE_SOURCES); + massUpdate.update("insert into project_links2" + + " (uuid, project_uuid, link_type, name, href, created_at, updated_at)" + + " values " + + " (?, ?, ?, ?, ?, ?, ?)"); + massUpdate.rowPluralName("project links"); + massUpdate.execute((row, update) -> { + String componentUuid = row.getString(1); + String linkType = row.getString(2); + String name = row.getString(3); + String href = row.getString(4); + + // project link "developer connection" are removed + if (linkType.equals(TYPE_SOURCES_DEV)) { + return false; + } + + update.setString(1, uuidFactory.create()); + update.setString(2, componentUuid); + update.setString(3, linkType); + // provided type don't need anymore a name, the UI will display it by getting the i18 bundle of the link_type value + if (PROVIDED_TYPES.contains(linkType)) { + update.setString(4, null); + } else { + update.setString(4, name); + } + update.setString(5, href); + update.setLong(6, now); + update.setLong(7, now); + return true; + }); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinks.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinks.java new file mode 100644 index 00000000000..dd9f12c647d --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinks.java @@ -0,0 +1,56 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.platform.db.migration.version.v71; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder; +import org.sonar.server.platform.db.migration.sql.RenameTableBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE; +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; + +public class RenameTableProjectLinks2ToProjectLinks extends DdlChange { + + public RenameTableProjectLinks2ToProjectLinks(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + context.execute(new RenameTableBuilder(getDialect()) + .setName("project_links2") + .setNewName("project_links") + .setAutoGeneratedId(false) + .build()); + + context.execute(new CreateIndexBuilder(getDialect()) + .setTable("project_links") + .setName("project_links_project") + .addColumn(newVarcharColumnDefBuilder() + .setColumnName("project_uuid") + .setLimit(UUID_SIZE) + .setIsNullable(false) + .build()) + .build()); + } + +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilderTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilderTest.java index 1f32d803d9f..cfe6cffad87 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilderTest.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilderTest.java @@ -62,6 +62,11 @@ public class RenameTableBuilderTest { } @Test + public void rename_table_on_oracle_when_auto_generated_id_is_false() { + verifySqlWhenAutoGeneratedIdIsFalse(new Oracle(), "RENAME foo TO bar"); + } + + @Test public void rename_table_on_postgresql() { verifySql(new PostgreSql(), "ALTER TABLE foo RENAME TO bar"); } @@ -89,4 +94,13 @@ public class RenameTableBuilderTest { .build(); assertThat(actual).containsExactly(expectedSql); } + + private static void verifySqlWhenAutoGeneratedIdIsFalse(Dialect dialect, String... expectedSql) { + List<String> actual = new RenameTableBuilder(dialect) + .setName("foo") + .setNewName("bar") + .setAutoGeneratedId(false) + .build(); + assertThat(actual).containsExactly(expectedSql); + } } diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test.java new file mode 100644 index 00000000000..ff65f3fcf36 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test.java @@ -0,0 +1,66 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.platform.db.migration.version.v71; + +import java.sql.SQLException; +import java.sql.Types; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.db.CoreDbTester; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CreateTableProjectLinks2Test { + + private static final String TABLE_NAME = "project_links2"; + + @Rule + public final CoreDbTester dbTester = CoreDbTester.createForSchema(CreateTableProjectLinks2Test.class, "empty.sql"); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private CreateTableProjectLinks2 underTest = new CreateTableProjectLinks2(dbTester.database()); + + @Test + public void creates_table_on_empty_db() throws SQLException { + underTest.execute(); + + assertThat(dbTester.countRowsOfTable(TABLE_NAME)).isEqualTo(0); + + dbTester.assertColumnDefinition(TABLE_NAME, "uuid", Types.VARCHAR, 40, false); + dbTester.assertColumnDefinition(TABLE_NAME, "project_uuid", Types.VARCHAR, 40, false); + dbTester.assertColumnDefinition(TABLE_NAME, "link_type", Types.VARCHAR, 20, false); + dbTester.assertColumnDefinition(TABLE_NAME, "name", Types.VARCHAR, 128, true); + dbTester.assertColumnDefinition(TABLE_NAME, "href", Types.VARCHAR, 2048, false); + dbTester.assertColumnDefinition(TABLE_NAME, "created_at", Types.BIGINT, null, false); + dbTester.assertColumnDefinition(TABLE_NAME, "updated_at", Types.BIGINT, null, false); + } + + @Test + public void migration_is_not_reentrant() throws SQLException { + underTest.execute(); + + expectedException.expect(IllegalStateException.class); + + underTest.execute(); + } + +}
\ No newline at end of file diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71Test.java index 15fee0317ac..a93444604fd 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71Test.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71Test.java @@ -36,7 +36,7 @@ public class DbVersion71Test { @Test public void verify_migration_count() { - verifyMigrationCount(underTest, 8); + verifyMigrationCount(underTest, 13); } } diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest.java new file mode 100644 index 00000000000..09e78e36aa1 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest.java @@ -0,0 +1,54 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.platform.db.migration.version.v71; + +import java.sql.SQLException; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.db.CoreDbTester; + +public class DropTableProjectLinksTest { + + @Rule + public final CoreDbTester dbTester = CoreDbTester.createForSchema(DropTableProjectLinksTest.class, "project_links.sql"); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private DropTableProjectLinks underTest = new DropTableProjectLinks(dbTester.database()); + + @Test + public void creates_table_on_empty_db() throws SQLException { + underTest.execute(); + + dbTester.assertTableDoesNotExist("project_links"); + } + + @Test + public void migration_is_not_reentrant() throws SQLException { + underTest.execute(); + + expectedException.expect(IllegalStateException.class); + + underTest.execute(); + } + +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test.java new file mode 100644 index 00000000000..487d57fac52 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test.java @@ -0,0 +1,209 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.platform.db.migration.version.v71; + +import java.sql.SQLException; +import java.util.stream.Collectors; +import org.assertj.core.groups.Tuple; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.utils.System2; +import org.sonar.api.utils.internal.TestSystem2; +import org.sonar.core.util.SequenceUuidFactory; +import org.sonar.core.util.UuidFactory; +import org.sonar.db.CoreDbTester; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.groups.Tuple.tuple; + +public class PopulateTableProjectLinks2Test { + + private static final long PAST = 5_000_000_000L; + private static final long NOW = 10_000_000_000L; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Rule + public CoreDbTester db = CoreDbTester.createForSchema(PopulateTableProjectLinks2Test.class, "project_links2.sql"); + + private System2 system2 = new TestSystem2().setNow(NOW); + private UuidFactory uuidFactory = new SequenceUuidFactory(); + + private PopulateTableProjectLinks2 underTest = new PopulateTableProjectLinks2(db.database(), uuidFactory, system2); + + @Test + public void copy_custom_links() throws SQLException { + String project = insertProject(); + insertProjectLink("Name1", "custom1", "http://link1", project); + insertProjectLink("Name2", "custom2", "http://link2", project); + + underTest.execute(); + + assertProjectLinks2( + tuple("Name1", "custom1", "http://link1", project, NOW, NOW), + tuple("Name2", "custom2", "http://link2", project, NOW, NOW)); + } + + @Test + public void remove_name_of_provided_links() throws SQLException { + String project = insertProject(); + insertProjectLink("Home", "homepage", "http://homepage", project); + insertProjectLink("CI", "ci", "http://ci", project); + insertProjectLink("Jira", "issue", "http://issue", project); + insertProjectLink("SCM", "scm", "http://scm", project); + + underTest.execute(); + + assertProjectLinks2( + tuple(null, "homepage", "http://homepage", project, NOW, NOW), + tuple(null, "ci", "http://ci", project, NOW, NOW), + tuple(null, "issue", "http://issue", project, NOW, NOW), + tuple(null, "scm", "http://scm", project, NOW, NOW)); + } + + @Test + public void copy_links_from_different_projects() throws SQLException { + String project1 = insertProject(); + insertProjectLink("Name", "custom", "http://link1", project1); + String project2 = insertProject(); + insertProjectLink("Name", "custom", "http://link2", project2); + + underTest.execute(); + + assertProjectLinks2( + tuple("Name", "custom", "http://link1", project1, NOW, NOW), + tuple("Name", "custom", "http://link2", project2, NOW, NOW)); + } + + @Test + public void do_not_copy_links_from_developer_connection_link() throws SQLException { + insertProjectLink("Dev", "scm_dev", "http://link1", insertProject()); + + underTest.execute(); + + assertNoProjectLinks2(); + } + + @Test + public void do_not_copy_links_from_components_that_are_not_projects() throws SQLException { + insertProjectLink("Name", "custom", "http://link1", insertComponent("PRJ", "BRC")); + insertProjectLink("Name", "custom", "http://link2", insertComponent("PRJ", "VW")); + insertProjectLink("Name", "custom", "http://link1", insertComponent("DIR", "DIR")); + insertProjectLink("Name", "custom", "http://link1", "UNKNOWN"); + + underTest.execute(); + + assertNoProjectLinks2(); + } + + @Test + public void do_not_copy_already_copied_data() throws SQLException { + String project = insertProject(); + insertProjectLink("Name", "custom", "http://link", project); + insertProjectLink("Home", "homepage", "http://homepage", project); + insertProjectLink2("UUID1", "Name", "custom", "http://link", project, PAST); + insertProjectLink2("UUID2", null, "homepage", "http://homepage", project, PAST); + + underTest.execute(); + + assertThat(db.select("SELECT UUID, NAME, LINK_TYPE, HREF, PROJECT_UUID, CREATED_AT FROM PROJECT_LINKS2") + .stream() + .map(map -> new Tuple(map.get("UUID"), map.get("NAME"), map.get("LINK_TYPE"), map.get("HREF"), map.get("PROJECT_UUID"), map.get("CREATED_AT"))) + .collect(Collectors.toList())) + .containsExactlyInAnyOrder( + tuple("UUID1", "Name", "custom", "http://link", project, PAST), + tuple("UUID2", null, "homepage", "http://homepage", project, PAST)); + } + + @Test + public void migration_is_reentrant() throws SQLException { + String project = insertProject(); + insertProjectLink("Name", "custom", "http://link", project); + + underTest.execute(); + underTest.execute(); + + assertProjectLinks2(tuple("Name", "custom", "http://link", project, NOW, NOW)); + } + + @Test + public void has_no_effect_if_table_is_empty() throws SQLException { + underTest.execute(); + + assertThat(db.countRowsOfTable("project_links2")).isZero(); + } + + private void assertNoProjectLinks2() { + assertProjectLinks2(); + } + + private void assertProjectLinks2(Tuple... expectedTuples) { + assertThat(db.select("SELECT NAME, LINK_TYPE, HREF, PROJECT_UUID, CREATED_AT, UPDATED_AT FROM PROJECT_LINKS2") + .stream() + .map(map -> new Tuple(map.get("NAME"), map.get("LINK_TYPE"), map.get("HREF"), map.get("PROJECT_UUID"), map.get("CREATED_AT"), map.get("UPDATED_AT"))) + .collect(Collectors.toList())) + .containsExactlyInAnyOrder(expectedTuples); + } + + private void insertProjectLink(String name, String linkType, String href, String componentUuid) { + db.executeInsert( + "PROJECT_LINKS", + "COMPONENT_UUID", componentUuid, + "NAME", name, + "LINK_TYPE", linkType, + "HREF", href); + } + + private void insertProjectLink2(String uuid, String name, String linkType, String href, String componentUuid, Long createdAt) { + db.executeInsert( + "PROJECT_LINKS2", + "UUID", uuid, + "PROJECT_UUID", componentUuid, + "NAME", name, + "LINK_TYPE", linkType, + "HREF", href, + "CREATED_AT", createdAt, + "UPDATED_AT", createdAt); + } + + private String insertProject() { + return insertComponent("PRJ", "TRK"); + } + + private String insertComponent(String scope, String qualifier) { + String uuid = uuidFactory.create(); + db.executeInsert("PROJECTS", + "ORGANIZATION_UUID", "O1", + "KEE", uuid, + "UUID", uuid, + "PROJECT_UUID", uuid, + "MAIN_BRANCH_PROJECT_UUID", uuid, + "UUID_PATH", ".", + "ROOT_UUID", uuid, + "PRIVATE", "true", + "QUALIFIER", qualifier, + "SCOPE", scope); + return uuid; + } + +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest.java new file mode 100644 index 00000000000..0440fc4e00d --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest.java @@ -0,0 +1,58 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.platform.db.migration.version.v71; + +import java.sql.SQLException; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.db.CoreDbTester; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RenameTableProjectLinks2ToProjectLinksTest { + + @Rule + public final CoreDbTester dbTester = CoreDbTester.createForSchema(RenameTableProjectLinks2ToProjectLinksTest.class, "project_links2.sql"); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private RenameTableProjectLinks2ToProjectLinks underTest = new RenameTableProjectLinks2ToProjectLinks(dbTester.database()); + + @Test + public void creates_table_on_empty_db() throws SQLException { + underTest.execute(); + + dbTester.assertTableDoesNotExist("project_links2"); + assertThat(dbTester.countRowsOfTable("project_links")).isZero(); + dbTester.assertIndex("project_links", "project_links_project", "project_uuid"); + } + + @Test + public void migration_is_not_reentrant() throws SQLException { + underTest.execute(); + + expectedException.expect(IllegalStateException.class); + + underTest.execute(); + } + +} diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test/empty.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test/empty.sql new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test/empty.sql diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest/project_links.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest/project_links.sql new file mode 100644 index 00000000000..9588643a463 --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest/project_links.sql @@ -0,0 +1,7 @@ +CREATE TABLE "PROJECT_LINKS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "COMPONENT_UUID" VARCHAR(50), + "LINK_TYPE" VARCHAR(20), + "NAME" VARCHAR(128), + "HREF" VARCHAR(2048) NOT NULL +); diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test/project_links2.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test/project_links2.sql new file mode 100644 index 00000000000..ef474cc6421 --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test/project_links2.sql @@ -0,0 +1,64 @@ +CREATE TABLE "PROJECT_LINKS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "COMPONENT_UUID" VARCHAR(50), + "LINK_TYPE" VARCHAR(20), + "NAME" VARCHAR(128), + "HREF" VARCHAR(2048) NOT NULL +); + +CREATE TABLE "PROJECT_LINKS2" ( + "UUID" VARCHAR(40) NOT NULL PRIMARY KEY, + "PROJECT_UUID" VARCHAR(50) NOT NULL, + "LINK_TYPE" VARCHAR(20) NOT NULL, + "NAME" VARCHAR(128), + "HREF" VARCHAR(2048) NOT NULL, + "CREATED_AT" BIGINT NOT NULL, + "UPDATED_AT" BIGINT NOT NULL +); + +CREATE TABLE "PROJECTS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "ORGANIZATION_UUID" VARCHAR(40) NOT NULL, + "KEE" VARCHAR(400), + "UUID" VARCHAR(50) NOT NULL, + "UUID_PATH" VARCHAR(1500) NOT NULL, + "ROOT_UUID" VARCHAR(50) NOT NULL, + "PROJECT_UUID" VARCHAR(50) NOT NULL, + "MODULE_UUID" VARCHAR(50), + "MODULE_UUID_PATH" VARCHAR(1500), + "MAIN_BRANCH_PROJECT_UUID" VARCHAR(50), + "NAME" VARCHAR(2000), + "DESCRIPTION" VARCHAR(2000), + "PRIVATE" BOOLEAN NOT NULL, + "TAGS" VARCHAR(500), + "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE, + "SCOPE" VARCHAR(3), + "QUALIFIER" VARCHAR(10), + "DEPRECATED_KEE" VARCHAR(400), + "PATH" VARCHAR(2000), + "LANGUAGE" VARCHAR(20), + "COPY_COMPONENT_UUID" VARCHAR(50), + "LONG_NAME" VARCHAR(2000), + "DEVELOPER_UUID" VARCHAR(50), + "CREATED_AT" TIMESTAMP, + "AUTHORIZATION_UPDATED_AT" BIGINT, + "B_CHANGED" BOOLEAN, + "B_COPY_COMPONENT_UUID" VARCHAR(50), + "B_DESCRIPTION" VARCHAR(2000), + "B_ENABLED" BOOLEAN, + "B_UUID_PATH" VARCHAR(1500), + "B_LANGUAGE" VARCHAR(20), + "B_LONG_NAME" VARCHAR(500), + "B_MODULE_UUID" VARCHAR(50), + "B_MODULE_UUID_PATH" VARCHAR(1500), + "B_NAME" VARCHAR(500), + "B_PATH" VARCHAR(2000), + "B_QUALIFIER" VARCHAR(10) +); +CREATE INDEX "PROJECTS_ORGANIZATION" ON "PROJECTS" ("ORGANIZATION_UUID"); +CREATE UNIQUE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE"); +CREATE INDEX "PROJECTS_ROOT_UUID" ON "PROJECTS" ("ROOT_UUID"); +CREATE UNIQUE INDEX "PROJECTS_UUID" ON "PROJECTS" ("UUID"); +CREATE INDEX "PROJECTS_PROJECT_UUID" ON "PROJECTS" ("PROJECT_UUID"); +CREATE INDEX "PROJECTS_MODULE_UUID" ON "PROJECTS" ("MODULE_UUID"); +CREATE INDEX "PROJECTS_QUALIFIER" ON "PROJECTS" ("QUALIFIER");
\ No newline at end of file diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest/project_links2.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest/project_links2.sql new file mode 100644 index 00000000000..c29900dbd64 --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest/project_links2.sql @@ -0,0 +1,9 @@ +CREATE TABLE "PROJECT_LINKS2" ( + "UUID" VARCHAR(40) NOT NULL PRIMARY KEY, + "PROJECT_UUID" VARCHAR(50) NOT NULL, + "LINK_TYPE" VARCHAR(20) NOT NULL, + "NAME" VARCHAR(128), + "HREF" VARCHAR(2048) NOT NULL, + "CREATED_AT" BIGINT NOT NULL, + "UPDATED_AT" BIGINT NOT NULL +); |