--- /dev/null
+/*
+ * 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;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Preconditions;
+import org.sonar.core.persistence.dialect.Dialect;
+import org.sonar.core.persistence.dialect.MsSql;
+import org.sonar.core.persistence.dialect.Oracle;
+import org.sonar.core.persistence.dialect.PostgreSql;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+public class AddColumnsBuilder {
+
+ private final Dialect dialect;
+ private final String tableName;
+ private List<ColumnDef> columnDefs = newArrayList();
+
+ public AddColumnsBuilder(Dialect dialect, String tableName) {
+ this.tableName = tableName;
+ this.dialect = dialect;
+ }
+
+ public AddColumnsBuilder addColumn(ColumnDef columnDef) {
+ columnDefs.add(columnDef);
+ return this;
+ }
+
+ public String build() {
+ StringBuilder sql = new StringBuilder().append("ALTER TABLE ").append(tableName).append(" ");
+ switch (dialect.getId()) {
+ case PostgreSql.ID:
+ addColumns(sql, "ADD COLUMN ");
+ break;
+ case MsSql.ID:
+ sql.append("ADD ");
+ addColumns(sql, "");
+ break;
+ default:
+ sql.append("ADD (");
+ addColumns(sql, "");
+ sql.append(")");
+ }
+ return sql.toString();
+ }
+
+ private void addColumns(StringBuilder sql, String columnPrefix) {
+ for (int i = 0; i < columnDefs.size(); i++) {
+ sql.append(columnPrefix);
+ addColumn(sql, columnDefs.get(i));
+ if (i < columnDefs.size() - 1) {
+ sql.append(", ");
+ }
+ }
+ }
+
+ private void addColumn(StringBuilder sql, ColumnDef columnDef) {
+ sql.append(columnDef.getName()).append(" ").append(typeToSql(columnDef));
+ Integer limit = columnDef.getLimit();
+ if (limit != null) {
+ sql.append(" (").append(Integer.toString(limit)).append(")");
+ }
+ sql.append(columnDef.isNullable() ? " NULL" : " NOT NULL");
+ }
+
+ private String typeToSql(ColumnDef columnDef) {
+ switch (columnDef.getType()) {
+ case STRING:
+ return "VARCHAR";
+ case BIG_INTEGER:
+ if (dialect.getId().equals(Oracle.ID)) {
+ return "NUMBER (38)";
+ } else {
+ return "BIGINT";
+ }
+ default:
+ throw new IllegalArgumentException("Unsupported type : " + columnDef.getType());
+ }
+ }
+
+ public static class ColumnDef {
+ private String name;
+ private Type type;
+ private boolean isNullable;
+ private Integer limit;
+
+ public enum Type {
+ STRING, BIG_INTEGER
+ }
+
+ public ColumnDef setNullable(boolean isNullable) {
+ this.isNullable = isNullable;
+ return this;
+ }
+
+ public ColumnDef setLimit(@Nullable Integer limit) {
+ this.limit = limit;
+ return this;
+ }
+
+ public ColumnDef setName(String name) {
+ Preconditions.checkArgument(CharMatcher.JAVA_LOWER_CASE.or(CharMatcher.anyOf("_")).matchesAllOf(name), "Column name should only contains lowercase and _ characters");
+ this.name = name;
+ return this;
+ }
+
+ public ColumnDef setType(Type type) {
+ this.type = type;
+ return this;
+ }
+
+ public boolean isNullable() {
+ return isNullable;
+ }
+
+ @CheckForNull
+ public Integer getLimit() {
+ return limit;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Type getType() {
+ return type;
+ }
+ }
+}
FeedManualMeasuresLongDates.class,
FeedEventsLongDates.class,
AddNewCharacteristics.class,
- RemovePermissionsOnModulesMigration.class
+ RemovePermissionsOnModulesMigration.class,
+ AddIssuesColumns.class,
+ DropIssuesColumns.class
);
}
--- /dev/null
+/*
+ * 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;
+
+import org.apache.commons.dbutils.DbUtils;
+import org.sonar.core.persistence.Database;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+public abstract class DdlChange implements DatabaseMigration {
+
+ private final Database db;
+
+ public DdlChange(Database db) {
+ this.db = db;
+ }
+
+ @Override
+ public final void execute() throws SQLException {
+ Connection writeConnection = null;
+ try {
+ writeConnection = db.getDataSource().getConnection();
+ writeConnection.setAutoCommit(false);
+ Context context = new Context(writeConnection);
+ execute(context);
+
+ } finally {
+ DbUtils.closeQuietly(writeConnection);
+ }
+ }
+
+ public class Context {
+ private final Connection writeConnection;
+
+ public Context(Connection writeConnection) {
+ this.writeConnection = writeConnection;
+ }
+
+ public void execute(String sql) throws SQLException {
+ try {
+ UpsertImpl.create(writeConnection, sql).execute().commit();
+ } catch (Exception e) {
+ throw new IllegalStateException(String.format("Fail to execute %s", sql), e);
+ }
+ }
+ }
+
+ public abstract void execute(Context context) throws SQLException;
+
+}
--- /dev/null
+/*
+ * 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;
+
+import org.sonar.core.persistence.dialect.*;
+
+public class DropColumnsBuilder {
+
+ private final Dialect dialect;
+ private final String tableName;
+ private final String[] columns;
+
+ public DropColumnsBuilder(Dialect dialect, String tableName, String... columns) {
+ this.tableName = tableName;
+ this.dialect = dialect;
+ this.columns = columns;
+ }
+
+ public String build() {
+ StringBuilder sql = new StringBuilder().append("ALTER TABLE ").append(tableName).append(" ");
+ switch (dialect.getId()) {
+ case PostgreSql.ID:
+ case MySql.ID:
+ dropColumns(sql, "DROP COLUMN ");
+ break;
+ case MsSql.ID:
+ sql.append("DROP COLUMN ");
+ dropColumns(sql, "");
+ break;
+ case Oracle.ID:
+ sql.append("DROP (");
+ dropColumns(sql, "");
+ sql.append(")");
+ break;
+ default:
+ throw new IllegalStateException(String.format("Unsupported database '%s'", dialect.getId()));
+ }
+ return sql.toString();
+ }
+
+ private void dropColumns(StringBuilder sql, String columnPrefix) {
+ for (int i = 0; i < columns.length; i++) {
+ sql.append(columnPrefix);
+ sql.append(columns[i]);
+ if (i < columns.length - 1) {
+ sql.append(", ");
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.v51;
+
+import org.sonar.core.persistence.Database;
+import org.sonar.server.db.migrations.AddColumnsBuilder;
+import org.sonar.server.db.migrations.DdlChange;
+
+import java.sql.SQLException;
+
+/**
+ * Add the following columns to the issues table :
+ * - issue_creation_date_ms
+ * - issue_update_date_ms
+ * - issue_close_date_ms
+ * - tags
+ * - component_uuid
+ * - project_uuid
+ */
+public class AddIssuesColumns extends DdlChange {
+
+ private final Database db;
+
+ public AddIssuesColumns(Database db) {
+ super(db);
+ this.db = db;
+ }
+
+ @Override
+ public void execute(DdlChange.Context context) throws SQLException {
+ context.execute(generateSql());
+ }
+
+ private String generateSql() {
+ return new AddColumnsBuilder(db.getDialect(), "issues")
+ .addColumn(
+ new AddColumnsBuilder.ColumnDef()
+ .setName("issue_creation_date_ms")
+ .setType(AddColumnsBuilder.ColumnDef.Type.BIG_INTEGER)
+ .setNullable(true)
+ )
+ .addColumn(
+ new AddColumnsBuilder.ColumnDef()
+ .setName("issue_update_date_ms")
+ .setType(AddColumnsBuilder.ColumnDef.Type.BIG_INTEGER)
+ .setNullable(true)
+ )
+ .addColumn(
+ new AddColumnsBuilder.ColumnDef()
+ .setName("issue_close_date_ms")
+ .setType(AddColumnsBuilder.ColumnDef.Type.BIG_INTEGER)
+ .setNullable(true)
+ )
+ .addColumn(
+ new AddColumnsBuilder.ColumnDef()
+ .setName("tags")
+ .setType(AddColumnsBuilder.ColumnDef.Type.STRING)
+ .setLimit(4000)
+ .setNullable(true))
+ .addColumn(
+ new AddColumnsBuilder.ColumnDef()
+ .setName("component_uuid")
+ .setType(AddColumnsBuilder.ColumnDef.Type.STRING)
+ .setLimit(50)
+ .setNullable(true))
+ .addColumn(
+ new AddColumnsBuilder.ColumnDef()
+ .setName("project_uuid")
+ .setType(AddColumnsBuilder.ColumnDef.Type.STRING)
+ .setLimit(50)
+ .setNullable(true))
+ .build();
+ }
+
+}
--- /dev/null
+/*
+ * 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.v51;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.sonar.core.persistence.Database;
+import org.sonar.server.db.migrations.DdlChange;
+import org.sonar.server.db.migrations.DropColumnsBuilder;
+
+import java.sql.SQLException;
+
+/**
+ * Drop the following columns from the issues table :
+ * - issue_creation_date
+ * - issue_update_date
+ * - issue_close_date
+ * - component_id
+ * - root_component_id
+ */
+public class DropIssuesColumns extends DdlChange {
+
+ private final Database db;
+
+ public DropIssuesColumns(Database db) {
+ super(db);
+ this.db = db;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(generateSql());
+ }
+
+ @VisibleForTesting
+ String generateSql() {
+ return new DropColumnsBuilder(db.getDialect(), "issues",
+ "issue_creation_date", "issue_update_date", "issue_close_date", "component_id", "root_component_id")
+ .build();
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+
+import org.junit.Test;
+import org.sonar.core.persistence.dialect.*;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
+
+public class AddColumnsBuilderTest {
+
+ @Test
+ public void add_columns_on_h2() throws Exception {
+ assertThat(new AddColumnsBuilder(new H2(), "issues")
+ .addColumn(new AddColumnsBuilder.ColumnDef()
+ .setName("date_in_ms")
+ .setType(AddColumnsBuilder.ColumnDef.Type.BIG_INTEGER)
+ .setNullable(true))
+ .addColumn(new AddColumnsBuilder.ColumnDef()
+ .setName("name")
+ .setType(AddColumnsBuilder.ColumnDef.Type.STRING)
+ .setNullable(false)
+ .setLimit(10))
+ .build()).isEqualTo("ALTER TABLE issues ADD (date_in_ms BIGINT NULL, name VARCHAR (10) NOT NULL)");
+ }
+
+ @Test
+ public void add_columns_on_mysql() throws Exception {
+ assertThat(new AddColumnsBuilder(new MySql(), "issues")
+ .addColumn(new AddColumnsBuilder.ColumnDef()
+ .setName("date_in_ms")
+ .setType(AddColumnsBuilder.ColumnDef.Type.BIG_INTEGER)
+ .setNullable(true))
+ .addColumn(new AddColumnsBuilder.ColumnDef()
+ .setName("name")
+ .setType(AddColumnsBuilder.ColumnDef.Type.STRING)
+ .setNullable(false)
+ .setLimit(10))
+ .build()).isEqualTo("ALTER TABLE issues ADD (date_in_ms BIGINT NULL, name VARCHAR (10) NOT NULL)");
+ }
+
+ @Test
+ public void add_columns_on_oracle() throws Exception {
+ assertThat(new AddColumnsBuilder(new Oracle(), "issues")
+ .addColumn(new AddColumnsBuilder.ColumnDef()
+ .setName("date_in_ms")
+ .setType(AddColumnsBuilder.ColumnDef.Type.BIG_INTEGER)
+ .setNullable(true))
+ .addColumn(new AddColumnsBuilder.ColumnDef()
+ .setName("name")
+ .setType(AddColumnsBuilder.ColumnDef.Type.STRING)
+ .setNullable(false)
+ .setLimit(10))
+ .build()).isEqualTo("ALTER TABLE issues ADD (date_in_ms NUMBER (38) NULL, name VARCHAR (10) NOT NULL)");
+ }
+
+ @Test
+ public void add_columns_on_postgresql() throws Exception {
+ assertThat(new AddColumnsBuilder(new PostgreSql(), "issues")
+ .addColumn(new AddColumnsBuilder.ColumnDef()
+ .setName("date_in_ms")
+ .setType(AddColumnsBuilder.ColumnDef.Type.BIG_INTEGER)
+ .setNullable(true))
+ .addColumn(new AddColumnsBuilder.ColumnDef()
+ .setName("name")
+ .setType(AddColumnsBuilder.ColumnDef.Type.STRING)
+ .setNullable(false)
+ .setLimit(10))
+ .build()).isEqualTo("ALTER TABLE issues ADD COLUMN date_in_ms BIGINT NULL, ADD COLUMN name VARCHAR (10) NOT NULL");
+ }
+
+ @Test
+ public void add_columns_on_mssql() throws Exception {
+ assertThat(new AddColumnsBuilder(new MsSql(), "issues")
+ .addColumn(new AddColumnsBuilder.ColumnDef()
+ .setName("date_in_ms")
+ .setType(AddColumnsBuilder.ColumnDef.Type.BIG_INTEGER)
+ .setNullable(true))
+ .addColumn(new AddColumnsBuilder.ColumnDef()
+ .setName("name")
+ .setType(AddColumnsBuilder.ColumnDef.Type.STRING)
+ .setNullable(false)
+ .setLimit(10))
+ .build()).isEqualTo("ALTER TABLE issues ADD date_in_ms BIGINT NULL, name VARCHAR (10) NOT NULL");
+ }
+
+ @Test
+ public void fail_when_column_name_is_in_upper_case() throws Exception {
+ try {
+ new AddColumnsBuilder.ColumnDef()
+ .setName("DATE_IN_MS")
+ .setType(AddColumnsBuilder.ColumnDef.Type.BIG_INTEGER)
+ .setNullable(true);
+ failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Column name should only contains lowercase and _ characters");
+ }
+ }
+
+ @Test
+ public void fail_when_column_name_contains_invalid_character() throws Exception {
+ try {
+ new AddColumnsBuilder.ColumnDef()
+ .setName("date-in/ms")
+ .setType(AddColumnsBuilder.ColumnDef.Type.BIG_INTEGER)
+ .setNullable(true);
+ failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Column name should only contains lowercase and _ characters");
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+
+import org.junit.Test;
+import org.sonar.core.persistence.dialect.*;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DropColumnsBuilderTest {
+
+ @Test
+ public void drop_columns_on_mysql() throws Exception {
+ assertThat(new DropColumnsBuilder(new MySql(), "issues", "date_in_ms", "name")
+ .build()).isEqualTo("ALTER TABLE issues DROP COLUMN date_in_ms, DROP COLUMN name");
+ }
+
+ @Test
+ public void drop_columns_on_oracle() throws Exception {
+ assertThat(new DropColumnsBuilder(new Oracle(), "issues", "date_in_ms", "name")
+ .build()).isEqualTo("ALTER TABLE issues DROP (date_in_ms, name)");
+ }
+
+ @Test
+ public void drop_columns_on_postgresql() throws Exception {
+ assertThat(new DropColumnsBuilder(new PostgreSql(), "issues", "date_in_ms", "name")
+ .build()).isEqualTo("ALTER TABLE issues DROP COLUMN date_in_ms, DROP COLUMN name");
+ }
+
+ @Test
+ public void drop_columns_on_mssql() throws Exception {
+ assertThat(new DropColumnsBuilder(new MsSql(), "issues", "date_in_ms", "name")
+ .build()).isEqualTo("ALTER TABLE issues DROP COLUMN date_in_ms, name");
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void fail_to_drop_columns_on_h2() throws Exception {
+ new DropColumnsBuilder(new H2(), "issues", "date_in_ms", "name")
+ .build();
+ }
+
+}
--- /dev/null
+/*
+ * 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.v51;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.db.migrations.DatabaseMigration;
+
+import java.sql.Types;
+
+public class AddIssuesColumnsTest {
+
+ @ClassRule
+ public static DbTester db = new DbTester().schema(AddIssuesColumnsTest.class, "schema.sql");
+
+ DatabaseMigration migration;
+
+ @Before
+ public void setUp() throws Exception {
+ migration = new AddIssuesColumns(db.database());
+ }
+
+ @Test
+ public void update_columns() throws Exception {
+ migration.execute();
+
+ db.assertColumnDefinition("issues", "issue_creation_date_ms", Types.BIGINT, null);
+ db.assertColumnDefinition("issues", "issue_update_date_ms", Types.BIGINT, null);
+ db.assertColumnDefinition("issues", "issue_close_date_ms", Types.BIGINT, null);
+ db.assertColumnDefinition("issues", "tags", Types.VARCHAR, 4000);
+ db.assertColumnDefinition("issues", "component_uuid", Types.VARCHAR, 50);
+ db.assertColumnDefinition("issues", "project_uuid", Types.VARCHAR, 50);
+ }
+
+}
--- /dev/null
+/*
+ * 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.v51;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.core.persistence.Database;
+import org.sonar.core.persistence.dialect.PostgreSql;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DropIssuesColumnsTest {
+
+ DropIssuesColumns migration;
+
+ Database database;
+
+ @Before
+ public void setUp() throws Exception {
+ database = mock(Database.class);
+ migration = new DropIssuesColumns(database);
+ }
+
+ @Test
+ public void generate_sql_on_postgresql() throws Exception {
+ when(database.getDialect()).thenReturn(new PostgreSql());
+ assertThat(migration.generateSql()).isEqualTo(
+ "ALTER TABLE issues DROP COLUMN issue_creation_date, DROP COLUMN issue_update_date, DROP COLUMN issue_close_date, DROP COLUMN component_id, DROP COLUMN root_component_id"
+ );
+ }
+
+}
--- /dev/null
+CREATE TABLE "ISSUES" (
+ "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "KEE" VARCHAR(50) UNIQUE NOT NULL,
+ "COMPONENT_ID" INTEGER NOT NULL,
+ "ROOT_COMPONENT_ID" INTEGER,
+ "RULE_ID" INTEGER,
+ "SEVERITY" VARCHAR(10),
+ "MANUAL_SEVERITY" BOOLEAN NOT NULL,
+ "MESSAGE" VARCHAR(4000),
+ "LINE" INTEGER,
+ "EFFORT_TO_FIX" DOUBLE,
+ "TECHNICAL_DEBT" INTEGER,
+ "STATUS" VARCHAR(20),
+ "RESOLUTION" VARCHAR(20),
+ "CHECKSUM" VARCHAR(1000),
+ "REPORTER" VARCHAR(255),
+ "ASSIGNEE" VARCHAR(255),
+ "AUTHOR_LOGIN" VARCHAR(255),
+ "ACTION_PLAN_KEY" VARCHAR(50) NULL,
+ "ISSUE_ATTRIBUTES" VARCHAR(4000),
+ "ISSUE_CREATION_DATE" TIMESTAMP,
+ "ISSUE_CLOSE_DATE" TIMESTAMP,
+ "ISSUE_UPDATE_DATE" TIMESTAMP,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT
+);
--- /dev/null
+#
+# 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.1
+# SONAR-5896
+#
+class AddIssuesColumns < ActiveRecord::Migration
+
+ def self.up
+ execute_java_migration('org.sonar.server.db.migrations.v51.AddIssuesColumns')
+ end
+
+end
+++ /dev/null
-#
-# 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.1
-# SONAR-5896
-#
-class AddIssuesTagsColumn < ActiveRecord::Migration
-
- def self.up
- add_column 'issues', :tags, :string, :null => true, :limit => 4000
- end
-
-end
+++ /dev/null
-#
-# 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.1
-#
-class AddIssueComponentUuids < ActiveRecord::Migration
-
- def self.up
- add_column 'issues', :component_uuid, :string, :limit => 50, :null => true
- add_column 'issues', :project_uuid, :string, :limit => 50, :null => true
- add_index 'issues', 'component_uuid', :name => 'issues_component_uuid'
- add_index 'issues', 'project_uuid', :name => 'issues_project_uuid'
- end
-end
--- /dev/null
+#
+# 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.1
+#
+class AddIssuesComponentUuidsIndexes < ActiveRecord::Migration
+
+ def self.up
+ add_index 'issues', 'component_uuid', :name => 'issues_component_uuid'
+ add_index 'issues', 'project_uuid', :name => 'issues_project_uuid'
+ end
+end
+++ /dev/null
-#
-# 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.1
-#
-class RemoveIssueComponentIds < ActiveRecord::Migration
-
- def self.up
- if dialect()=='sqlserver'
- remove_index :issues, :name => 'issues_component_uuid'
- remove_index :issues, :name => 'issues_project_uuid'
- end
- remove_index 'issues', :name => 'issues_component_id'
- remove_index 'issues', :name => 'issues_root_component_id'
- remove_column 'issues', 'component_id'
- remove_column 'issues', 'root_component_id'
-
- if dialect()=='sqlserver'
- add_index :issues, :component_uuid, :name => 'issues_component_uuid'
- add_index :issues, :project_uuid, :name => 'issues_project_uuid'
- end
- end
-end
--- /dev/null
+#
+# 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.1
+#
+class FeedIssuesLongDates < ActiveRecord::Migration
+
+ def self.up
+ execute_java_migration('org.sonar.server.db.migrations.v51.FeedIssuesLongDates')
+ end
+
+end
+
+++ /dev/null
-#
-# 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.1
-#
-class AddIssuesLongDates < ActiveRecord::Migration
- def self.up
- add_column 'issues', :issue_creation_date_ms, :big_integer, :null => true
- add_column 'issues', :issue_update_date_ms, :big_integer, :null => true
- add_column 'issues', :issue_close_date_ms, :big_integer, :null => true
- end
-end
--- /dev/null
+#
+# 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.1
+#
+class RemoveIssuesComponentIdsAndCreationDateIndexes < ActiveRecord::Migration
+
+ def self.up
+ remove_index 'issues', :name => 'issues_component_id'
+ remove_index 'issues', :name => 'issues_root_component_id'
+ remove_index 'issues', :name => 'issues_creation_date'
+ end
+end
--- /dev/null
+#
+# 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.1
+#
+class DropIssuesColumns < ActiveRecord::Migration
+
+ def self.up
+ execute_java_migration('org.sonar.server.db.migrations.v51.DropIssuesColumns')
+ end
+end
+++ /dev/null
-#
-# 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.1
-#
-class FeedIssuesLongDates < ActiveRecord::Migration
- def self.up
- execute_java_migration('org.sonar.server.db.migrations.v51.FeedIssuesLongDates')
- end
-end
-
# SonarQube 5.1
#
class RenameIssuesLongDates < ActiveRecord::Migration
+
def self.up
- remove_index 'issues', :name => 'issues_creation_date'
- remove_column 'issues', 'issue_creation_date'
- remove_column 'issues', 'issue_update_date'
- remove_column 'issues', 'issue_close_date'
rename_column 'issues', 'issue_creation_date_ms', 'issue_creation_date'
rename_column 'issues', 'issue_update_date_ms', 'issue_update_date'
rename_column 'issues', 'issue_close_date_ms', 'issue_close_date'
add_index 'issues', 'issue_creation_date', :name => 'issues_creation_date'
end
+
end
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('770');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('771');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('772');
-INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('773');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('774');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('775');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('776');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('777');
import org.sonar.core.config.Logback;
import org.sonar.core.persistence.dialect.Dialect;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
-import java.sql.Clob;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
+import java.sql.*;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
/**
for (int i = 1; i <= colCount; i++) {
Object value = resultSet.getObject(i);
if (value instanceof Clob) {
- value = IOUtils.toString(((Clob)value).getAsciiStream());
+ value = IOUtils.toString(((Clob) value).getAsciiStream());
}
columns.put(metaData.getColumnLabel(i), value);
}
}
}
+ public void assertColumnDefinition(String table, String column, int expectedType, @Nullable Integer expectedSize) {
+ try (Connection connection = openConnection();
+ PreparedStatement stmt = connection.prepareStatement("select * from " + table);
+ ResultSet res = stmt.executeQuery()) {
+ Integer columnIndex = getColumnIndex(res, column);
+ if (columnIndex == null) {
+ fail("The column '" + column + "' does not exist");
+ }
+
+ assertThat(res.getMetaData().getColumnType(columnIndex)).isEqualTo(expectedType);
+ if (expectedSize != null) {
+ assertThat(res.getMetaData().getColumnDisplaySize(columnIndex)).isEqualTo(expectedSize);
+ }
+
+ } catch (Exception e) {
+ throw new IllegalStateException("Fail to check column");
+ }
+ }
+
+ @CheckForNull
+ private Integer getColumnIndex(ResultSet res, String column) {
+ try {
+ ResultSetMetaData meta = res.getMetaData();
+ int numCol = meta.getColumnCount();
+ for (int i = 1; i < numCol + 1; i++) {
+ if (meta.getColumnLabel(i).toLowerCase().equals(column.toLowerCase())) {
+ return i;
+ }
+ }
+ return null;
+
+ } catch (Exception e) {
+ throw new IllegalStateException("Fail to get column idnex");
+ }
+ }
+
private IDataSet dbUnitDataSet(InputStream stream) {
try {
ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(stream));