aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-db-migration
diff options
context:
space:
mode:
authorEric Hartmann <hartmann.eric@gmail.com>2017-06-14 13:24:39 +0200
committerEric Hartmann <hartmann.eric@gmail.com>2017-06-14 15:43:13 +0200
commit764185d9211229e5dcafe885cfdcbfbfadf54ce7 (patch)
tree719e8e2046ccdacaedc5e6c14d949d01792915a7 /server/sonar-db-migration
parentbce59a878501872b105e120bc0d8e13494f79aee (diff)
downloadsonarqube-764185d9211229e5dcafe885cfdcbfbfadf54ce7.tar.gz
sonarqube-764185d9211229e5dcafe885cfdcbfbfadf54ce7.zip
SONAR-9427 Improve performance on quality profile changelog
Diffstat (limited to 'server/sonar-db-migration')
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/def/TinyIntColumnDef.java2
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/def/Validations.java3
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/AlterColumnsBuilder.java2
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/RenameColumnsBuilder.java132
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v65/AddIndexRulesProfileUuidOnQProfileChangesIsIndexed.java54
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v65/DbVersion65.java4
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v65/RenameQProfileKeyToRulesProfileUuidOnQProfileChanges.java51
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/sql/RenameColumnsBuilderTest.java167
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/AddIndexRulesProfileUuidOnQProfileChangesIsIndexedTest.java44
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/DbVersion65Test.java2
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/RenameQProfileKeyToRulesProfileUuidOnQProfileChangesTest.java45
-rw-r--r--server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v65/AddIndexRulesProfileUuidOnQProfileChangesIsIndexedTest/initial.sql9
-rw-r--r--server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v65/RenameQProfileKeyToRulesProfileUuidOnQProfileChangesTest/initial.sql9
13 files changed, 519 insertions, 5 deletions
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/def/TinyIntColumnDef.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/def/TinyIntColumnDef.java
index 1df802ceed9..37311afd3b5 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/def/TinyIntColumnDef.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/def/TinyIntColumnDef.java
@@ -40,6 +40,8 @@ public class TinyIntColumnDef extends AbstractColumnDef {
super(builder.columnName, builder.isNullable, null);
}
+ public static Builder newTinyIntColumnDefBuilder() { return new Builder(); }
+
@Override
public String generateSqlType(Dialect dialect) {
switch (dialect.getId()) {
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/def/Validations.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/def/Validations.java
index 97580c115fc..d0a05ae05c8 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/def/Validations.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/def/Validations.java
@@ -49,7 +49,7 @@ public class Validations {
* @return the same {@code columnName}
* @see #checkDbIdentifier(String, String, int)
*/
- static String validateColumnName(@Nullable String columnName) {
+ public static String validateColumnName(@Nullable String columnName) {
String name = requireNonNull(columnName, "Column name cannot be null");
checkDbIdentifierCharacters(columnName, "Column name");
return name;
@@ -115,6 +115,7 @@ public class Validations {
}
private static void checkDbIdentifierCharacters(String identifier, String identifierDesc) {
+ checkArgument(identifier != null && identifier.length() > 0, "Identifier must not be empty");
checkArgument(
LOWER_CASE_ASCII_LETTERS_CHAR_MATCHER.or(DIGIT_CHAR_MATCHER).or(anyOf("_")).matchesAllOf(identifier),
"%s must be lower case and contain only alphanumeric chars or '_', got '%s'", identifierDesc, identifier);
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/AlterColumnsBuilder.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/AlterColumnsBuilder.java
index 3471389aad6..d2d529fc8b6 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/AlterColumnsBuilder.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/AlterColumnsBuilder.java
@@ -142,7 +142,5 @@ public class AlterColumnsBuilder {
if (addNotNullableProperty) {
sql.append(columnDef.isNullable() ? " NULL" : " NOT NULL");
}
-
}
-
}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/RenameColumnsBuilder.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/RenameColumnsBuilder.java
new file mode 100644
index 00000000000..19fb80d7212
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/RenameColumnsBuilder.java
@@ -0,0 +1,132 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.sql;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.CheckForNull;
+import org.sonar.db.dialect.Dialect;
+import org.sonar.db.dialect.H2;
+import org.sonar.db.dialect.MsSql;
+import org.sonar.db.dialect.MySql;
+import org.sonar.db.dialect.Oracle;
+import org.sonar.db.dialect.PostgreSql;
+import org.sonar.server.platform.db.migration.def.ColumnDef;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.sonar.server.platform.db.migration.def.Validations.validateColumnName;
+import static org.sonar.server.platform.db.migration.def.Validations.validateTableName;
+
+/**
+ * This builder have the main goal to change the name column.
+ *
+ * For MySQL the column definition is mandatory, however the change of column
+ * is not supported on this class.
+ * In case of renaming and changing a column, this must be done in two separate steps,
+ * first rename the column then update the types of this column with @see {@link AlterColumnsBuilder}
+ */
+public class RenameColumnsBuilder {
+
+ private final Dialect dialect;
+ private final String tableName;
+ private final List<Renaming> renamings = new ArrayList();
+
+ public RenameColumnsBuilder(Dialect dialect, String tableName) {
+ this.dialect = dialect;
+ this.tableName = tableName;
+ }
+
+ public RenameColumnsBuilder renameColumn(String oldColumnName, ColumnDef columnDef) {
+ renamings.add(new Renaming(oldColumnName, columnDef));
+ return this;
+ }
+
+ public List<String> build() {
+ validateTableName(tableName);
+ renamings.stream().forEach(
+ r -> {
+ validateColumnName(r.getOldColumnName());
+ validateColumnName(r.getNewColumnName());
+ checkArgument(!r.getNewColumnName().equals(r.getOldColumnName()), "Column names must be different");
+ }
+ );
+ return createSqlStatement();
+ }
+
+ private List<String> createSqlStatement() {
+ return renamings.stream().map(
+ r -> {
+ switch (dialect.getId()) {
+ case H2.ID:
+ return "ALTER TABLE " + tableName + " ALTER COLUMN " + r.getOldColumnName() + " RENAME TO " + r.getNewColumnName();
+ case Oracle.ID:
+ case PostgreSql.ID:
+ return "ALTER TABLE " + tableName + " RENAME COLUMN " + r.getOldColumnName() + " TO " + r.getNewColumnName();
+ case MySql.ID:
+ return "ALTER TABLE " + tableName + " CHANGE " + r.getOldColumnName() + " " + r.getNewColumnName() + " " + r.generateSqlType(dialect);
+ case MsSql.ID:
+ return "EXEC sp_rename '" + tableName + "." + r.getOldColumnName() + "', '" + r.getNewColumnName() + "', 'COLUMN'";
+ default:
+ throw new IllegalArgumentException("Unsupported dialect id " + dialect.getId());
+ }
+ }
+ ).collect(Collectors.toList());
+ }
+
+ private class Renaming implements ColumnDef {
+ private final ColumnDef columnDef;
+ private final String oldColumnName;
+
+ private Renaming(String oldColumnName, ColumnDef columnDef) {
+ this.columnDef = columnDef;
+ this.oldColumnName = oldColumnName;
+ }
+
+ public String getOldColumnName() {
+ return oldColumnName;
+ }
+
+ public String getNewColumnName() {
+ return columnDef.getName();
+ }
+
+ @Override
+ public boolean isNullable() {
+ return columnDef.isNullable();
+ }
+
+ @Override
+ public String getName() {
+ return columnDef.getName();
+ }
+
+ @Override
+ public String generateSqlType(Dialect dialect) {
+ return columnDef.generateSqlType(dialect);
+ }
+
+ @CheckForNull
+ @Override
+ public Object getDefaultValue() {
+ return columnDef.getDefaultValue();
+ }
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v65/AddIndexRulesProfileUuidOnQProfileChangesIsIndexed.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v65/AddIndexRulesProfileUuidOnQProfileChangesIsIndexed.java
new file mode 100644
index 00000000000..cd7ebee4ec9
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v65/AddIndexRulesProfileUuidOnQProfileChangesIsIndexed.java
@@ -0,0 +1,54 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.v65;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class AddIndexRulesProfileUuidOnQProfileChangesIsIndexed extends DdlChange {
+
+ private static final String TABLE_NAME = "qprofile_changes";
+ private static final String COLUMN_NAME = "rules_profile_uuid";
+ private static final String NEW_INDEX_NAME = "qp_changes_rules_profile_uuid";
+
+ public AddIndexRulesProfileUuidOnQProfileChangesIsIndexed(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ VarcharColumnDef rulesProfileUuid = VarcharColumnDef.newVarcharColumnDefBuilder()
+ .setColumnName(COLUMN_NAME)
+ .setLimit(255)
+ .setIsNullable(false)
+ .build();
+
+ context.execute(new CreateIndexBuilder(getDialect())
+ .setName(NEW_INDEX_NAME)
+ .setTable(TABLE_NAME)
+ .addColumn(rulesProfileUuid)
+ .build()
+ );
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v65/DbVersion65.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v65/DbVersion65.java
index b8647194efd..67b0d8fbf43 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v65/DbVersion65.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v65/DbVersion65.java
@@ -52,6 +52,8 @@ public class DbVersion65 implements DbVersion {
.add(1723, "Populate table qprofiles", PopulateOrgQProfiles.class)
.add(1724, "Drop columns organization_uuid and parent_kee from rules_profiles", DropOrgColumnsFromRulesProfiles.class)
.add(1725, "Mark rules_profiles.is_built_in to true for default organization", SetRulesProfilesIsBuiltInToTrueForDefaultOrganization.class)
- .add(1726, "Update OrgQProfiles to point to built-in profiles", UpdateOrgQProfilesToPointToBuiltInProfiles.class);
+ .add(1726, "Update OrgQProfiles to point to built-in profiles", UpdateOrgQProfilesToPointToBuiltInProfiles.class)
+ .add(1727, "Rename column qprofile_changes.qprofile_key to qprofile_changes.rules_profile_uuid", RenameQProfileKeyToRulesProfileUuidOnQProfileChanges.class)
+ .add(1728, "Ensure presence of index on qprofile_changes.rules_profile_uuid", AddIndexRulesProfileUuidOnQProfileChangesIsIndexed.class);
}
}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v65/RenameQProfileKeyToRulesProfileUuidOnQProfileChanges.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v65/RenameQProfileKeyToRulesProfileUuidOnQProfileChanges.java
new file mode 100644
index 00000000000..749abd1ee66
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v65/RenameQProfileKeyToRulesProfileUuidOnQProfileChanges.java
@@ -0,0 +1,51 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.v65;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.RenameColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class RenameQProfileKeyToRulesProfileUuidOnQProfileChanges extends DdlChange {
+
+ private static final String TABLE_NAME = "qprofile_changes";
+ private static final String OLD_COLUMN = "qprofile_key";
+ private static final String NEW_COLUMN = "rules_profile_uuid";
+
+ public RenameQProfileKeyToRulesProfileUuidOnQProfileChanges(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ VarcharColumnDef newColumn = VarcharColumnDef.newVarcharColumnDefBuilder()
+ .setColumnName(NEW_COLUMN)
+ .setLimit(255)
+ .setIsNullable(false)
+ .build();
+
+ context.execute(
+ new RenameColumnsBuilder(getDialect(), TABLE_NAME)
+ .renameColumn(OLD_COLUMN, newColumn)
+ .build());
+ }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/sql/RenameColumnsBuilderTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/sql/RenameColumnsBuilderTest.java
new file mode 100644
index 00000000000..73cf94cbd1f
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/sql/RenameColumnsBuilderTest.java
@@ -0,0 +1,167 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.sql;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang.text.StrSubstitutor;
+import org.junit.Rule;
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.FromDataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.sonar.db.dialect.Dialect;
+import org.sonar.db.dialect.H2;
+import org.sonar.db.dialect.MsSql;
+import org.sonar.db.dialect.MySql;
+import org.sonar.db.dialect.Oracle;
+import org.sonar.db.dialect.PostgreSql;
+import org.sonar.server.platform.db.migration.def.BigIntegerColumnDef;
+import org.sonar.server.platform.db.migration.def.BlobColumnDef;
+import org.sonar.server.platform.db.migration.def.BooleanColumnDef;
+import org.sonar.server.platform.db.migration.def.ClobColumnDef;
+import org.sonar.server.platform.db.migration.def.ColumnDef;
+import org.sonar.server.platform.db.migration.def.DecimalColumnDef;
+import org.sonar.server.platform.db.migration.def.IntegerColumnDef;
+import org.sonar.server.platform.db.migration.def.TinyIntColumnDef;
+import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
+
+import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(Theories.class)
+public class RenameColumnsBuilderTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private static final String NEW_COLUMN_NAME = "new_" + randomAlphabetic(6).toLowerCase();
+
+ @DataPoints("database")
+ public static final DatabaseAndResult[] DATABASES = {
+ new DatabaseAndResult(new H2(), "ALTER TABLE ${table_name} ALTER COLUMN ${old_column_name} RENAME TO ${new_column_name}"),
+ new DatabaseAndResult(new PostgreSql(), "ALTER TABLE ${table_name} RENAME COLUMN ${old_column_name} TO ${new_column_name}"),
+ new DatabaseAndResult(new MySql(), "ALTER TABLE ${table_name} CHANGE ${old_column_name} ${new_column_name} ${column_def}"),
+ new DatabaseAndResult(new MsSql(), "EXEC sp_rename '${table_name}.${old_column_name}', '${new_column_name}', 'COLUMN'"),
+ new DatabaseAndResult(new Oracle(), "ALTER TABLE ${table_name} RENAME COLUMN ${old_column_name} TO ${new_column_name}")
+ };
+
+ @DataPoints("columnDef")
+ public static final ColumnDef[] COLUMN_DEFS = {
+ BigIntegerColumnDef.newBigIntegerColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(false).build(),
+ BigIntegerColumnDef.newBigIntegerColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(true).build(),
+ BlobColumnDef.newBlobColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(false).build(),
+ BlobColumnDef.newBlobColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(true).build(),
+ BooleanColumnDef.newBooleanColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(false).build(),
+ BooleanColumnDef.newBooleanColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(true).build(),
+ ClobColumnDef.newClobColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(false).build(),
+ ClobColumnDef.newClobColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(true).build(),
+ DecimalColumnDef.newDecimalColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(false).build(),
+ DecimalColumnDef.newDecimalColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(true).build(),
+ IntegerColumnDef.newIntegerColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(false).build(),
+ IntegerColumnDef.newIntegerColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(true).build(),
+ TinyIntColumnDef.newTinyIntColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(false).build(),
+ TinyIntColumnDef.newTinyIntColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(true).build(),
+ VarcharColumnDef.newVarcharColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(false).setLimit(10).build(),
+ VarcharColumnDef.newVarcharColumnDefBuilder().setColumnName(NEW_COLUMN_NAME).setIsNullable(true).setLimit(10).build(),
+ };
+
+ @DataPoints("illegalColumnName")
+ public static final String[] ILLEGAL_COLUMN_NAME = {
+ "",
+ "AA",
+ "A.A",
+ "_A",
+ "1A",
+ "\uD801\uDC8B\uD801\uDC8C\uD801\uDC8D"
+ };
+
+ @Theory
+ public void checkSQL_results(
+ @FromDataPoints("database") DatabaseAndResult database,
+ @FromDataPoints("columnDef") ColumnDef columnDef) {
+
+ String oldColumnName = "old_" + randomAlphabetic(6).toLowerCase();
+ String tableName = "table_" + randomAlphabetic(6).toLowerCase();
+
+ List<String> result = new RenameColumnsBuilder(database.getDialect(), tableName)
+ .renameColumn(oldColumnName, columnDef)
+ .build();
+
+ Map<String, String> parameters = new HashMap<>();
+ parameters.put("table_name", tableName);
+ parameters.put("old_column_name", oldColumnName);
+ parameters.put("new_column_name", NEW_COLUMN_NAME);
+ parameters.put("column_def", columnDef.generateSqlType(database.getDialect()));
+ String expectedResult = StrSubstitutor.replace(database.getTemplateSql(), parameters);
+ assertThat(result).containsExactlyInAnyOrder(expectedResult);
+ }
+
+ @Theory
+ public void when_old_column_is_same_as_new_column_ISA_is_thrown (
+ @FromDataPoints("database") DatabaseAndResult database,
+ @FromDataPoints("columnDef") ColumnDef columnDef) {
+
+ String tableName = "table_" + randomAlphabetic(6).toLowerCase();
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Column names must be different");
+
+ new RenameColumnsBuilder(database.getDialect(), tableName)
+ .renameColumn(NEW_COLUMN_NAME, columnDef)
+ .build();
+ }
+
+ @Theory
+ public void when_new_column_contains_illegal_character_ISA_is_thrown (
+ @FromDataPoints("database") DatabaseAndResult database,
+ @FromDataPoints("columnDef") ColumnDef columnDef,
+ @FromDataPoints("illegalColumnName") String illegalColumnName) {
+
+ String tableName = "table_" + randomAlphabetic(6).toLowerCase();
+
+ expectedException.expect(IllegalArgumentException.class);
+
+ new RenameColumnsBuilder(database.getDialect(), tableName)
+ .renameColumn(illegalColumnName, columnDef)
+ .build();
+ }
+
+ private static class DatabaseAndResult {
+ private final Dialect dialect;
+ private final String templateSql;
+
+ private DatabaseAndResult(Dialect dialect, String templateSql) {
+ this.dialect = dialect;
+ this.templateSql = templateSql;
+ }
+
+ public Dialect getDialect() {
+ return dialect;
+ }
+
+ public String getTemplateSql() {
+ return templateSql;
+ }
+ }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/AddIndexRulesProfileUuidOnQProfileChangesIsIndexedTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/AddIndexRulesProfileUuidOnQProfileChangesIsIndexedTest.java
new file mode 100644
index 00000000000..818b4c74680
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/AddIndexRulesProfileUuidOnQProfileChangesIsIndexedTest.java
@@ -0,0 +1,44 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.v65;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+
+public class AddIndexRulesProfileUuidOnQProfileChangesIsIndexedTest {
+
+ private static final String TABLE_NAME = "qprofile_changes";
+ private static final String COLUMN_NAME = "rules_profile_uuid";
+ private static final String INDEX_NAME = "qp_changes_rules_profile_uuid";
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(AddIndexRulesProfileUuidOnQProfileChangesIsIndexedTest.class, "initial.sql");
+
+ private AddIndexRulesProfileUuidOnQProfileChangesIsIndexed underTest = new AddIndexRulesProfileUuidOnQProfileChangesIsIndexed(db.database());
+
+ @Test
+ public void add_index_ON_RULES_PROFILE_UUID_of_QPROFILE_CHANGES() throws SQLException {
+ underTest.execute();
+
+ db.assertIndex(TABLE_NAME, INDEX_NAME,COLUMN_NAME);
+ }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/DbVersion65Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/DbVersion65Test.java
index 551158fabc0..008357b2f8d 100644
--- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/DbVersion65Test.java
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/DbVersion65Test.java
@@ -35,6 +35,6 @@ public class DbVersion65Test {
@Test
public void verify_migration_count() {
- verifyMigrationCount(underTest, 27);
+ verifyMigrationCount(underTest, 29);
}
}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/RenameQProfileKeyToRulesProfileUuidOnQProfileChangesTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/RenameQProfileKeyToRulesProfileUuidOnQProfileChangesTest.java
new file mode 100644
index 00000000000..c71856c7bdd
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/RenameQProfileKeyToRulesProfileUuidOnQProfileChangesTest.java
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.v65;
+
+import java.sql.Types;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+
+public class RenameQProfileKeyToRulesProfileUuidOnQProfileChangesTest {
+
+ private static final String TABLE_NAME = "qprofile_changes";
+ private static final String OLD_COLUMN_NAME = "qprofile_key";
+ private static final String NEW_COLUMN_NAME = "rules_profile_uuid";
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(RenameQProfileKeyToRulesProfileUuidOnQProfileChangesTest.class, "initial.sql");
+
+ private RenameQProfileKeyToRulesProfileUuidOnQProfileChanges underTest = new RenameQProfileKeyToRulesProfileUuidOnQProfileChanges(db.database());
+
+ @Test
+ public void change_column_name_from_QPROFILE_KEY_to_RULES_PROFILE_UUID() throws Exception {
+ db.assertColumnDefinition(TABLE_NAME, OLD_COLUMN_NAME, Types.VARCHAR, 255);
+ underTest.execute();
+ db.assertColumnDefinition(TABLE_NAME, NEW_COLUMN_NAME, Types.VARCHAR, 255);
+ db.assertColumnDoesNotExist(TABLE_NAME, OLD_COLUMN_NAME);
+ }
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v65/AddIndexRulesProfileUuidOnQProfileChangesIsIndexedTest/initial.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v65/AddIndexRulesProfileUuidOnQProfileChangesIsIndexedTest/initial.sql
new file mode 100644
index 00000000000..43d3ab5c3c1
--- /dev/null
+++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v65/AddIndexRulesProfileUuidOnQProfileChangesIsIndexedTest/initial.sql
@@ -0,0 +1,9 @@
+CREATE TABLE "QPROFILE_CHANGES" (
+ "KEE" VARCHAR(40) NOT NULL PRIMARY KEY,
+ "RULES_PROFILE_UUID" VARCHAR(255) NOT NULL,
+ "CHANGE_TYPE" VARCHAR(20) NOT NULL,
+ "CREATED_AT" BIGINT NOT NULL,
+ "USER_LOGIN" VARCHAR(255),
+ "CHANGE_DATA" CLOB
+);
+CREATE INDEX "QPROFILE_CHANGES_QPROFILE_KEY" ON "QPROFILE_CHANGES" ("RULES_PROFILE_UUID");
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v65/RenameQProfileKeyToRulesProfileUuidOnQProfileChangesTest/initial.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v65/RenameQProfileKeyToRulesProfileUuidOnQProfileChangesTest/initial.sql
new file mode 100644
index 00000000000..cb28a6fccd1
--- /dev/null
+++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v65/RenameQProfileKeyToRulesProfileUuidOnQProfileChangesTest/initial.sql
@@ -0,0 +1,9 @@
+CREATE TABLE "QPROFILE_CHANGES" (
+ "KEE" VARCHAR(40) NOT NULL PRIMARY KEY,
+ "QPROFILE_KEY" VARCHAR(255) NOT NULL,
+ "CHANGE_TYPE" VARCHAR(20) NOT NULL,
+ "CREATED_AT" BIGINT NOT NULL,
+ "USER_LOGIN" VARCHAR(255),
+ "CHANGE_DATA" CLOB
+);
+CREATE INDEX "QPROFILE_CHANGES_QPROFILE_KEY" ON "QPROFILE_CHANGES" ("QPROFILE_KEY");