]> source.dussan.org Git - sonarqube.git/commitdiff
Rename packages of Java db migrations
authorSimon Brandhof <simon.brandhof@gmail.com>
Thu, 6 Mar 2014 14:24:01 +0000 (15:24 +0100)
committerSimon Brandhof <simon.brandhof@gmail.com>
Thu, 6 Mar 2014 14:24:01 +0000 (15:24 +0100)
87 files changed:
sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java
sonar-server/src/main/java/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigration.java [deleted file]
sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueChangelogMigration.java [deleted file]
sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueMigration.java [deleted file]
sonar-server/src/main/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigration.java [deleted file]
sonar-server/src/main/java/org/sonar/server/db/migrations/debt/WorkDurationConvertor.java [deleted file]
sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigration.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/IssueChangelogMigration.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/IssueMigration.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigration.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/WorkDurationConvertor.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/db/migrations/violation/Progress.java [deleted file]
sonar-server/src/main/java/org/sonar/server/db/migrations/violation/Referentials.java [deleted file]
sonar-server/src/main/java/org/sonar/server/db/migrations/violation/ViolationConverter.java [deleted file]
sonar-server/src/main/java/org/sonar/server/db/migrations/violation/ViolationConverters.java [deleted file]
sonar-server/src/main/java/org/sonar/server/db/migrations/violation/ViolationMigration.java [deleted file]
sonar-server/src/main/java/org/sonar/server/db/migrations/violation/package-info.java [deleted file]
sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/Progress.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/Referentials.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/ViolationConverter.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/ViolationConverters.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/ViolationMigration.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/package-info.java [new file with mode: 0644]
sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb
sonar-server/src/main/webapp/WEB-INF/db/migrate/401_migrate_violations_to_issues.rb
sonar-server/src/main/webapp/WEB-INF/db/migrate/513_update_issue_debt_to_minutes.rb
sonar-server/src/main/webapp/WEB-INF/db/migrate/514_update_issue_changelog_debt_to_minutes.rb
sonar-server/src/main/webapp/WEB-INF/db/migrate/515_update_measures_debt_to_minutes.rb
sonar-server/src/main/webapp/WEB-INF/db/migrate/516_update_development_cost_to_minutes.rb
sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DebtMigrationExecutorTest.java [deleted file]
sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigrationTest.java [deleted file]
sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest.java [deleted file]
sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueMigrationTest.java [deleted file]
sonar-server/src/test/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest.java [deleted file]
sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/DebtMigrationExecutorTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigrationTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/IssueChangelogMigrationTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/IssueMigrationTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/db/migrations/violation/ProgressTest.java [deleted file]
sonar-server/src/test/java/org/sonar/server/db/migrations/violation/ViolationConvertersTest.java [deleted file]
sonar-server/src/test/java/org/sonar/server/db/migrations/violation/ViolationMigrationTest.java [deleted file]
sonar-server/src/test/java/org/sonar/server/db/migrations/violation36/ProgressTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/db/migrations/violation36/ViolationConvertersTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/db/migrations/violation36/ViolationMigrationTest.java [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigrationTest/migrate_dev_cost_measures.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigrationTest/migrate_dev_cost_measures_result.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigrationTest/schema.sql [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest/migrate_issue_changelog_debt.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest/migrate_issue_changelog_debt_result.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest/schema.sql [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueMigrationTest/migrate_issues_debt.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueMigrationTest/migrate_issues_debt_result.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueMigrationTest/schema.sql [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_new_technical_debt_measures.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_new_technical_debt_measures_result.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_sqale_measures.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_sqale_measures_result.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_technical_debt_measures.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_technical_debt_measures_result.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/schema.sql [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigrationTest/migrate_dev_cost_measures.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigrationTest/migrate_dev_cost_measures_result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigrationTest/schema.sql [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueChangelogMigrationTest/migrate_issue_changelog_debt.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueChangelogMigrationTest/migrate_issue_changelog_debt_result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueChangelogMigrationTest/schema.sql [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueMigrationTest/migrate_issues_debt.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueMigrationTest/migrate_issues_debt_result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueMigrationTest/schema.sql [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_new_technical_debt_measures.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_new_technical_debt_measures_result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_sqale_measures.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_sqale_measures_result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_technical_debt_measures.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_technical_debt_measures_result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/schema.sql [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/migrate_violations.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/migrate_violations_result.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/no_violations_to_migrate.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/no_violations_to_migrate_result.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/schema.sql [deleted file]
sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/migrate_violations.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/migrate_violations_result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/no_violations_to_migrate.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/no_violations_to_migrate_result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/schema.sql [new file with mode: 0644]

index 50eb4ea271150df66e001e07bea7364a373666c5..b8640b747c1e9340032f80818d1fc1afb5e6a413 100644 (file)
 package org.sonar.server.db.migrations;
 
 import com.google.common.collect.ImmutableList;
-import org.sonar.server.db.migrations.debt.DevelopmentCostMeasuresMigration;
-import org.sonar.server.db.migrations.debt.IssueChangelogMigration;
-import org.sonar.server.db.migrations.debt.IssueMigration;
-import org.sonar.server.db.migrations.debt.TechnicalDebtMeasuresMigration;
-import org.sonar.server.db.migrations.violation.ViolationMigration;
+import org.sonar.server.db.migrations.debt43.DevelopmentCostMeasuresMigration;
+import org.sonar.server.db.migrations.debt43.IssueChangelogMigration;
+import org.sonar.server.db.migrations.debt43.IssueMigration;
+import org.sonar.server.db.migrations.debt43.TechnicalDebtMeasuresMigration;
+import org.sonar.server.db.migrations.violation36.ViolationMigration;
 
 import java.util.List;
 
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigration.java
deleted file mode 100644 (file)
index 717e3b6..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.debt;
-
-import org.sonar.api.config.Settings;
-import org.sonar.core.persistence.Database;
-import org.sonar.server.db.migrations.DatabaseMigration;
-import org.sonar.server.db.migrations.MassUpdater;
-import org.sonar.server.db.migrations.SqlUtil;
-
-import javax.annotation.CheckForNull;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-/**
- * Used in the Active Record Migration 516
- * @since 4.3
- */
-public class DevelopmentCostMeasuresMigration implements DatabaseMigration {
-
-  private final WorkDurationConvertor workDurationConvertor;
-  private final Database db;
-
-  public DevelopmentCostMeasuresMigration(Database database, Settings settings) {
-    this.db = database;
-    this.workDurationConvertor = new WorkDurationConvertor(settings);
-  }
-
-  @Override
-  public void execute() {
-    new MassUpdater(db).execute(
-      new MassUpdater.InputLoader<Row>() {
-        @Override
-        public String selectSql() {
-          return "SELECT pm.id, pm.value " +
-            " FROM project_measures pm INNER JOIN metrics m on m.id=pm.metric_id " +
-            " WHERE m.name='development_cost' AND pm.value IS NOT NULL";
-        }
-
-        @Override
-        public Row load(ResultSet rs) throws SQLException {
-          Row row = new Row();
-          row.id = SqlUtil.getLong(rs, 1);
-          row.value = SqlUtil.getDouble(rs, 2);
-          return row;
-        }
-      },
-      new MassUpdater.InputConverter<Row>() {
-        @Override
-        public String updateSql() {
-          return "UPDATE project_measures SET value=NULL,text_value=? WHERE id=?";
-        }
-
-        @Override
-        public void convert(Row row, PreparedStatement updateStatement) throws SQLException {
-          updateStatement.setString(1, convertDebtForDays(row.value));
-          updateStatement.setLong(2, row.id);
-        }
-      }
-    );
-  }
-
-  @CheckForNull
-  private String convertDebtForDays(Double data) {
-    return Long.toString(workDurationConvertor.createFromDays(data));
-  }
-
-  private static class Row {
-    private Long id;
-    private Double value;
-  }
-
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueChangelogMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueChangelogMigration.java
deleted file mode 100644 (file)
index 720d611..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.debt;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Strings;
-import org.sonar.api.config.Settings;
-import org.sonar.api.utils.System2;
-import org.sonar.core.persistence.Database;
-import org.sonar.server.db.migrations.DatabaseMigration;
-import org.sonar.server.db.migrations.MassUpdater;
-import org.sonar.server.db.migrations.SqlUtil;
-
-import java.sql.Date;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Used in the Active Record Migration 514
- * @since 4.3
- */
-public class IssueChangelogMigration implements DatabaseMigration {
-
-  private final WorkDurationConvertor workDurationConvertor;
-  private final System2 system2;
-  private final Database db;
-
-  public IssueChangelogMigration(Database database, Settings settings) {
-    this(database, settings, System2.INSTANCE);
-  }
-
-  @VisibleForTesting
-  IssueChangelogMigration(Database database, Settings settings, System2 system2) {
-    this.db = database;
-    this.workDurationConvertor = new WorkDurationConvertor(settings);
-    this.system2 = system2;
-  }
-
-  @Override
-  public void execute() {
-    new MassUpdater(db).execute(
-      new MassUpdater.InputLoader<Row>() {
-        @Override
-        public String selectSql() {
-          return "SELECT ic.id, ic.change_data  FROM issue_changes ic " +
-            " WHERE ic.change_type = 'diff' AND ic.change_data LIKE '%technicalDebt%'";
-        }
-
-        @Override
-        public Row load(ResultSet rs) throws SQLException {
-          Row row = new Row();
-          row.id = SqlUtil.getLong(rs, 1);
-          row.changeData = rs.getString(2);
-          return row;
-        }
-      },
-      new MassUpdater.InputConverter<Row>() {
-        @Override
-        public String updateSql() {
-          return "UPDATE issue_changes SET change_data=?,updated_at=? WHERE id=?";
-        }
-
-        @Override
-        public void convert(Row row, PreparedStatement updateStatement) throws SQLException {
-          updateStatement.setString(1, convertChangelog(row.changeData));
-          updateStatement.setDate(2, new Date(system2.now()));
-          updateStatement.setLong(3, row.id);
-        }
-      }
-    );
-  }
-
-  @VisibleForTesting
-  String convertChangelog(String data) {
-    Pattern pattern = Pattern.compile("technicalDebt=(\\d*)\\|(\\d*)", Pattern.CASE_INSENSITIVE);
-    Matcher matcher = pattern.matcher(data);
-    StringBuffer sb = new StringBuffer();
-    if (matcher.find()) {
-      String replacement = "technicalDebt=";
-      String oldValue = matcher.group(1);
-      if (!Strings.isNullOrEmpty(oldValue)) {
-        long oldDebt = workDurationConvertor.createFromLong(Long.parseLong(oldValue));
-        replacement += Long.toString(oldDebt);
-      }
-      replacement += "|";
-      String newValue = matcher.group(2);
-      if (!Strings.isNullOrEmpty(newValue)) {
-        long newDebt = workDurationConvertor.createFromLong(Long.parseLong(newValue));
-        replacement += Long.toString(newDebt);
-      }
-      matcher.appendReplacement(sb, replacement);
-    }
-    matcher.appendTail(sb);
-    return sb.toString();
-  }
-
-  private static class Row {
-    private Long id;
-    private String changeData;
-  }
-
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueMigration.java
deleted file mode 100644 (file)
index c8f379b..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.debt;
-
-import com.google.common.annotations.VisibleForTesting;
-import org.sonar.api.config.Settings;
-import org.sonar.api.utils.System2;
-import org.sonar.core.persistence.Database;
-import org.sonar.server.db.migrations.DatabaseMigration;
-import org.sonar.server.db.migrations.MassUpdater;
-import org.sonar.server.db.migrations.SqlUtil;
-
-import java.sql.Date;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-/**
- * Used in the Active Record Migration 513
- * @since 4.3
- */
-public class IssueMigration implements DatabaseMigration {
-
-  private final WorkDurationConvertor workDurationConvertor;
-  private final System2 system2;
-  private final Database db;
-
-  public IssueMigration(Database database, Settings settings) {
-    this(database, settings, System2.INSTANCE);
-  }
-
-  @VisibleForTesting
-  IssueMigration(Database database, Settings settings, System2 system2) {
-    this.db = database;
-    this.workDurationConvertor = new WorkDurationConvertor(settings);
-    this.system2 = system2;
-  }
-
-  @Override
-  public void execute() {
-    new MassUpdater(db).execute(
-      new MassUpdater.InputLoader<Row>() {
-        @Override
-        public String selectSql() {
-          return "SELECT i.id, i.technical_debt FROM issues i WHERE i.technical_debt IS NOT NULL";
-        }
-
-        @Override
-        public Row load(ResultSet rs) throws SQLException {
-          Row row = new Row();
-          row.id = SqlUtil.getLong(rs, 1);
-          row.debt = SqlUtil.getLong(rs, 2);
-          return row;
-        }
-      },
-      new MassUpdater.InputConverter<Row>() {
-        @Override
-        public String updateSql() {
-          return "UPDATE issues SET technical_debt=?,updated_at=? WHERE id=?";
-        }
-
-        @Override
-        public void convert(Row row, PreparedStatement updateStatement) throws SQLException {
-          updateStatement.setLong(1, workDurationConvertor.createFromLong(row.debt));
-          updateStatement.setDate(2, new Date(system2.now()));
-          updateStatement.setLong(3, row.id);
-        }
-      }
-    );
-  }
-
-  private static class Row {
-    private Long id;
-    private Long debt;
-  }
-
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigration.java
deleted file mode 100644 (file)
index b177209..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.debt;
-
-import org.sonar.api.config.Settings;
-import org.sonar.core.persistence.Database;
-import org.sonar.server.db.migrations.DatabaseMigration;
-import org.sonar.server.db.migrations.MassUpdater;
-import org.sonar.server.db.migrations.SqlUtil;
-
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Types;
-
-/**
- * Used in the Active Record Migration 515
- * @since 4.3
- */
-public class TechnicalDebtMeasuresMigration implements DatabaseMigration {
-
-  private static final String SELECT_SQL = "SELECT pm.id, pm.value " +
-    ", pm.variation_value_1 , pm.variation_value_2, pm.variation_value_3 " +
-    ", pm.variation_value_4 , pm.variation_value_5 " +
-    " FROM project_measures pm INNER JOIN metrics m on m.id=pm.metric_id " +
-    " WHERE (m.name='sqale_index' or m.name='new_technical_debt' " +
-    // SQALE measures
-    " or m.name='sqale_effort_to_grade_a' or m.name='sqale_effort_to_grade_b' or m.name='sqale_effort_to_grade_c' or m.name='sqale_effort_to_grade_d' " +
-    " or m.name='blocker_remediation_cost' or m.name='critical_remediation_cost' or m.name='major_remediation_cost' or m.name='minor_remediation_cost' " +
-    " or m.name='info_remediation_cost' " +
-    ")";
-
-  private static final String UPDATE_SQL = "UPDATE project_measures SET value=?," +
-    "variation_value_1=?,variation_value_2=?,variation_value_3=?,variation_value_4=?,variation_value_5=? WHERE id=?";
-
-  private final WorkDurationConvertor workDurationConvertor;
-  private final Database db;
-
-  public TechnicalDebtMeasuresMigration(Database database, Settings settings) {
-    this.db = database;
-    this.workDurationConvertor = new WorkDurationConvertor(settings);
-  }
-
-  @Override
-  public void execute() {
-    new MassUpdater(db).execute(
-      new MassUpdater.InputLoader<Row>() {
-        @Override
-        public String selectSql() {
-          return SELECT_SQL;
-        }
-
-        @Override
-        public Row load(ResultSet rs) throws SQLException {
-          Row row = new Row();
-          row.id = SqlUtil.getLong(rs, 1);
-          row.value = SqlUtil.getDouble(rs, 2);
-          row.var1 = SqlUtil.getDouble(rs, 3);
-          row.var2 = SqlUtil.getDouble(rs, 4);
-          row.var3 = SqlUtil.getDouble(rs, 5);
-          row.var4 = SqlUtil.getDouble(rs, 6);
-          row.var5 = SqlUtil.getDouble(rs, 7);
-          return row;
-        }
-      },
-      new MassUpdater.InputConverter<Row>() {
-        @Override
-        public String updateSql() {
-          return UPDATE_SQL;
-        }
-
-        @Override
-        public void convert(Row row, PreparedStatement updateStatement) throws SQLException {
-          setDouble(updateStatement, 1, row.value);
-          setDouble(updateStatement, 2, row.var1);
-          setDouble(updateStatement, 3, row.var2);
-          setDouble(updateStatement, 4, row.var3);
-          setDouble(updateStatement, 5, row.var4);
-          setDouble(updateStatement, 6, row.var5);
-          updateStatement.setLong(7, row.id);
-        }
-      }
-    );
-  }
-
-  private void setDouble(PreparedStatement statement, int index, Double value) throws SQLException {
-    if (value != null) {
-      statement.setDouble(index, convertDebtForDays(value));
-    } else {
-      statement.setNull(index, Types.DOUBLE);
-    }
-  }
-
-  private Long convertDebtForDays(Double data) {
-    return workDurationConvertor.createFromDays(data);
-  }
-
-  private static class Row {
-    private Long id;
-    private Double value;
-    private Double var1;
-    private Double var2;
-    private Double var3;
-    private Double var4;
-    private Double var5;
-  }
-
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/WorkDurationConvertor.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/WorkDurationConvertor.java
deleted file mode 100644 (file)
index 2d98efd..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.debt;
-
-import org.sonar.api.config.Settings;
-
-class WorkDurationConvertor {
-
-  static final long ONE_HOUR = 60L;
-
-  static final String HOURS_IN_DAY_PROPERTY = "sonar.technicalDebt.hoursInDay";
-
-  private final Settings settings;
-
-  WorkDurationConvertor(Settings settings) {
-    this.settings = settings;
-  }
-
-  long createFromLong(long durationInLong) {
-    int hoursInDay = hoursInDay();
-
-    long durationInMinutes = 0L;
-
-    long remainingTime = durationInLong;
-    Long currentTime = remainingTime / 10000;
-    if (currentTime > 0) {
-      durationInMinutes = currentTime.intValue() * hoursInDay * ONE_HOUR;
-      remainingTime = remainingTime - (currentTime * 10000);
-    }
-
-    currentTime = remainingTime / 100;
-    if (currentTime > 0) {
-      durationInMinutes += currentTime.intValue() * ONE_HOUR;
-      remainingTime = remainingTime - (currentTime * 100);
-    }
-
-    currentTime = remainingTime;
-    if (currentTime > 0) {
-      durationInMinutes += currentTime.intValue();
-    }
-
-    return durationInMinutes;
-  }
-
-  long createFromDays(double days) {
-    return ((Double) (days * hoursInDay() * ONE_HOUR)).longValue();
-  }
-
-  private int hoursInDay() {
-    int hoursInDay = settings.getInt(HOURS_IN_DAY_PROPERTY);
-    if (hoursInDay < 0) {
-      throw new IllegalArgumentException(String.format("Bad value of %s: %d", HOURS_IN_DAY_PROPERTY, hoursInDay));
-    }
-    if (hoursInDay == 0) {
-      hoursInDay = 8;
-    }
-    return hoursInDay;
-  }
-
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigration.java
new file mode 100644 (file)
index 0000000..3b3d4e3
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.debt43;
+
+import org.sonar.api.config.Settings;
+import org.sonar.core.persistence.Database;
+import org.sonar.server.db.migrations.DatabaseMigration;
+import org.sonar.server.db.migrations.MassUpdater;
+import org.sonar.server.db.migrations.SqlUtil;
+
+import javax.annotation.CheckForNull;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * Used in the Active Record Migration 516
+ * @since 4.3
+ */
+public class DevelopmentCostMeasuresMigration implements DatabaseMigration {
+
+  private final WorkDurationConvertor workDurationConvertor;
+  private final Database db;
+
+  public DevelopmentCostMeasuresMigration(Database database, Settings settings) {
+    this.db = database;
+    this.workDurationConvertor = new WorkDurationConvertor(settings);
+  }
+
+  @Override
+  public void execute() {
+    new MassUpdater(db).execute(
+      new MassUpdater.InputLoader<Row>() {
+        @Override
+        public String selectSql() {
+          return "SELECT pm.id, pm.value " +
+            " FROM project_measures pm INNER JOIN metrics m on m.id=pm.metric_id " +
+            " WHERE m.name='development_cost' AND pm.value IS NOT NULL";
+        }
+
+        @Override
+        public Row load(ResultSet rs) throws SQLException {
+          Row row = new Row();
+          row.id = SqlUtil.getLong(rs, 1);
+          row.value = SqlUtil.getDouble(rs, 2);
+          return row;
+        }
+      },
+      new MassUpdater.InputConverter<Row>() {
+        @Override
+        public String updateSql() {
+          return "UPDATE project_measures SET value=NULL,text_value=? WHERE id=?";
+        }
+
+        @Override
+        public void convert(Row row, PreparedStatement updateStatement) throws SQLException {
+          updateStatement.setString(1, convertDebtForDays(row.value));
+          updateStatement.setLong(2, row.id);
+        }
+      }
+    );
+  }
+
+  @CheckForNull
+  private String convertDebtForDays(Double data) {
+    return Long.toString(workDurationConvertor.createFromDays(data));
+  }
+
+  private static class Row {
+    private Long id;
+    private Double value;
+  }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/IssueChangelogMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/IssueChangelogMigration.java
new file mode 100644 (file)
index 0000000..015d48f
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.debt43;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Strings;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.Database;
+import org.sonar.server.db.migrations.DatabaseMigration;
+import org.sonar.server.db.migrations.MassUpdater;
+import org.sonar.server.db.migrations.SqlUtil;
+
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Used in the Active Record Migration 514
+ * @since 4.3
+ */
+public class IssueChangelogMigration implements DatabaseMigration {
+
+  private final WorkDurationConvertor workDurationConvertor;
+  private final System2 system2;
+  private final Database db;
+
+  public IssueChangelogMigration(Database database, Settings settings) {
+    this(database, settings, System2.INSTANCE);
+  }
+
+  @VisibleForTesting
+  IssueChangelogMigration(Database database, Settings settings, System2 system2) {
+    this.db = database;
+    this.workDurationConvertor = new WorkDurationConvertor(settings);
+    this.system2 = system2;
+  }
+
+  @Override
+  public void execute() {
+    new MassUpdater(db).execute(
+      new MassUpdater.InputLoader<Row>() {
+        @Override
+        public String selectSql() {
+          return "SELECT ic.id, ic.change_data  FROM issue_changes ic " +
+            " WHERE ic.change_type = 'diff' AND ic.change_data LIKE '%technicalDebt%'";
+        }
+
+        @Override
+        public Row load(ResultSet rs) throws SQLException {
+          Row row = new Row();
+          row.id = SqlUtil.getLong(rs, 1);
+          row.changeData = rs.getString(2);
+          return row;
+        }
+      },
+      new MassUpdater.InputConverter<Row>() {
+        @Override
+        public String updateSql() {
+          return "UPDATE issue_changes SET change_data=?,updated_at=? WHERE id=?";
+        }
+
+        @Override
+        public void convert(Row row, PreparedStatement updateStatement) throws SQLException {
+          updateStatement.setString(1, convertChangelog(row.changeData));
+          updateStatement.setDate(2, new Date(system2.now()));
+          updateStatement.setLong(3, row.id);
+        }
+      }
+    );
+  }
+
+  @VisibleForTesting
+  String convertChangelog(String data) {
+    Pattern pattern = Pattern.compile("technicalDebt=(\\d*)\\|(\\d*)", Pattern.CASE_INSENSITIVE);
+    Matcher matcher = pattern.matcher(data);
+    StringBuffer sb = new StringBuffer();
+    if (matcher.find()) {
+      String replacement = "technicalDebt=";
+      String oldValue = matcher.group(1);
+      if (!Strings.isNullOrEmpty(oldValue)) {
+        long oldDebt = workDurationConvertor.createFromLong(Long.parseLong(oldValue));
+        replacement += Long.toString(oldDebt);
+      }
+      replacement += "|";
+      String newValue = matcher.group(2);
+      if (!Strings.isNullOrEmpty(newValue)) {
+        long newDebt = workDurationConvertor.createFromLong(Long.parseLong(newValue));
+        replacement += Long.toString(newDebt);
+      }
+      matcher.appendReplacement(sb, replacement);
+    }
+    matcher.appendTail(sb);
+    return sb.toString();
+  }
+
+  private static class Row {
+    private Long id;
+    private String changeData;
+  }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/IssueMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/IssueMigration.java
new file mode 100644 (file)
index 0000000..e988bb7
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.debt43;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.Database;
+import org.sonar.server.db.migrations.DatabaseMigration;
+import org.sonar.server.db.migrations.MassUpdater;
+import org.sonar.server.db.migrations.SqlUtil;
+
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * Used in the Active Record Migration 513
+ * @since 4.3
+ */
+public class IssueMigration implements DatabaseMigration {
+
+  private final WorkDurationConvertor workDurationConvertor;
+  private final System2 system2;
+  private final Database db;
+
+  public IssueMigration(Database database, Settings settings) {
+    this(database, settings, System2.INSTANCE);
+  }
+
+  @VisibleForTesting
+  IssueMigration(Database database, Settings settings, System2 system2) {
+    this.db = database;
+    this.workDurationConvertor = new WorkDurationConvertor(settings);
+    this.system2 = system2;
+  }
+
+  @Override
+  public void execute() {
+    new MassUpdater(db).execute(
+      new MassUpdater.InputLoader<Row>() {
+        @Override
+        public String selectSql() {
+          return "SELECT i.id, i.technical_debt FROM issues i WHERE i.technical_debt IS NOT NULL";
+        }
+
+        @Override
+        public Row load(ResultSet rs) throws SQLException {
+          Row row = new Row();
+          row.id = SqlUtil.getLong(rs, 1);
+          row.debt = SqlUtil.getLong(rs, 2);
+          return row;
+        }
+      },
+      new MassUpdater.InputConverter<Row>() {
+        @Override
+        public String updateSql() {
+          return "UPDATE issues SET technical_debt=?,updated_at=? WHERE id=?";
+        }
+
+        @Override
+        public void convert(Row row, PreparedStatement updateStatement) throws SQLException {
+          updateStatement.setLong(1, workDurationConvertor.createFromLong(row.debt));
+          updateStatement.setDate(2, new Date(system2.now()));
+          updateStatement.setLong(3, row.id);
+        }
+      }
+    );
+  }
+
+  private static class Row {
+    private Long id;
+    private Long debt;
+  }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigration.java
new file mode 100644 (file)
index 0000000..99eeda2
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.debt43;
+
+import org.sonar.api.config.Settings;
+import org.sonar.core.persistence.Database;
+import org.sonar.server.db.migrations.DatabaseMigration;
+import org.sonar.server.db.migrations.MassUpdater;
+import org.sonar.server.db.migrations.SqlUtil;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+
+/**
+ * Used in the Active Record Migration 515
+ * @since 4.3
+ */
+public class TechnicalDebtMeasuresMigration implements DatabaseMigration {
+
+  private static final String SELECT_SQL = "SELECT pm.id, pm.value " +
+    ", pm.variation_value_1 , pm.variation_value_2, pm.variation_value_3 " +
+    ", pm.variation_value_4 , pm.variation_value_5 " +
+    " FROM project_measures pm INNER JOIN metrics m on m.id=pm.metric_id " +
+    " WHERE (m.name='sqale_index' or m.name='new_technical_debt' " +
+    // SQALE measures
+    " or m.name='sqale_effort_to_grade_a' or m.name='sqale_effort_to_grade_b' or m.name='sqale_effort_to_grade_c' or m.name='sqale_effort_to_grade_d' " +
+    " or m.name='blocker_remediation_cost' or m.name='critical_remediation_cost' or m.name='major_remediation_cost' or m.name='minor_remediation_cost' " +
+    " or m.name='info_remediation_cost' " +
+    ")";
+
+  private static final String UPDATE_SQL = "UPDATE project_measures SET value=?," +
+    "variation_value_1=?,variation_value_2=?,variation_value_3=?,variation_value_4=?,variation_value_5=? WHERE id=?";
+
+  private final WorkDurationConvertor workDurationConvertor;
+  private final Database db;
+
+  public TechnicalDebtMeasuresMigration(Database database, Settings settings) {
+    this.db = database;
+    this.workDurationConvertor = new WorkDurationConvertor(settings);
+  }
+
+  @Override
+  public void execute() {
+    new MassUpdater(db).execute(
+      new MassUpdater.InputLoader<Row>() {
+        @Override
+        public String selectSql() {
+          return SELECT_SQL;
+        }
+
+        @Override
+        public Row load(ResultSet rs) throws SQLException {
+          Row row = new Row();
+          row.id = SqlUtil.getLong(rs, 1);
+          row.value = SqlUtil.getDouble(rs, 2);
+          row.var1 = SqlUtil.getDouble(rs, 3);
+          row.var2 = SqlUtil.getDouble(rs, 4);
+          row.var3 = SqlUtil.getDouble(rs, 5);
+          row.var4 = SqlUtil.getDouble(rs, 6);
+          row.var5 = SqlUtil.getDouble(rs, 7);
+          return row;
+        }
+      },
+      new MassUpdater.InputConverter<Row>() {
+        @Override
+        public String updateSql() {
+          return UPDATE_SQL;
+        }
+
+        @Override
+        public void convert(Row row, PreparedStatement updateStatement) throws SQLException {
+          setDouble(updateStatement, 1, row.value);
+          setDouble(updateStatement, 2, row.var1);
+          setDouble(updateStatement, 3, row.var2);
+          setDouble(updateStatement, 4, row.var3);
+          setDouble(updateStatement, 5, row.var4);
+          setDouble(updateStatement, 6, row.var5);
+          updateStatement.setLong(7, row.id);
+        }
+      }
+    );
+  }
+
+  private void setDouble(PreparedStatement statement, int index, Double value) throws SQLException {
+    if (value != null) {
+      statement.setDouble(index, convertDebtForDays(value));
+    } else {
+      statement.setNull(index, Types.DOUBLE);
+    }
+  }
+
+  private Long convertDebtForDays(Double data) {
+    return workDurationConvertor.createFromDays(data);
+  }
+
+  private static class Row {
+    private Long id;
+    private Double value;
+    private Double var1;
+    private Double var2;
+    private Double var3;
+    private Double var4;
+    private Double var5;
+  }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/WorkDurationConvertor.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt43/WorkDurationConvertor.java
new file mode 100644 (file)
index 0000000..f0bae4e
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.debt43;
+
+import org.sonar.api.config.Settings;
+
+class WorkDurationConvertor {
+
+  static final long ONE_HOUR = 60L;
+
+  static final String HOURS_IN_DAY_PROPERTY = "sonar.technicalDebt.hoursInDay";
+
+  private final Settings settings;
+
+  WorkDurationConvertor(Settings settings) {
+    this.settings = settings;
+  }
+
+  long createFromLong(long durationInLong) {
+    int hoursInDay = hoursInDay();
+
+    long durationInMinutes = 0L;
+
+    long remainingTime = durationInLong;
+    Long currentTime = remainingTime / 10000;
+    if (currentTime > 0) {
+      durationInMinutes = currentTime.intValue() * hoursInDay * ONE_HOUR;
+      remainingTime = remainingTime - (currentTime * 10000);
+    }
+
+    currentTime = remainingTime / 100;
+    if (currentTime > 0) {
+      durationInMinutes += currentTime.intValue() * ONE_HOUR;
+      remainingTime = remainingTime - (currentTime * 100);
+    }
+
+    currentTime = remainingTime;
+    if (currentTime > 0) {
+      durationInMinutes += currentTime.intValue();
+    }
+
+    return durationInMinutes;
+  }
+
+  long createFromDays(double days) {
+    return ((Double) (days * hoursInDay() * ONE_HOUR)).longValue();
+  }
+
+  private int hoursInDay() {
+    int hoursInDay = settings.getInt(HOURS_IN_DAY_PROPERTY);
+    if (hoursInDay < 0) {
+      throw new IllegalArgumentException(String.format("Bad value of %s: %d", HOURS_IN_DAY_PROPERTY, hoursInDay));
+    }
+    if (hoursInDay == 0) {
+      hoursInDay = 8;
+    }
+    return hoursInDay;
+  }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/violation/Progress.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/violation/Progress.java
deleted file mode 100644 (file)
index 7673ac2..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.violation;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.TimerTask;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * This task logs every minute the status of migration. It is destroyed
- * when migration is finished.
- */
-class Progress extends TimerTask {
-
-  static final String THREAD_NAME = "Violation Migration Progress";
-  static final long DELAY_MS = 60000L;
-
-  private final AtomicLong counter = new AtomicLong(0L);
-  private final Logger logger;
-  private final long totalViolations;
-  private final long start;
-
-  Progress(long totalViolations, Logger logger, long startDate) {
-    this.totalViolations = totalViolations;
-    this.logger = logger;
-    this.start = startDate;
-  }
-
-  Progress(long totalViolations) {
-    this(totalViolations, LoggerFactory.getLogger(Progress.class), System.currentTimeMillis());
-  }
-
-  void increment(int delta) {
-    counter.addAndGet(delta);
-  }
-
-  @Override
-  public void run() {
-    long totalIssues = counter.get();
-    long durationMinutes = (System.currentTimeMillis() - start) / 60000L;
-    int percents = (int) ((100L * totalIssues) / totalViolations);
-    if (totalIssues > 0 && durationMinutes > 0) {
-      int frequency = (int) (totalIssues / durationMinutes);
-      long remaining = (totalViolations - totalIssues) / frequency;
-      logger.info(String.format(
-        "%d%% [%d/%d violations, %d minutes remaining]", percents, totalIssues, totalViolations, remaining)
-      );
-    } else {
-      logger.info(String.format("%d%% [%d/%d violations]", percents, totalIssues, totalViolations));
-    }
-
-  }
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/violation/Referentials.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/violation/Referentials.java
deleted file mode 100644 (file)
index 4cf805a..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.violation;
-
-import com.google.common.collect.Maps;
-import org.apache.commons.dbutils.DbUtils;
-import org.apache.commons.dbutils.QueryRunner;
-import org.apache.commons.dbutils.ResultSetHandler;
-import org.sonar.core.persistence.Database;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.Map;
-import java.util.Queue;
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-/**
- * Data loaded from database before migrating violations. It is
- * shared amongst converter parallel tasks.
- */
-class Referentials {
-
-  static final int VIOLATION_GROUP_SIZE = 1000;
-
-  private final Map<Long, String> loginsByUserId;
-  private final Map<Long, String> plansById;
-  private final Queue<long[]> groupsOfViolationIds;
-  private long totalViolations = 0L;
-
-  Referentials(Database database) throws SQLException {
-    loginsByUserId = selectLongString(database, "select id,login from users");
-    plansById = selectLongString(database, "select id,kee from action_plans");
-    groupsOfViolationIds = initGroupOfViolationIds(database);
-  }
-
-  @CheckForNull
-  String actionPlan(@Nullable Long id) {
-    return id != null ? plansById.get(id) : null;
-  }
-
-  @CheckForNull
-  String userLogin(@Nullable Long id) {
-    return id != null ? loginsByUserId.get(id) : null;
-  }
-
-  long totalViolations() {
-    return totalViolations;
-  }
-
-  Long[] pollGroupOfViolationIds() {
-    long[] longs = groupsOfViolationIds.poll();
-    if (longs == null) {
-      return new Long[0];
-    }
-    Long[] objects = new Long[longs.length];
-    for (int i = 0; i < longs.length; i++) {
-      objects[i] = Long.valueOf(longs[i]);
-    }
-    return objects;
-  }
-
-  private Map<Long, String> selectLongString(Database database, String sql) throws SQLException {
-    Connection connection = database.getDataSource().getConnection();
-    try {
-      return new QueryRunner().query(connection, sql, new ResultSetHandler<Map<Long, String>>() {
-        @Override
-        public Map<Long, String> handle(ResultSet rs) throws SQLException {
-          Map<Long, String> map = Maps.newHashMap();
-          while (rs.next()) {
-            map.put(rs.getLong(1), rs.getString(2));
-          }
-          return map;
-        }
-      });
-    } finally {
-      DbUtils.closeQuietly(connection);
-    }
-  }
-
-  private Queue<long[]> initGroupOfViolationIds(Database database) throws SQLException {
-    Connection connection = database.getDataSource().getConnection();
-    Statement stmt = null;
-    ResultSet rs = null;
-    try {
-      connection.setAutoCommit(false);
-      stmt = connection.createStatement();
-      stmt.setFetchSize(10000);
-      rs = stmt.executeQuery("select id from rule_failures");
-      ConcurrentLinkedQueue<long[]> queue = new ConcurrentLinkedQueue<long[]>();
-
-      totalViolations = 0;
-      long[] block = new long[VIOLATION_GROUP_SIZE];
-      int cursor = 0;
-      while (rs.next()) {
-        block[cursor] = rs.getLong(1);
-        cursor++;
-        totalViolations++;
-        if (cursor == VIOLATION_GROUP_SIZE) {
-          queue.add(block);
-          block = new long[VIOLATION_GROUP_SIZE];
-          cursor = 0;
-        }
-      }
-      if (cursor > 0) {
-        queue.add(block);
-      }
-      return queue;
-    } finally {
-      DbUtils.closeQuietly(connection, stmt, rs);
-    }
-  }
-
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/violation/ViolationConverter.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/violation/ViolationConverter.java
deleted file mode 100644 (file)
index 1cc1496..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.violation;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import org.apache.commons.dbutils.DbUtils;
-import org.apache.commons.dbutils.QueryRunner;
-import org.apache.commons.dbutils.handlers.AbstractListHandler;
-import org.sonar.api.rule.Severity;
-import org.sonar.core.persistence.Database;
-import org.sonar.server.db.migrations.SqlUtil;
-
-import java.sql.Connection;
-import java.sql.Date;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.Callable;
-
-class ViolationConverter implements Callable<Object> {
-
-  private static final long ONE_YEAR = 365L * 24 * 60 * 60 * 1000;
-  private static final Date ONE_YEAR_AGO = new Date(System.currentTimeMillis() - ONE_YEAR);
-
-  private static final String PROJECT_ID = "projectId";
-  private static final String CREATED_AT = "createdAt";
-  private static final String REVIEW_ID = "reviewId";
-  private static final String SEVERITY = "severity";
-  private static final String REVIEW_STATUS = "reviewStatus";
-  private static final String REVIEW_MANUAL_SEVERITY = "reviewManualSeverity";
-  private static final String REVIEW_SEVERITY = "reviewSeverity";
-  private static final String REVIEW_UPDATED_AT = "reviewUpdatedAt";
-  private static final String ROOT_PROJECT_ID = "rootProjectId";
-  private static final String RULE_ID = "ruleId";
-  private static final String MESSAGE = "message";
-  private static final String LINE = "line";
-  private static final String COST = "cost";
-  private static final String CHECKSUM = "checksum";
-  private static final String REVIEW_RESOLUTION = "reviewResolution";
-  private static final String REVIEW_REPORTER_ID = "reviewReporterId";
-  private static final String REVIEW_ASSIGNEE_ID = "reviewAssigneeId";
-  private static final String REVIEW_DATA = "reviewData";
-  private static final String REVIEW_MANUAL_VIOLATION = "reviewManualViolation";
-  private static final String PLAN_ID = "planId";
-  private static final String ISSUE_KEY = "issueKey";
-  private static final String STATUS_OPEN = "OPEN";
-  private static final String STATUS_CONFIRMED = "CONFIRMED";
-  private static final String UPDATED_AT = "updatedAt";
-  private static final String REVIEW_TEXT = "reviewText";
-  private static final String USER_ID = "userId";
-  private static final String SEVERITY_MAJOR = "MAJOR";
-
-
-  private static final String SQL_ISSUE_COLUMNS = "kee, component_id, root_component_id, rule_id, severity, manual_severity, message, line, effort_to_fix, status, resolution, " +
-    "checksum, reporter, assignee, action_plan_key, issue_attributes, issue_creation_date, issue_update_date, created_at, updated_at";
-
-  private static final String SQL_INSERT_ISSUE = "INSERT INTO issues(" + SQL_ISSUE_COLUMNS + ")" +
-    " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
-
-  private static final String SQL_INSERT_ISSUE_CHANGE = "INSERT INTO issue_changes(kee, issue_key, user_login, change_type, change_data, created_at, updated_at)" +
-    " VALUES (?, ?, ?, 'comment', ?, ?, ?)";
-
-  private static final String SQL_DELETE_RULE_FAILURES;
-
-  static {
-    StringBuilder sb = new StringBuilder("delete from rule_failures where ");
-    for (int i = 0; i < Referentials.VIOLATION_GROUP_SIZE; i++) {
-      if (i > 0) {
-        sb.append(" or ");
-      }
-      sb.append("id=?");
-    }
-    SQL_DELETE_RULE_FAILURES = sb.toString();
-  }
-
-  static final String SQL_SELECT_RULE_FAILURES;
-
-  static {
-    StringBuilder sb = new StringBuilder("select rev.id as reviewId, s.project_id as projectId, rf.rule_id as ruleId, " +
-      "  rf.failure_level as failureLevel, rf.message as message, rf.line as line, " +
-      "  rf.cost as cost, rf.created_at as createdAt, rf.checksum as checksum, rev.user_id as reviewReporterId, " +
-      "  rev.assignee_id as reviewAssigneeId, rev.status as reviewStatus, " +
-      "  rev.severity as reviewSeverity, rev.resolution as reviewResolution, rev.manual_severity as reviewManualSeverity, " +
-      "  rev.data as reviewData, rev.updated_at as reviewUpdatedAt, " +
-      "  s.root_project_id as rootProjectId, rev.manual_violation as reviewManualViolation, planreviews.action_plan_id as planId " +
-      " from rule_failures rf " +
-      " inner join snapshots s on s.id=rf.snapshot_id " +
-      " left join reviews rev on rev.rule_failure_permanent_id=rf.permanent_id " +
-      " left join action_plans_reviews planreviews on planreviews.review_id=rev.id " +
-      " where ");
-    for (int i = 0; i < Referentials.VIOLATION_GROUP_SIZE; i++) {
-      if (i > 0) {
-        sb.append(" or ");
-      }
-      sb.append("rf.id=?");
-    }
-    SQL_SELECT_RULE_FAILURES = sb.toString();
-  }
-
-  private final Database db;
-  private final Referentials referentials;
-  private final Progress progress;
-
-  ViolationConverter(Referentials referentials, Database db, Progress progress) {
-    this.referentials = referentials;
-    this.db = db;
-    this.progress = progress;
-  }
-
-  @Override
-  public Object call() throws SQLException {
-    // For each group of 1000 violation ids:
-    // - load related violations, reviews and action plans
-    // - in a transaction
-    //   -- insert issues
-    //   -- insert issue_changes if there are review comments
-    //   -- delete violations
-
-    Long[] violationIds = referentials.pollGroupOfViolationIds();
-    while (violationIds.length>0) {
-      List<Map<String, Object>> rows = selectRows(violationIds);
-      convert(rows, violationIds);
-
-      violationIds = referentials.pollGroupOfViolationIds();
-    }
-    return null;
-  }
-
-  private List<Map<String, Object>> selectRows(Long[] violationIds) throws SQLException {
-    Connection readConnection = null;
-    try {
-      readConnection = db.getDataSource().getConnection();
-      ViolationHandler violationHandler = new ViolationHandler();
-      return new QueryRunner().query(readConnection, SQL_SELECT_RULE_FAILURES, violationHandler, violationIds);
-
-    } finally {
-      DbUtils.closeQuietly(readConnection);
-    }
-  }
-
-  private void convert(List<Map<String, Object>> rows, Long[] violationIds) throws SQLException {
-    Connection readConnection = null;
-    Connection writeConnection = null;
-    try {
-      readConnection = db.getDataSource().getConnection();
-      writeConnection = db.getDataSource().getConnection();
-      writeConnection.setAutoCommit(false);
-
-      List<Object[]> allParams = Lists.newArrayList();
-      List<Map<String, Object>> allComments = Lists.newArrayList();
-
-      QueryRunner runner = new QueryRunner();
-      for (Map<String, Object> row : rows) {
-        Long componentId = (Long) row.get(PROJECT_ID);
-        if (componentId == null) {
-          continue;
-        }
-        String issueKey = UUID.randomUUID().toString();
-        String status, severity, reporter = null;
-        boolean manualSeverity;
-        Object createdAt = Objects.firstNonNull(row.get(CREATED_AT), ONE_YEAR_AGO);
-        Object updatedAt;
-        Long reviewId = (Long) row.get(REVIEW_ID);
-        if (reviewId == null) {
-          // violation without review
-          status = STATUS_OPEN;
-          manualSeverity = false;
-          severity = (String) row.get(SEVERITY);
-          updatedAt = createdAt;
-        } else {
-          // violation + review
-          String reviewStatus = (String) row.get(REVIEW_STATUS);
-          status = (STATUS_OPEN.equals(reviewStatus) ? STATUS_CONFIRMED : reviewStatus);
-          manualSeverity = Objects.firstNonNull((Boolean) row.get(REVIEW_MANUAL_SEVERITY), false);
-          severity = (String) row.get(REVIEW_SEVERITY);
-          updatedAt = Objects.firstNonNull(row.get(REVIEW_UPDATED_AT), ONE_YEAR_AGO);
-          if ((Boolean) row.get(REVIEW_MANUAL_VIOLATION)) {
-            reporter = referentials.userLogin((Long) row.get(REVIEW_REPORTER_ID));
-          }
-
-          List<Map<String, Object>> comments = runner.query(readConnection, ReviewCommentsHandler.SQL + reviewId, new ReviewCommentsHandler());
-          for (Map<String, Object> comment : comments) {
-            comment.put(ISSUE_KEY, issueKey);
-            allComments.add(comment);
-          }
-        }
-        Object[] params = new Object[20];
-        params[0] = issueKey;
-        params[1] = componentId;
-        params[2] = row.get(ROOT_PROJECT_ID);
-        params[3] = row.get(RULE_ID);
-        params[4] = severity;
-        params[5] = manualSeverity;
-        params[6] = row.get(MESSAGE);
-        params[7] = row.get(LINE);
-        params[8] = row.get(COST);
-        params[9] = status;
-        params[10] = row.get(REVIEW_RESOLUTION);
-        params[11] = row.get(CHECKSUM);
-        params[12] = reporter;
-        params[13] = referentials.userLogin((Long) row.get(REVIEW_ASSIGNEE_ID));
-        params[14] = referentials.actionPlan((Long) row.get(PLAN_ID));
-        params[15] = row.get(REVIEW_DATA);
-        params[16] = createdAt;
-        params[17] = updatedAt;
-        params[18] = createdAt;
-        params[19] = updatedAt;
-        allParams.add(params);
-      }
-      runner.batch(writeConnection, SQL_INSERT_ISSUE, allParams.toArray(new Object[allParams.size()][]));
-      insertComments(writeConnection, allComments);
-      runner.update(writeConnection, SQL_DELETE_RULE_FAILURES, violationIds);
-      writeConnection.commit();
-      progress.increment(rows.size());
-
-    } finally {
-      DbUtils.closeQuietly(readConnection);
-      DbUtils.closeQuietly(writeConnection);
-    }
-  }
-
-  private void insertComments(Connection writeConnection, List<Map<String, Object>> comments) throws SQLException {
-    List<Object[]> allParams = Lists.newArrayList();
-
-    for (Map<String, Object> comment : comments) {
-      String login = referentials.userLogin((Long) comment.get(USER_ID));
-      if (login != null) {
-        Object[] params = new Object[6];
-        params[0] = UUID.randomUUID().toString();
-        params[1] = comment.get(ISSUE_KEY);
-        params[2] = login;
-        params[3] = comment.get(REVIEW_TEXT);
-        params[4] = comment.get(CREATED_AT);
-        params[5] = comment.get(UPDATED_AT);
-        allParams.add(params);
-      }
-    }
-    if (!allParams.isEmpty()) {
-      new QueryRunner().batch(writeConnection, SQL_INSERT_ISSUE_CHANGE, allParams.toArray(new Object[allParams.size()][]));
-    }
-  }
-
-
-  private static class ReviewCommentsHandler extends AbstractListHandler<Map<String, Object>> {
-    static final String SQL = "select created_at as createdAt, updated_at as updatedAt, user_id as userId, review_text as reviewText from review_comments where review_id=";
-
-    @Override
-    protected Map<String, Object> handleRow(ResultSet rs) throws SQLException {
-      Map<String, Object> map = Maps.newHashMap();
-      map.put(CREATED_AT, rs.getTimestamp(CREATED_AT));
-      map.put(UPDATED_AT, rs.getTimestamp(UPDATED_AT));
-      map.put(USER_ID, SqlUtil.getLong(rs, USER_ID));
-      map.put(REVIEW_TEXT, rs.getString(REVIEW_TEXT));
-      return map;
-    }
-  }
-
-  private static class ViolationHandler extends AbstractListHandler<Map<String, Object>> {
-    private static final Map<Integer, String> SEVERITIES = ImmutableMap.of(0, Severity.INFO, 1, Severity.MINOR, 2, Severity.MAJOR, 3, Severity.CRITICAL, 4, Severity.BLOCKER);
-
-
-    @Override
-    protected Map<String, Object> handleRow(ResultSet rs) throws SQLException {
-      Map<String, Object> map = Maps.newHashMap();
-      map.put(REVIEW_ID, SqlUtil.getLong(rs, REVIEW_ID));
-      map.put(PROJECT_ID, SqlUtil.getLong(rs, PROJECT_ID));
-      map.put(ROOT_PROJECT_ID, SqlUtil.getLong(rs, ROOT_PROJECT_ID));
-      map.put(RULE_ID, SqlUtil.getLong(rs, RULE_ID));
-      map.put(SEVERITY, Objects.firstNonNull(SEVERITIES.get(SqlUtil.getInt(rs, "failureLevel")), SEVERITY_MAJOR));
-      map.put(MESSAGE, rs.getString(MESSAGE));
-      map.put(LINE, SqlUtil.getInt(rs, LINE));
-      map.put(COST, SqlUtil.getDouble(rs, COST));
-      map.put(CHECKSUM, rs.getString(CHECKSUM));
-      map.put(CREATED_AT, rs.getTimestamp(CREATED_AT));
-      map.put(REVIEW_RESOLUTION, rs.getString(REVIEW_RESOLUTION));
-      map.put(REVIEW_SEVERITY, Objects.firstNonNull(rs.getString(REVIEW_SEVERITY), SEVERITY_MAJOR));
-      map.put(REVIEW_STATUS, rs.getString(REVIEW_STATUS));
-      map.put(REVIEW_REPORTER_ID, SqlUtil.getLong(rs, REVIEW_REPORTER_ID));
-      map.put(REVIEW_ASSIGNEE_ID, SqlUtil.getLong(rs, REVIEW_ASSIGNEE_ID));
-      map.put(REVIEW_DATA, rs.getString(REVIEW_DATA));
-      map.put(REVIEW_MANUAL_SEVERITY, rs.getBoolean(REVIEW_MANUAL_SEVERITY));
-      map.put(REVIEW_UPDATED_AT, rs.getTimestamp(REVIEW_UPDATED_AT));
-      map.put(REVIEW_MANUAL_VIOLATION, rs.getBoolean(REVIEW_MANUAL_VIOLATION));
-      map.put(PLAN_ID, SqlUtil.getLong(rs, PLAN_ID));
-      return map;
-    }
-  }
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/violation/ViolationConverters.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/violation/ViolationConverters.java
deleted file mode 100644 (file)
index 622708d..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.violation;
-
-import com.google.common.collect.Lists;
-import org.sonar.api.config.Settings;
-import org.sonar.core.persistence.Database;
-
-import java.util.List;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-class ViolationConverters {
-
-  static final int DEFAULT_THREADS = 5;
-  static final String THREADS_PROPERTY = "sonar.violationMigration.threads";
-  private final Settings settings;
-
-  ViolationConverters(Settings settings) {
-    this.settings = settings;
-  }
-
-  void execute(Referentials referentials, Database db) {
-    Progress progress = new Progress(referentials.totalViolations());
-
-    List<Callable<Object>> converters = Lists.newArrayList();
-    for (int i = 0; i < numberOfThreads(); i++) {
-      converters.add(new ViolationConverter(referentials, db, progress));
-    }
-
-    doExecute(progress, converters);
-  }
-
-  void doExecute(TimerTask progress, List<Callable<Object>> converters) {
-    Timer timer = new Timer(Progress.THREAD_NAME);
-    timer.schedule(progress, Progress.DELAY_MS, Progress.DELAY_MS);
-    try {
-      ExecutorService executor = Executors.newFixedThreadPool(converters.size());
-      List<Future<Object>> results = executor.invokeAll(converters);
-      executor.shutdown();
-      for (Future result : results) {
-        result.get();
-      }
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to start migration threads", e);
-    } finally {
-      progress.cancel();
-      timer.cancel();
-      timer.purge();
-    }
-  }
-
-  int numberOfThreads() {
-    int threads = settings.getInt(THREADS_PROPERTY);
-    if (threads < 0) {
-      throw new IllegalArgumentException(String.format("Bad value of %s: %d", THREADS_PROPERTY, threads));
-    }
-    if (threads == 0) {
-      threads = DEFAULT_THREADS;
-    }
-    return threads;
-  }
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/violation/ViolationMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/violation/ViolationMigration.java
deleted file mode 100644 (file)
index d534b01..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.violation;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.config.Settings;
-import org.sonar.api.utils.MessageException;
-import org.sonar.core.persistence.Database;
-import org.sonar.server.db.migrations.DatabaseMigration;
-import org.sonar.server.db.migrations.SqlUtil;
-
-import java.sql.SQLException;
-
-/**
- * Used in the Active Record Migration 401
- */
-public class ViolationMigration implements DatabaseMigration {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(ViolationMigration.class);
-
-  private static final String FAILURE_MESSAGE = "Fail to convert violations to issues";
-
-  private final Settings settings;
-  private final Database db;
-
-  public ViolationMigration(Database database, Settings settings) {
-    this.db = database;
-    this.settings = settings;
-  }
-
-  @Override
-  public void execute() {
-    try {
-      LOGGER.info("Initialize input");
-      Referentials referentials = new Referentials(db);
-      if (referentials.totalViolations() > 0) {
-        LOGGER.info("Migrate {} violations", referentials.totalViolations());
-        ViolationConverters converters = new ViolationConverters(settings);
-        converters.execute(referentials, db);
-      }
-    } catch (SQLException e) {
-      LOGGER.error(FAILURE_MESSAGE, e);
-      SqlUtil.log(LOGGER, e);
-      throw MessageException.of(FAILURE_MESSAGE);
-
-    } catch (Exception e) {
-      LOGGER.error(FAILURE_MESSAGE, e);
-      throw MessageException.of(FAILURE_MESSAGE);
-    }
-  }
-
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/violation/package-info.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/violation/package-info.java
deleted file mode 100644 (file)
index 969ef6e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-@ParametersAreNonnullByDefault
-package org.sonar.server.db.migrations.violation;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/Progress.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/Progress.java
new file mode 100644 (file)
index 0000000..e89ad01
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.violation36;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.TimerTask;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * This task logs every minute the status of migration. It is destroyed
+ * when migration is finished.
+ */
+class Progress extends TimerTask {
+
+  static final String THREAD_NAME = "Violation Migration Progress";
+  static final long DELAY_MS = 60000L;
+
+  private final AtomicLong counter = new AtomicLong(0L);
+  private final Logger logger;
+  private final long totalViolations;
+  private final long start;
+
+  Progress(long totalViolations, Logger logger, long startDate) {
+    this.totalViolations = totalViolations;
+    this.logger = logger;
+    this.start = startDate;
+  }
+
+  Progress(long totalViolations) {
+    this(totalViolations, LoggerFactory.getLogger(Progress.class), System.currentTimeMillis());
+  }
+
+  void increment(int delta) {
+    counter.addAndGet(delta);
+  }
+
+  @Override
+  public void run() {
+    long totalIssues = counter.get();
+    long durationMinutes = (System.currentTimeMillis() - start) / 60000L;
+    int percents = (int) ((100L * totalIssues) / totalViolations);
+    if (totalIssues > 0 && durationMinutes > 0) {
+      int frequency = (int) (totalIssues / durationMinutes);
+      long remaining = (totalViolations - totalIssues) / frequency;
+      logger.info(String.format(
+        "%d%% [%d/%d violations, %d minutes remaining]", percents, totalIssues, totalViolations, remaining)
+      );
+    } else {
+      logger.info(String.format("%d%% [%d/%d violations]", percents, totalIssues, totalViolations));
+    }
+
+  }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/Referentials.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/Referentials.java
new file mode 100644 (file)
index 0000000..76e3c19
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.violation36;
+
+import com.google.common.collect.Maps;
+import org.apache.commons.dbutils.DbUtils;
+import org.apache.commons.dbutils.QueryRunner;
+import org.apache.commons.dbutils.ResultSetHandler;
+import org.sonar.core.persistence.Database;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * Data loaded from database before migrating violations. It is
+ * shared amongst converter parallel tasks.
+ */
+class Referentials {
+
+  static final int VIOLATION_GROUP_SIZE = 1000;
+
+  private final Map<Long, String> loginsByUserId;
+  private final Map<Long, String> plansById;
+  private final Queue<long[]> groupsOfViolationIds;
+  private long totalViolations = 0L;
+
+  Referentials(Database database) throws SQLException {
+    loginsByUserId = selectLongString(database, "select id,login from users");
+    plansById = selectLongString(database, "select id,kee from action_plans");
+    groupsOfViolationIds = initGroupOfViolationIds(database);
+  }
+
+  @CheckForNull
+  String actionPlan(@Nullable Long id) {
+    return id != null ? plansById.get(id) : null;
+  }
+
+  @CheckForNull
+  String userLogin(@Nullable Long id) {
+    return id != null ? loginsByUserId.get(id) : null;
+  }
+
+  long totalViolations() {
+    return totalViolations;
+  }
+
+  Long[] pollGroupOfViolationIds() {
+    long[] longs = groupsOfViolationIds.poll();
+    if (longs == null) {
+      return new Long[0];
+    }
+    Long[] objects = new Long[longs.length];
+    for (int i = 0; i < longs.length; i++) {
+      objects[i] = Long.valueOf(longs[i]);
+    }
+    return objects;
+  }
+
+  private Map<Long, String> selectLongString(Database database, String sql) throws SQLException {
+    Connection connection = database.getDataSource().getConnection();
+    try {
+      return new QueryRunner().query(connection, sql, new ResultSetHandler<Map<Long, String>>() {
+        @Override
+        public Map<Long, String> handle(ResultSet rs) throws SQLException {
+          Map<Long, String> map = Maps.newHashMap();
+          while (rs.next()) {
+            map.put(rs.getLong(1), rs.getString(2));
+          }
+          return map;
+        }
+      });
+    } finally {
+      DbUtils.closeQuietly(connection);
+    }
+  }
+
+  private Queue<long[]> initGroupOfViolationIds(Database database) throws SQLException {
+    Connection connection = database.getDataSource().getConnection();
+    Statement stmt = null;
+    ResultSet rs = null;
+    try {
+      connection.setAutoCommit(false);
+      stmt = connection.createStatement();
+      stmt.setFetchSize(10000);
+      rs = stmt.executeQuery("select id from rule_failures");
+      ConcurrentLinkedQueue<long[]> queue = new ConcurrentLinkedQueue<long[]>();
+
+      totalViolations = 0;
+      long[] block = new long[VIOLATION_GROUP_SIZE];
+      int cursor = 0;
+      while (rs.next()) {
+        block[cursor] = rs.getLong(1);
+        cursor++;
+        totalViolations++;
+        if (cursor == VIOLATION_GROUP_SIZE) {
+          queue.add(block);
+          block = new long[VIOLATION_GROUP_SIZE];
+          cursor = 0;
+        }
+      }
+      if (cursor > 0) {
+        queue.add(block);
+      }
+      return queue;
+    } finally {
+      DbUtils.closeQuietly(connection, stmt, rs);
+    }
+  }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/ViolationConverter.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/ViolationConverter.java
new file mode 100644 (file)
index 0000000..33a071c
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.violation36;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.apache.commons.dbutils.DbUtils;
+import org.apache.commons.dbutils.QueryRunner;
+import org.apache.commons.dbutils.handlers.AbstractListHandler;
+import org.sonar.api.rule.Severity;
+import org.sonar.core.persistence.Database;
+import org.sonar.server.db.migrations.SqlUtil;
+
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+
+class ViolationConverter implements Callable<Object> {
+
+  private static final long ONE_YEAR = 365L * 24 * 60 * 60 * 1000;
+  private static final Date ONE_YEAR_AGO = new Date(System.currentTimeMillis() - ONE_YEAR);
+
+  private static final String PROJECT_ID = "projectId";
+  private static final String CREATED_AT = "createdAt";
+  private static final String REVIEW_ID = "reviewId";
+  private static final String SEVERITY = "severity";
+  private static final String REVIEW_STATUS = "reviewStatus";
+  private static final String REVIEW_MANUAL_SEVERITY = "reviewManualSeverity";
+  private static final String REVIEW_SEVERITY = "reviewSeverity";
+  private static final String REVIEW_UPDATED_AT = "reviewUpdatedAt";
+  private static final String ROOT_PROJECT_ID = "rootProjectId";
+  private static final String RULE_ID = "ruleId";
+  private static final String MESSAGE = "message";
+  private static final String LINE = "line";
+  private static final String COST = "cost";
+  private static final String CHECKSUM = "checksum";
+  private static final String REVIEW_RESOLUTION = "reviewResolution";
+  private static final String REVIEW_REPORTER_ID = "reviewReporterId";
+  private static final String REVIEW_ASSIGNEE_ID = "reviewAssigneeId";
+  private static final String REVIEW_DATA = "reviewData";
+  private static final String REVIEW_MANUAL_VIOLATION = "reviewManualViolation";
+  private static final String PLAN_ID = "planId";
+  private static final String ISSUE_KEY = "issueKey";
+  private static final String STATUS_OPEN = "OPEN";
+  private static final String STATUS_CONFIRMED = "CONFIRMED";
+  private static final String UPDATED_AT = "updatedAt";
+  private static final String REVIEW_TEXT = "reviewText";
+  private static final String USER_ID = "userId";
+  private static final String SEVERITY_MAJOR = "MAJOR";
+
+
+  private static final String SQL_ISSUE_COLUMNS = "kee, component_id, root_component_id, rule_id, severity, manual_severity, message, line, effort_to_fix, status, resolution, " +
+    "checksum, reporter, assignee, action_plan_key, issue_attributes, issue_creation_date, issue_update_date, created_at, updated_at";
+
+  private static final String SQL_INSERT_ISSUE = "INSERT INTO issues(" + SQL_ISSUE_COLUMNS + ")" +
+    " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+
+  private static final String SQL_INSERT_ISSUE_CHANGE = "INSERT INTO issue_changes(kee, issue_key, user_login, change_type, change_data, created_at, updated_at)" +
+    " VALUES (?, ?, ?, 'comment', ?, ?, ?)";
+
+  private static final String SQL_DELETE_RULE_FAILURES;
+
+  static {
+    StringBuilder sb = new StringBuilder("delete from rule_failures where ");
+    for (int i = 0; i < Referentials.VIOLATION_GROUP_SIZE; i++) {
+      if (i > 0) {
+        sb.append(" or ");
+      }
+      sb.append("id=?");
+    }
+    SQL_DELETE_RULE_FAILURES = sb.toString();
+  }
+
+  static final String SQL_SELECT_RULE_FAILURES;
+
+  static {
+    StringBuilder sb = new StringBuilder("select rev.id as reviewId, s.project_id as projectId, rf.rule_id as ruleId, " +
+      "  rf.failure_level as failureLevel, rf.message as message, rf.line as line, " +
+      "  rf.cost as cost, rf.created_at as createdAt, rf.checksum as checksum, rev.user_id as reviewReporterId, " +
+      "  rev.assignee_id as reviewAssigneeId, rev.status as reviewStatus, " +
+      "  rev.severity as reviewSeverity, rev.resolution as reviewResolution, rev.manual_severity as reviewManualSeverity, " +
+      "  rev.data as reviewData, rev.updated_at as reviewUpdatedAt, " +
+      "  s.root_project_id as rootProjectId, rev.manual_violation as reviewManualViolation, planreviews.action_plan_id as planId " +
+      " from rule_failures rf " +
+      " inner join snapshots s on s.id=rf.snapshot_id " +
+      " left join reviews rev on rev.rule_failure_permanent_id=rf.permanent_id " +
+      " left join action_plans_reviews planreviews on planreviews.review_id=rev.id " +
+      " where ");
+    for (int i = 0; i < Referentials.VIOLATION_GROUP_SIZE; i++) {
+      if (i > 0) {
+        sb.append(" or ");
+      }
+      sb.append("rf.id=?");
+    }
+    SQL_SELECT_RULE_FAILURES = sb.toString();
+  }
+
+  private final Database db;
+  private final Referentials referentials;
+  private final Progress progress;
+
+  ViolationConverter(Referentials referentials, Database db, Progress progress) {
+    this.referentials = referentials;
+    this.db = db;
+    this.progress = progress;
+  }
+
+  @Override
+  public Object call() throws SQLException {
+    // For each group of 1000 violation ids:
+    // - load related violations, reviews and action plans
+    // - in a transaction
+    //   -- insert issues
+    //   -- insert issue_changes if there are review comments
+    //   -- delete violations
+
+    Long[] violationIds = referentials.pollGroupOfViolationIds();
+    while (violationIds.length>0) {
+      List<Map<String, Object>> rows = selectRows(violationIds);
+      convert(rows, violationIds);
+
+      violationIds = referentials.pollGroupOfViolationIds();
+    }
+    return null;
+  }
+
+  private List<Map<String, Object>> selectRows(Long[] violationIds) throws SQLException {
+    Connection readConnection = null;
+    try {
+      readConnection = db.getDataSource().getConnection();
+      ViolationHandler violationHandler = new ViolationHandler();
+      return new QueryRunner().query(readConnection, SQL_SELECT_RULE_FAILURES, violationHandler, violationIds);
+
+    } finally {
+      DbUtils.closeQuietly(readConnection);
+    }
+  }
+
+  private void convert(List<Map<String, Object>> rows, Long[] violationIds) throws SQLException {
+    Connection readConnection = null;
+    Connection writeConnection = null;
+    try {
+      readConnection = db.getDataSource().getConnection();
+      writeConnection = db.getDataSource().getConnection();
+      writeConnection.setAutoCommit(false);
+
+      List<Object[]> allParams = Lists.newArrayList();
+      List<Map<String, Object>> allComments = Lists.newArrayList();
+
+      QueryRunner runner = new QueryRunner();
+      for (Map<String, Object> row : rows) {
+        Long componentId = (Long) row.get(PROJECT_ID);
+        if (componentId == null) {
+          continue;
+        }
+        String issueKey = UUID.randomUUID().toString();
+        String status, severity, reporter = null;
+        boolean manualSeverity;
+        Object createdAt = Objects.firstNonNull(row.get(CREATED_AT), ONE_YEAR_AGO);
+        Object updatedAt;
+        Long reviewId = (Long) row.get(REVIEW_ID);
+        if (reviewId == null) {
+          // violation without review
+          status = STATUS_OPEN;
+          manualSeverity = false;
+          severity = (String) row.get(SEVERITY);
+          updatedAt = createdAt;
+        } else {
+          // violation + review
+          String reviewStatus = (String) row.get(REVIEW_STATUS);
+          status = (STATUS_OPEN.equals(reviewStatus) ? STATUS_CONFIRMED : reviewStatus);
+          manualSeverity = Objects.firstNonNull((Boolean) row.get(REVIEW_MANUAL_SEVERITY), false);
+          severity = (String) row.get(REVIEW_SEVERITY);
+          updatedAt = Objects.firstNonNull(row.get(REVIEW_UPDATED_AT), ONE_YEAR_AGO);
+          if ((Boolean) row.get(REVIEW_MANUAL_VIOLATION)) {
+            reporter = referentials.userLogin((Long) row.get(REVIEW_REPORTER_ID));
+          }
+
+          List<Map<String, Object>> comments = runner.query(readConnection, ReviewCommentsHandler.SQL + reviewId, new ReviewCommentsHandler());
+          for (Map<String, Object> comment : comments) {
+            comment.put(ISSUE_KEY, issueKey);
+            allComments.add(comment);
+          }
+        }
+        Object[] params = new Object[20];
+        params[0] = issueKey;
+        params[1] = componentId;
+        params[2] = row.get(ROOT_PROJECT_ID);
+        params[3] = row.get(RULE_ID);
+        params[4] = severity;
+        params[5] = manualSeverity;
+        params[6] = row.get(MESSAGE);
+        params[7] = row.get(LINE);
+        params[8] = row.get(COST);
+        params[9] = status;
+        params[10] = row.get(REVIEW_RESOLUTION);
+        params[11] = row.get(CHECKSUM);
+        params[12] = reporter;
+        params[13] = referentials.userLogin((Long) row.get(REVIEW_ASSIGNEE_ID));
+        params[14] = referentials.actionPlan((Long) row.get(PLAN_ID));
+        params[15] = row.get(REVIEW_DATA);
+        params[16] = createdAt;
+        params[17] = updatedAt;
+        params[18] = createdAt;
+        params[19] = updatedAt;
+        allParams.add(params);
+      }
+      runner.batch(writeConnection, SQL_INSERT_ISSUE, allParams.toArray(new Object[allParams.size()][]));
+      insertComments(writeConnection, allComments);
+      runner.update(writeConnection, SQL_DELETE_RULE_FAILURES, violationIds);
+      writeConnection.commit();
+      progress.increment(rows.size());
+
+    } finally {
+      DbUtils.closeQuietly(readConnection);
+      DbUtils.closeQuietly(writeConnection);
+    }
+  }
+
+  private void insertComments(Connection writeConnection, List<Map<String, Object>> comments) throws SQLException {
+    List<Object[]> allParams = Lists.newArrayList();
+
+    for (Map<String, Object> comment : comments) {
+      String login = referentials.userLogin((Long) comment.get(USER_ID));
+      if (login != null) {
+        Object[] params = new Object[6];
+        params[0] = UUID.randomUUID().toString();
+        params[1] = comment.get(ISSUE_KEY);
+        params[2] = login;
+        params[3] = comment.get(REVIEW_TEXT);
+        params[4] = comment.get(CREATED_AT);
+        params[5] = comment.get(UPDATED_AT);
+        allParams.add(params);
+      }
+    }
+    if (!allParams.isEmpty()) {
+      new QueryRunner().batch(writeConnection, SQL_INSERT_ISSUE_CHANGE, allParams.toArray(new Object[allParams.size()][]));
+    }
+  }
+
+
+  private static class ReviewCommentsHandler extends AbstractListHandler<Map<String, Object>> {
+    static final String SQL = "select created_at as createdAt, updated_at as updatedAt, user_id as userId, review_text as reviewText from review_comments where review_id=";
+
+    @Override
+    protected Map<String, Object> handleRow(ResultSet rs) throws SQLException {
+      Map<String, Object> map = Maps.newHashMap();
+      map.put(CREATED_AT, rs.getTimestamp(CREATED_AT));
+      map.put(UPDATED_AT, rs.getTimestamp(UPDATED_AT));
+      map.put(USER_ID, SqlUtil.getLong(rs, USER_ID));
+      map.put(REVIEW_TEXT, rs.getString(REVIEW_TEXT));
+      return map;
+    }
+  }
+
+  private static class ViolationHandler extends AbstractListHandler<Map<String, Object>> {
+    private static final Map<Integer, String> SEVERITIES = ImmutableMap.of(0, Severity.INFO, 1, Severity.MINOR, 2, Severity.MAJOR, 3, Severity.CRITICAL, 4, Severity.BLOCKER);
+
+
+    @Override
+    protected Map<String, Object> handleRow(ResultSet rs) throws SQLException {
+      Map<String, Object> map = Maps.newHashMap();
+      map.put(REVIEW_ID, SqlUtil.getLong(rs, REVIEW_ID));
+      map.put(PROJECT_ID, SqlUtil.getLong(rs, PROJECT_ID));
+      map.put(ROOT_PROJECT_ID, SqlUtil.getLong(rs, ROOT_PROJECT_ID));
+      map.put(RULE_ID, SqlUtil.getLong(rs, RULE_ID));
+      map.put(SEVERITY, Objects.firstNonNull(SEVERITIES.get(SqlUtil.getInt(rs, "failureLevel")), SEVERITY_MAJOR));
+      map.put(MESSAGE, rs.getString(MESSAGE));
+      map.put(LINE, SqlUtil.getInt(rs, LINE));
+      map.put(COST, SqlUtil.getDouble(rs, COST));
+      map.put(CHECKSUM, rs.getString(CHECKSUM));
+      map.put(CREATED_AT, rs.getTimestamp(CREATED_AT));
+      map.put(REVIEW_RESOLUTION, rs.getString(REVIEW_RESOLUTION));
+      map.put(REVIEW_SEVERITY, Objects.firstNonNull(rs.getString(REVIEW_SEVERITY), SEVERITY_MAJOR));
+      map.put(REVIEW_STATUS, rs.getString(REVIEW_STATUS));
+      map.put(REVIEW_REPORTER_ID, SqlUtil.getLong(rs, REVIEW_REPORTER_ID));
+      map.put(REVIEW_ASSIGNEE_ID, SqlUtil.getLong(rs, REVIEW_ASSIGNEE_ID));
+      map.put(REVIEW_DATA, rs.getString(REVIEW_DATA));
+      map.put(REVIEW_MANUAL_SEVERITY, rs.getBoolean(REVIEW_MANUAL_SEVERITY));
+      map.put(REVIEW_UPDATED_AT, rs.getTimestamp(REVIEW_UPDATED_AT));
+      map.put(REVIEW_MANUAL_VIOLATION, rs.getBoolean(REVIEW_MANUAL_VIOLATION));
+      map.put(PLAN_ID, SqlUtil.getLong(rs, PLAN_ID));
+      return map;
+    }
+  }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/ViolationConverters.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/ViolationConverters.java
new file mode 100644 (file)
index 0000000..bc9627b
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.violation36;
+
+import com.google.common.collect.Lists;
+import org.sonar.api.config.Settings;
+import org.sonar.core.persistence.Database;
+
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+class ViolationConverters {
+
+  static final int DEFAULT_THREADS = 5;
+  static final String THREADS_PROPERTY = "sonar.violationMigration.threads";
+  private final Settings settings;
+
+  ViolationConverters(Settings settings) {
+    this.settings = settings;
+  }
+
+  void execute(Referentials referentials, Database db) {
+    Progress progress = new Progress(referentials.totalViolations());
+
+    List<Callable<Object>> converters = Lists.newArrayList();
+    for (int i = 0; i < numberOfThreads(); i++) {
+      converters.add(new ViolationConverter(referentials, db, progress));
+    }
+
+    doExecute(progress, converters);
+  }
+
+  void doExecute(TimerTask progress, List<Callable<Object>> converters) {
+    Timer timer = new Timer(Progress.THREAD_NAME);
+    timer.schedule(progress, Progress.DELAY_MS, Progress.DELAY_MS);
+    try {
+      ExecutorService executor = Executors.newFixedThreadPool(converters.size());
+      List<Future<Object>> results = executor.invokeAll(converters);
+      executor.shutdown();
+      for (Future result : results) {
+        result.get();
+      }
+    } catch (Exception e) {
+      throw new IllegalStateException("Fail to start migration threads", e);
+    } finally {
+      progress.cancel();
+      timer.cancel();
+      timer.purge();
+    }
+  }
+
+  int numberOfThreads() {
+    int threads = settings.getInt(THREADS_PROPERTY);
+    if (threads < 0) {
+      throw new IllegalArgumentException(String.format("Bad value of %s: %d", THREADS_PROPERTY, threads));
+    }
+    if (threads == 0) {
+      threads = DEFAULT_THREADS;
+    }
+    return threads;
+  }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/ViolationMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/ViolationMigration.java
new file mode 100644 (file)
index 0000000..4dd6a20
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.violation36;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.MessageException;
+import org.sonar.core.persistence.Database;
+import org.sonar.server.db.migrations.DatabaseMigration;
+import org.sonar.server.db.migrations.SqlUtil;
+
+import java.sql.SQLException;
+
+/**
+ * Used in the Active Record Migration 401
+ */
+public class ViolationMigration implements DatabaseMigration {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(ViolationMigration.class);
+
+  private static final String FAILURE_MESSAGE = "Fail to convert violations to issues";
+
+  private final Settings settings;
+  private final Database db;
+
+  public ViolationMigration(Database database, Settings settings) {
+    this.db = database;
+    this.settings = settings;
+  }
+
+  @Override
+  public void execute() {
+    try {
+      LOGGER.info("Initialize input");
+      Referentials referentials = new Referentials(db);
+      if (referentials.totalViolations() > 0) {
+        LOGGER.info("Migrate {} violations", referentials.totalViolations());
+        ViolationConverters converters = new ViolationConverters(settings);
+        converters.execute(referentials, db);
+      }
+    } catch (SQLException e) {
+      LOGGER.error(FAILURE_MESSAGE, e);
+      SqlUtil.log(LOGGER, e);
+      throw MessageException.of(FAILURE_MESSAGE);
+
+    } catch (Exception e) {
+      LOGGER.error(FAILURE_MESSAGE, e);
+      throw MessageException.of(FAILURE_MESSAGE);
+    }
+  }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/package-info.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/violation36/package-info.java
new file mode 100644 (file)
index 0000000..e3f6d5e
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.server.db.migrations.violation36;
+
+import javax.annotation.ParametersAreNonnullByDefault;
index 4d05132ced825c8e4c43d3574ec29548f915fec1..99082a59c9ac4cd1c7b85c6119a68bacc42ba4fe 100644 (file)
@@ -34,7 +34,7 @@ class Issue
     hash[:message] = issue.message if issue.message
     hash[:line] = issue.line.to_i if issue.line
     hash[:effortToFix] = issue.effortToFix.to_f if issue.effortToFix
-    hash[:debt] = Internal.durations.encode(issue.debt) if issue.debt
+    hash[:debt43] = Internal.durations.encode(issue.debt) if issue.debt
     hash[:reporter] = issue.reporter if issue.reporter
     hash[:assignee] = issue.assignee if issue.assignee
     hash[:author] = issue.authorLogin if issue.authorLogin
index 7b7f0301572f78e8495141ef0a91d6c157473213..1251948f574cd0a6f83394dbd075f003dc0eaec5 100644 (file)
@@ -32,7 +32,7 @@ class MigrateViolationsToIssues < ActiveRecord::Migration
     # Required for MSSQL to unlock the table RULE_FAILURES
     ActiveRecord::Base.connection.commit_db_transaction
 
-    Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.violation.ViolationMigration')
+    Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.violation36.ViolationMigration')
 
     # Currently not possible in Java because of Oracle (triggers and sequences must be dropped)
     drop_table('rule_failures')
index 8c2bc9aab70188b931b8acf30ab2921295fb03af..6f49643fe5faaab8136fd7ea682d01e5289124dc 100644 (file)
@@ -25,6 +25,6 @@
 class UpdateIssueDebtToMinutes < ActiveRecord::Migration
 
   def self.up
-    Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.debt.IssueMigration')
+    Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.debt43.IssueMigration')
   end
 end
index 6ca54b8adde3f5a49352ea6d26694bd776e9c6cc..368bed888d768c12c9f7d248aef3ab181f801e98 100644 (file)
@@ -25,6 +25,6 @@
 class UpdateIssueChangelogDebtToMinutes < ActiveRecord::Migration
 
   def self.up
-    Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.debt.IssueChangelogMigration')
+    Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.debt43.IssueChangelogMigration')
   end
 end
index e3edd5ec3f4f21addd5359a0148c89def6bac055..bdc205655ffc7560954966d5cd9f37ade7b7a71c 100644 (file)
@@ -25,6 +25,6 @@
 class UpdateMeasuresDebtToMinutes < ActiveRecord::Migration
 
   def self.up
-    Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.debt.TechnicalDebtMeasuresMigration')
+    Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.debt43.TechnicalDebtMeasuresMigration')
   end
 end
index 1997feda9829787aaec11f204a09a6e60492d2c4..790ff5e7ea68cc9f0b8d37214258f149b9f1cc02 100644 (file)
@@ -25,6 +25,6 @@
 class UpdateDevelopmentCostToMinutes < ActiveRecord::Migration
 
   def self.up
-    Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.debt.DevelopmentCostMeasuresMigration')
+    Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.debt43.DevelopmentCostMeasuresMigration')
   end
 end
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DebtMigrationExecutorTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DebtMigrationExecutorTest.java
deleted file mode 100644 (file)
index 38570d9..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.debt;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.config.Settings;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
-
-public class DebtMigrationExecutorTest {
-
-  static final int HOURS_IN_DAY = 8;
-
-  static final Long ONE_MINUTE = 1L;
-  static final Long ONE_HOUR_IN_MINUTES = ONE_MINUTE * 60;
-  static final Long ONE_DAY_IN_MINUTES = ONE_HOUR_IN_MINUTES * HOURS_IN_DAY;
-
-  Settings settings = new Settings();
-
-  WorkDurationConvertor convertor;
-
-  @Before
-  public void setUp() throws Exception {
-    convertor = new WorkDurationConvertor(settings);
-  }
-
-  @Test
-  public void convert_from_long() throws Exception {
-    settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, HOURS_IN_DAY);
-
-    assertThat(convertor.createFromLong(1)).isEqualTo(ONE_MINUTE);
-    assertThat(convertor.createFromLong(100)).isEqualTo(ONE_HOUR_IN_MINUTES);
-    assertThat(convertor.createFromLong(10000)).isEqualTo(ONE_DAY_IN_MINUTES);
-    assertThat(convertor.createFromLong(10101)).isEqualTo(ONE_DAY_IN_MINUTES + ONE_HOUR_IN_MINUTES + ONE_MINUTE);
-  }
-
-  @Test
-  public void convert_from_long_use_default_value_for_hours_in_day_when_no_property() throws Exception {
-    assertThat(convertor.createFromLong(1)).isEqualTo(ONE_MINUTE);
-  }
-
-  @Test
-  public void fail_convert_from_long_on_bad_hours_in_day_property() throws Exception {
-    try {
-      settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, -2);
-      convertor.createFromLong(1);
-      fail();
-    } catch (Exception e) {
-      assertThat(e).isInstanceOf(IllegalArgumentException.class);
-    }
-  }
-
-  @Test
-  public void convert_from_days() throws Exception {
-    settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, HOURS_IN_DAY);
-
-    assertThat(convertor.createFromDays(1.0)).isEqualTo(ONE_DAY_IN_MINUTES);
-    assertThat(convertor.createFromDays(0.1)).isEqualTo(48L);
-
-    // Should be 4.8 but as it's a long it's truncated after comma
-    assertThat(convertor.createFromDays(0.01)).isEqualTo(4L);
-  }
-
-}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigrationTest.java
deleted file mode 100644 (file)
index 259940f..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.debt;
-
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.config.Settings;
-import org.sonar.core.persistence.TestDatabase;
-
-@RunWith(MockitoJUnitRunner.class)
-public class DevelopmentCostMeasuresMigrationTest {
-
-  @ClassRule
-  public static TestDatabase db = new TestDatabase().schema(DevelopmentCostMeasuresMigrationTest.class, "schema.sql");
-
-  Settings settings;
-
-  DevelopmentCostMeasuresMigration migration;
-
-  @Before
-  public void setUp() throws Exception {
-    settings = new Settings();
-    settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, 8);
-
-    migration = new DevelopmentCostMeasuresMigration(db.database(), settings);
-  }
-
-  @Test
-  public void migrate_dev_cost_measures() throws Exception {
-    db.prepareDbUnit(getClass(), "migrate_dev_cost_measures.xml");
-
-    migration.execute();
-
-    db.assertDbUnit(getClass(), "migrate_dev_cost_measures_result.xml", "project_measures");
-  }
-
-}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest.java
deleted file mode 100644 (file)
index 54abbb6..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.debt;
-
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.config.Settings;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.System2;
-import org.sonar.core.persistence.TestDatabase;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class IssueChangelogMigrationTest {
-
-  @ClassRule
-  public static TestDatabase db = new TestDatabase().schema(IssueChangelogMigrationTest.class, "schema.sql");
-
-  @Mock
-  System2 system2;
-
-  Settings settings;
-
-  IssueChangelogMigration migration;
-
-  @Before
-  public void setUp() throws Exception {
-    when(system2.now()).thenReturn(DateUtils.parseDate("2014-02-19").getTime());
-    settings = new Settings();
-    settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, 8);
-
-    migration = new IssueChangelogMigration(db.database(), settings, system2);
-  }
-
-  @Test
-  public void migrate_issue_changelog_debt() throws Exception {
-    db.prepareDbUnit(getClass(), "migrate_issue_changelog_debt.xml");
-
-    migration.execute();
-
-    db.assertDbUnit(getClass(), "migrate_issue_changelog_debt_result.xml", "issue_changes");
-  }
-
-  @Test
-  public void convert_data_containing_only_debt_change() throws Exception {
-    assertThat(migration.convertChangelog("technicalDebt=1|2")).isEqualTo("technicalDebt=1|2");
-    assertThat(migration.convertChangelog("technicalDebt=100|200")).isEqualTo("technicalDebt=60|120");
-    assertThat(migration.convertChangelog("technicalDebt=10000|20000")).isEqualTo("technicalDebt=480|960");
-
-    assertThat(migration.convertChangelog("technicalDebt=|2")).isEqualTo("technicalDebt=|2");
-    assertThat(migration.convertChangelog("technicalDebt=1|")).isEqualTo("technicalDebt=1|");
-  }
-
-  @Test
-  public void convert_data_beginning_with_debt_change() throws Exception {
-    assertThat(migration.convertChangelog("technicalDebt=100|200,status=RESOLVED|REOPENED")).isEqualTo("technicalDebt=60|120,status=RESOLVED|REOPENED");
-    assertThat(migration.convertChangelog("technicalDebt=|200,status=RESOLVED|REOPENED")).isEqualTo("technicalDebt=|120,status=RESOLVED|REOPENED");
-    assertThat(migration.convertChangelog("technicalDebt=100|,status=RESOLVED|REOPENED")).isEqualTo("technicalDebt=60|,status=RESOLVED|REOPENED");
-  }
-
-  @Test
-  public void convert_data_finishing_with_debt_change() throws Exception {
-    assertThat(migration.convertChangelog("status=RESOLVED|REOPENED,technicalDebt=100|200")).isEqualTo("status=RESOLVED|REOPENED,technicalDebt=60|120");
-    assertThat(migration.convertChangelog("status=RESOLVED|REOPENED,technicalDebt=|200")).isEqualTo("status=RESOLVED|REOPENED,technicalDebt=|120");
-    assertThat(migration.convertChangelog("status=RESOLVED|REOPENED,technicalDebt=100|")).isEqualTo("status=RESOLVED|REOPENED,technicalDebt=60|");
-  }
-
-  @Test
-  public void convert_data_with_debt_change_in_the_middle() throws Exception {
-    assertThat(migration.convertChangelog("status=RESOLVED|REOPENED,technicalDebt=100|200,resolution=")).isEqualTo("status=RESOLVED|REOPENED,technicalDebt=60|120,resolution=");
-    assertThat(migration.convertChangelog("status=RESOLVED|REOPENED,technicalDebt=|200,resolution=")).isEqualTo("status=RESOLVED|REOPENED,technicalDebt=|120,resolution=");
-    assertThat(migration.convertChangelog("status=RESOLVED|REOPENED,technicalDebt=100|,resolution=")).isEqualTo("status=RESOLVED|REOPENED,technicalDebt=60|,resolution=");
-  }
-}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueMigrationTest.java
deleted file mode 100644 (file)
index 9b6cb1c..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.debt;
-
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.config.Settings;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.System2;
-import org.sonar.core.persistence.TestDatabase;
-
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class IssueMigrationTest {
-
-  @ClassRule
-  public static TestDatabase db = new TestDatabase().schema(IssueMigrationTest.class, "schema.sql");
-
-  @Mock
-  System2 system2;
-
-  Settings settings;
-
-  IssueMigration migration;
-
-  @Before
-  public void setUp() throws Exception {
-    when(system2.now()).thenReturn(DateUtils.parseDate("2014-02-19").getTime());
-    settings = new Settings();
-    settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, 8);
-
-    migration = new IssueMigration(db.database(), settings, system2);
-  }
-
-  @Test
-  public void migrate_issues_debt() throws Exception {
-    db.prepareDbUnit(getClass(), "migrate_issues_debt.xml");
-
-    migration.execute();
-
-    db.assertDbUnit(getClass(), "migrate_issues_debt_result.xml", "issues");
-  }
-
-}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest.java
deleted file mode 100644 (file)
index 4d68b3a..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.debt;
-
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.config.Settings;
-import org.sonar.core.persistence.TestDatabase;
-
-@RunWith(MockitoJUnitRunner.class)
-public class TechnicalDebtMeasuresMigrationTest {
-
-  @ClassRule
-  public static TestDatabase db = new TestDatabase().schema(TechnicalDebtMeasuresMigrationTest.class, "schema.sql");
-
-  Settings settings;
-
-  TechnicalDebtMeasuresMigration migration;
-
-  @Before
-  public void setUp() throws Exception {
-    settings = new Settings();
-    settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, 8);
-
-    migration = new TechnicalDebtMeasuresMigration(db.database(), settings);
-  }
-
-  @Test
-  public void migrate_technical_debt_measures() throws Exception {
-    db.prepareDbUnit(getClass(), "migrate_technical_debt_measures.xml");
-
-    migration.execute();
-
-    db.assertDbUnit(getClass(), "migrate_technical_debt_measures_result.xml", "project_measures");
-  }
-
-  @Test
-  public void migrate_added_technical_debt_measures() throws Exception {
-    db.prepareDbUnit(getClass(), "migrate_new_technical_debt_measures.xml");
-
-    migration.execute();
-
-    db.assertDbUnit(getClass(), "migrate_new_technical_debt_measures_result.xml", "project_measures");
-  }
-
-  @Test
-  public void migrate_sqale_measures() throws Exception {
-    db.prepareDbUnit(getClass(), "migrate_sqale_measures.xml");
-
-    migration.execute();
-
-    db.assertDbUnit(getClass(), "migrate_sqale_measures_result.xml", "project_measures");
-  }
-
-}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/DebtMigrationExecutorTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/DebtMigrationExecutorTest.java
new file mode 100644 (file)
index 0000000..bea16d4
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.debt43;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.server.db.migrations.debt43.WorkDurationConvertor;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class DebtMigrationExecutorTest {
+
+  static final int HOURS_IN_DAY = 8;
+
+  static final Long ONE_MINUTE = 1L;
+  static final Long ONE_HOUR_IN_MINUTES = ONE_MINUTE * 60;
+  static final Long ONE_DAY_IN_MINUTES = ONE_HOUR_IN_MINUTES * HOURS_IN_DAY;
+
+  Settings settings = new Settings();
+
+  WorkDurationConvertor convertor;
+
+  @Before
+  public void setUp() throws Exception {
+    convertor = new WorkDurationConvertor(settings);
+  }
+
+  @Test
+  public void convert_from_long() throws Exception {
+    settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, HOURS_IN_DAY);
+
+    assertThat(convertor.createFromLong(1)).isEqualTo(ONE_MINUTE);
+    assertThat(convertor.createFromLong(100)).isEqualTo(ONE_HOUR_IN_MINUTES);
+    assertThat(convertor.createFromLong(10000)).isEqualTo(ONE_DAY_IN_MINUTES);
+    assertThat(convertor.createFromLong(10101)).isEqualTo(ONE_DAY_IN_MINUTES + ONE_HOUR_IN_MINUTES + ONE_MINUTE);
+  }
+
+  @Test
+  public void convert_from_long_use_default_value_for_hours_in_day_when_no_property() throws Exception {
+    assertThat(convertor.createFromLong(1)).isEqualTo(ONE_MINUTE);
+  }
+
+  @Test
+  public void fail_convert_from_long_on_bad_hours_in_day_property() throws Exception {
+    try {
+      settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, -2);
+      convertor.createFromLong(1);
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalArgumentException.class);
+    }
+  }
+
+  @Test
+  public void convert_from_days() throws Exception {
+    settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, HOURS_IN_DAY);
+
+    assertThat(convertor.createFromDays(1.0)).isEqualTo(ONE_DAY_IN_MINUTES);
+    assertThat(convertor.createFromDays(0.1)).isEqualTo(48L);
+
+    // Should be 4.8 but as it's a long it's truncated after comma
+    assertThat(convertor.createFromDays(0.01)).isEqualTo(4L);
+  }
+
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigrationTest.java
new file mode 100644 (file)
index 0000000..89d767b
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.debt43;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.config.Settings;
+import org.sonar.core.persistence.TestDatabase;
+
+@RunWith(MockitoJUnitRunner.class)
+public class DevelopmentCostMeasuresMigrationTest {
+
+  @ClassRule
+  public static TestDatabase db = new TestDatabase().schema(DevelopmentCostMeasuresMigrationTest.class, "schema.sql");
+
+  Settings settings;
+
+  DevelopmentCostMeasuresMigration migration;
+
+  @Before
+  public void setUp() throws Exception {
+    settings = new Settings();
+    settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, 8);
+
+    migration = new DevelopmentCostMeasuresMigration(db.database(), settings);
+  }
+
+  @Test
+  public void migrate_dev_cost_measures() throws Exception {
+    db.prepareDbUnit(getClass(), "migrate_dev_cost_measures.xml");
+
+    migration.execute();
+
+    db.assertDbUnit(getClass(), "migrate_dev_cost_measures_result.xml", "project_measures");
+  }
+
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/IssueChangelogMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/IssueChangelogMigrationTest.java
new file mode 100644 (file)
index 0000000..ed4adce
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.debt43;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.TestDatabase;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class IssueChangelogMigrationTest {
+
+  @ClassRule
+  public static TestDatabase db = new TestDatabase().schema(IssueChangelogMigrationTest.class, "schema.sql");
+
+  @Mock
+  System2 system2;
+
+  Settings settings;
+
+  IssueChangelogMigration migration;
+
+  @Before
+  public void setUp() throws Exception {
+    when(system2.now()).thenReturn(DateUtils.parseDate("2014-02-19").getTime());
+    settings = new Settings();
+    settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, 8);
+
+    migration = new IssueChangelogMigration(db.database(), settings, system2);
+  }
+
+  @Test
+  public void migrate_issue_changelog_debt() throws Exception {
+    db.prepareDbUnit(getClass(), "migrate_issue_changelog_debt.xml");
+
+    migration.execute();
+
+    db.assertDbUnit(getClass(), "migrate_issue_changelog_debt_result.xml", "issue_changes");
+  }
+
+  @Test
+  public void convert_data_containing_only_debt_change() throws Exception {
+    assertThat(migration.convertChangelog("technicalDebt=1|2")).isEqualTo("technicalDebt=1|2");
+    assertThat(migration.convertChangelog("technicalDebt=100|200")).isEqualTo("technicalDebt=60|120");
+    assertThat(migration.convertChangelog("technicalDebt=10000|20000")).isEqualTo("technicalDebt=480|960");
+
+    assertThat(migration.convertChangelog("technicalDebt=|2")).isEqualTo("technicalDebt=|2");
+    assertThat(migration.convertChangelog("technicalDebt=1|")).isEqualTo("technicalDebt=1|");
+  }
+
+  @Test
+  public void convert_data_beginning_with_debt_change() throws Exception {
+    assertThat(migration.convertChangelog("technicalDebt=100|200,status=RESOLVED|REOPENED")).isEqualTo("technicalDebt=60|120,status=RESOLVED|REOPENED");
+    assertThat(migration.convertChangelog("technicalDebt=|200,status=RESOLVED|REOPENED")).isEqualTo("technicalDebt=|120,status=RESOLVED|REOPENED");
+    assertThat(migration.convertChangelog("technicalDebt=100|,status=RESOLVED|REOPENED")).isEqualTo("technicalDebt=60|,status=RESOLVED|REOPENED");
+  }
+
+  @Test
+  public void convert_data_finishing_with_debt_change() throws Exception {
+    assertThat(migration.convertChangelog("status=RESOLVED|REOPENED,technicalDebt=100|200")).isEqualTo("status=RESOLVED|REOPENED,technicalDebt=60|120");
+    assertThat(migration.convertChangelog("status=RESOLVED|REOPENED,technicalDebt=|200")).isEqualTo("status=RESOLVED|REOPENED,technicalDebt=|120");
+    assertThat(migration.convertChangelog("status=RESOLVED|REOPENED,technicalDebt=100|")).isEqualTo("status=RESOLVED|REOPENED,technicalDebt=60|");
+  }
+
+  @Test
+  public void convert_data_with_debt_change_in_the_middle() throws Exception {
+    assertThat(migration.convertChangelog("status=RESOLVED|REOPENED,technicalDebt=100|200,resolution=")).isEqualTo("status=RESOLVED|REOPENED,technicalDebt=60|120,resolution=");
+    assertThat(migration.convertChangelog("status=RESOLVED|REOPENED,technicalDebt=|200,resolution=")).isEqualTo("status=RESOLVED|REOPENED,technicalDebt=|120,resolution=");
+    assertThat(migration.convertChangelog("status=RESOLVED|REOPENED,technicalDebt=100|,resolution=")).isEqualTo("status=RESOLVED|REOPENED,technicalDebt=60|,resolution=");
+  }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/IssueMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/IssueMigrationTest.java
new file mode 100644 (file)
index 0000000..6358563
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.debt43;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.TestDatabase;
+
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class IssueMigrationTest {
+
+  @ClassRule
+  public static TestDatabase db = new TestDatabase().schema(IssueMigrationTest.class, "schema.sql");
+
+  @Mock
+  System2 system2;
+
+  Settings settings;
+
+  IssueMigration migration;
+
+  @Before
+  public void setUp() throws Exception {
+    when(system2.now()).thenReturn(DateUtils.parseDate("2014-02-19").getTime());
+    settings = new Settings();
+    settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, 8);
+
+    migration = new IssueMigration(db.database(), settings, system2);
+  }
+
+  @Test
+  public void migrate_issues_debt() throws Exception {
+    db.prepareDbUnit(getClass(), "migrate_issues_debt.xml");
+
+    migration.execute();
+
+    db.assertDbUnit(getClass(), "migrate_issues_debt_result.xml", "issues");
+  }
+
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest.java
new file mode 100644 (file)
index 0000000..5c11307
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.debt43;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.config.Settings;
+import org.sonar.core.persistence.TestDatabase;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TechnicalDebtMeasuresMigrationTest {
+
+  @ClassRule
+  public static TestDatabase db = new TestDatabase().schema(TechnicalDebtMeasuresMigrationTest.class, "schema.sql");
+
+  Settings settings;
+
+  TechnicalDebtMeasuresMigration migration;
+
+  @Before
+  public void setUp() throws Exception {
+    settings = new Settings();
+    settings.setProperty(WorkDurationConvertor.HOURS_IN_DAY_PROPERTY, 8);
+
+    migration = new TechnicalDebtMeasuresMigration(db.database(), settings);
+  }
+
+  @Test
+  public void migrate_technical_debt_measures() throws Exception {
+    db.prepareDbUnit(getClass(), "migrate_technical_debt_measures.xml");
+
+    migration.execute();
+
+    db.assertDbUnit(getClass(), "migrate_technical_debt_measures_result.xml", "project_measures");
+  }
+
+  @Test
+  public void migrate_added_technical_debt_measures() throws Exception {
+    db.prepareDbUnit(getClass(), "migrate_new_technical_debt_measures.xml");
+
+    migration.execute();
+
+    db.assertDbUnit(getClass(), "migrate_new_technical_debt_measures_result.xml", "project_measures");
+  }
+
+  @Test
+  public void migrate_sqale_measures() throws Exception {
+    db.prepareDbUnit(getClass(), "migrate_sqale_measures.xml");
+
+    migration.execute();
+
+    db.assertDbUnit(getClass(), "migrate_sqale_measures_result.xml", "project_measures");
+  }
+
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/violation/ProgressTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/violation/ProgressTest.java
deleted file mode 100644 (file)
index 87c0e2f..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.violation;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.slf4j.Logger;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-public class ProgressTest {
-  @Test
-  public void log_progress() throws Exception {
-    Logger logger = mock(Logger.class);
-    ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
-
-    Progress progress = new Progress(5000, logger, System.currentTimeMillis());
-    progress.run();
-    progress.increment(200);
-    progress.increment(130);
-    progress.run();
-    progress.increment(1670);
-    progress.run();
-
-    verify(logger, times(3)).info(argument.capture());
-    assertThat(argument.getAllValues().get(0)).isEqualTo("0% [0/5000 violations]");
-    assertThat(argument.getAllValues().get(1)).isEqualTo("6% [330/5000 violations]");
-    assertThat(argument.getAllValues().get(2)).isEqualTo("40% [2000/5000 violations]");
-  }
-
-  @Test
-  public void log_remaining_time() throws Exception {
-    Logger logger = mock(Logger.class);
-    ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
-
-    long fiveMinutesAgo = System.currentTimeMillis() - 5 * 60 * 1000;
-    Progress progress = new Progress(5000, logger, fiveMinutesAgo);
-    progress.increment(2000);
-    progress.run();
-
-    verify(logger).info(argument.capture());
-    assertThat(argument.getValue()).isEqualTo("40% [2000/5000 violations, 7 minutes remaining]");
-  }
-}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/violation/ViolationConvertersTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/violation/ViolationConvertersTest.java
deleted file mode 100644 (file)
index 6e37ed9..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.violation;
-
-import com.google.common.collect.Lists;
-import org.apache.commons.lang.exception.ExceptionUtils;
-import org.junit.Test;
-import org.sonar.api.config.Settings;
-
-import java.util.List;
-import java.util.TimerTask;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class ViolationConvertersTest {
-
-  @Test
-  public void default_number_of_threads() throws Exception {
-    assertThat(new ViolationConverters(new Settings()).numberOfThreads()).isEqualTo(ViolationConverters.DEFAULT_THREADS);
-  }
-
-  @Test
-  public void configure_number_of_threads() throws Exception {
-    Settings settings = new Settings();
-    settings.setProperty(ViolationConverters.THREADS_PROPERTY, 2);
-    assertThat(new ViolationConverters(settings).numberOfThreads()).isEqualTo(2);
-  }
-
-  @Test
-  public void number_of_threads_should_not_be_negative() throws Exception {
-    try {
-      Settings settings = new Settings();
-      settings.setProperty(ViolationConverters.THREADS_PROPERTY, -2);
-      new ViolationConverters(settings).numberOfThreads();
-      fail();
-    } catch (IllegalArgumentException e) {
-      assertThat(e.getMessage()).isEqualTo("Bad value of " + ViolationConverters.THREADS_PROPERTY + ": -2");
-    }
-  }
-
-  @Test
-  public void propagate_converter_failure() throws Exception {
-    Callable<Object> callable = mock(Callable.class);
-    when(callable.call()).thenThrow(new IllegalStateException("Need to cry"));
-
-    List<Callable<Object>> callables = Lists.newArrayList(callable);
-    try {
-      new ViolationConverters(new Settings()).doExecute(new FakeTimerTask(), callables);
-      fail();
-    } catch (Exception e) {
-      assertThat(ExceptionUtils.getRootCause(e).getMessage()).isEqualTo("Need to cry");
-    }
-
-  }
-
-  static class FakeTimerTask extends TimerTask {
-    @Override
-    public void run() {
-    }
-  }
-}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/violation/ViolationMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/violation/ViolationMigrationTest.java
deleted file mode 100644 (file)
index 851615d..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.violation;
-
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.api.config.Settings;
-import org.sonar.core.persistence.TestDatabase;
-
-import java.util.Set;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class ViolationMigrationTest {
-
-  @ClassRule
-  public static TestDatabase db = new TestDatabase().schema(ViolationMigrationTest.class, "schema.sql");
-
-  @Test
-  public void migrate_violations() throws Exception {
-    db.prepareDbUnit(getClass(), "migrate_violations.xml");
-
-    new ViolationMigration(db.database(), new Settings()).execute();
-
-    db.assertDbUnit(getClass(), "migrate_violations_result.xml", "issues", "issue_changes");
-    assertMigrationEnded();
-  }
-
-  @Test
-  public void no_violations_to_migrate() throws Exception {
-    db.prepareDbUnit(getClass(), "no_violations_to_migrate.xml");
-
-    new ViolationMigration(db.database(), new Settings()).execute();
-
-    db.assertDbUnit(getClass(), "no_violations_to_migrate_result.xml", "issues", "issue_changes");
-    assertMigrationEnded();
-  }
-
-  private void assertMigrationEnded() {
-    assertThat(db.count("select count(id) from rule_failures")).isEqualTo(0);
-
-    // Progress thread is dead
-    Set<Thread> threads = Thread.getAllStackTraces().keySet();
-    for (Thread thread : threads) {
-      assertThat(thread.getName()).isNotEqualTo(Progress.THREAD_NAME);
-    }
-  }
-}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/violation36/ProgressTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/violation36/ProgressTest.java
new file mode 100644 (file)
index 0000000..f9eed06
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.violation36;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.slf4j.Logger;
+import org.sonar.server.db.migrations.violation36.Progress;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class ProgressTest {
+  @Test
+  public void log_progress() throws Exception {
+    Logger logger = mock(Logger.class);
+    ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
+
+    Progress progress = new Progress(5000, logger, System.currentTimeMillis());
+    progress.run();
+    progress.increment(200);
+    progress.increment(130);
+    progress.run();
+    progress.increment(1670);
+    progress.run();
+
+    verify(logger, times(3)).info(argument.capture());
+    assertThat(argument.getAllValues().get(0)).isEqualTo("0% [0/5000 violations]");
+    assertThat(argument.getAllValues().get(1)).isEqualTo("6% [330/5000 violations]");
+    assertThat(argument.getAllValues().get(2)).isEqualTo("40% [2000/5000 violations]");
+  }
+
+  @Test
+  public void log_remaining_time() throws Exception {
+    Logger logger = mock(Logger.class);
+    ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
+
+    long fiveMinutesAgo = System.currentTimeMillis() - 5 * 60 * 1000;
+    Progress progress = new Progress(5000, logger, fiveMinutesAgo);
+    progress.increment(2000);
+    progress.run();
+
+    verify(logger).info(argument.capture());
+    assertThat(argument.getValue()).isEqualTo("40% [2000/5000 violations, 7 minutes remaining]");
+  }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/violation36/ViolationConvertersTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/violation36/ViolationConvertersTest.java
new file mode 100644 (file)
index 0000000..06ea4f7
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.violation36;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.server.db.migrations.violation36.ViolationConverters;
+
+import java.util.List;
+import java.util.TimerTask;
+import java.util.concurrent.Callable;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ViolationConvertersTest {
+
+  @Test
+  public void default_number_of_threads() throws Exception {
+    assertThat(new ViolationConverters(new Settings()).numberOfThreads()).isEqualTo(ViolationConverters.DEFAULT_THREADS);
+  }
+
+  @Test
+  public void configure_number_of_threads() throws Exception {
+    Settings settings = new Settings();
+    settings.setProperty(ViolationConverters.THREADS_PROPERTY, 2);
+    assertThat(new ViolationConverters(settings).numberOfThreads()).isEqualTo(2);
+  }
+
+  @Test
+  public void number_of_threads_should_not_be_negative() throws Exception {
+    try {
+      Settings settings = new Settings();
+      settings.setProperty(ViolationConverters.THREADS_PROPERTY, -2);
+      new ViolationConverters(settings).numberOfThreads();
+      fail();
+    } catch (IllegalArgumentException e) {
+      assertThat(e.getMessage()).isEqualTo("Bad value of " + ViolationConverters.THREADS_PROPERTY + ": -2");
+    }
+  }
+
+  @Test
+  public void propagate_converter_failure() throws Exception {
+    Callable<Object> callable = mock(Callable.class);
+    when(callable.call()).thenThrow(new IllegalStateException("Need to cry"));
+
+    List<Callable<Object>> callables = Lists.newArrayList(callable);
+    try {
+      new ViolationConverters(new Settings()).doExecute(new FakeTimerTask(), callables);
+      fail();
+    } catch (Exception e) {
+      assertThat(ExceptionUtils.getRootCause(e).getMessage()).isEqualTo("Need to cry");
+    }
+
+  }
+
+  static class FakeTimerTask extends TimerTask {
+    @Override
+    public void run() {
+    }
+  }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/violation36/ViolationMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/violation36/ViolationMigrationTest.java
new file mode 100644 (file)
index 0000000..523eec9
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.violation36;
+
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.core.persistence.TestDatabase;
+
+import java.util.Set;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class ViolationMigrationTest {
+
+  @ClassRule
+  public static TestDatabase db = new TestDatabase().schema(ViolationMigrationTest.class, "schema.sql");
+
+  @Test
+  public void migrate_violations() throws Exception {
+    db.prepareDbUnit(getClass(), "migrate_violations.xml");
+
+    new ViolationMigration(db.database(), new Settings()).execute();
+
+    db.assertDbUnit(getClass(), "migrate_violations_result.xml", "issues", "issue_changes");
+    assertMigrationEnded();
+  }
+
+  @Test
+  public void no_violations_to_migrate() throws Exception {
+    db.prepareDbUnit(getClass(), "no_violations_to_migrate.xml");
+
+    new ViolationMigration(db.database(), new Settings()).execute();
+
+    db.assertDbUnit(getClass(), "no_violations_to_migrate_result.xml", "issues", "issue_changes");
+    assertMigrationEnded();
+  }
+
+  private void assertMigrationEnded() {
+    assertThat(db.count("select count(id) from rule_failures")).isEqualTo(0);
+
+    // Progress thread is dead
+    Set<Thread> threads = Thread.getAllStackTraces().keySet();
+    for (Thread thread : threads) {
+      assertThat(thread.getName()).isNotEqualTo(Progress.THREAD_NAME);
+    }
+  }
+}
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigrationTest/migrate_dev_cost_measures.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigrationTest/migrate_dev_cost_measures.xml
deleted file mode 100644 (file)
index 2d1633d..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<dataset>
-
-  <!-- development_cost -->
-  <metrics delete_historical_data="[null]" id="1" name="development_cost" VAL_TYPE="STRING" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-
-  <project_measures id="1" VALUE="1.0" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
-
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigrationTest/migrate_dev_cost_measures_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigrationTest/migrate_dev_cost_measures_result.xml
deleted file mode 100644 (file)
index 6db169e..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<dataset>
-
-  <project_measures id="1" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="480" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
-
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/DevelopmentCostMeasuresMigrationTest/schema.sql
deleted file mode 100644 (file)
index 1e29613..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
--- 4.3
-
-CREATE TABLE "PROJECT_MEASURES" (
-  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "VALUE" DOUBLE,
-  "METRIC_ID" INTEGER NOT NULL,
-  "SNAPSHOT_ID" INTEGER,
-  "RULE_ID" INTEGER,
-  "RULES_CATEGORY_ID" INTEGER,
-  "TEXT_VALUE" VARCHAR(96),
-  "TENDENCY" INTEGER,
-  "MEASURE_DATE" TIMESTAMP,
-  "PROJECT_ID" INTEGER,
-  "ALERT_STATUS" VARCHAR(5),
-  "ALERT_TEXT" VARCHAR(4000),
-  "URL" VARCHAR(2000),
-  "DESCRIPTION" VARCHAR(4000),
-  "RULE_PRIORITY" INTEGER,
-  "CHARACTERISTIC_ID" INTEGER,
-  "PERSON_ID" INTEGER,
-  "VARIATION_VALUE_1" DOUBLE,
-  "VARIATION_VALUE_2" DOUBLE,
-  "VARIATION_VALUE_3" DOUBLE,
-  "VARIATION_VALUE_4" DOUBLE,
-  "VARIATION_VALUE_5" DOUBLE
-);
-
-CREATE TABLE "METRICS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "NAME" VARCHAR(64) NOT NULL,
-  "DESCRIPTION" VARCHAR(255),
-  "DIRECTION" INTEGER NOT NULL DEFAULT 0,
-  "DOMAIN" VARCHAR(64),
-  "SHORT_NAME" VARCHAR(64),
-  "QUALITATIVE" BOOLEAN NOT NULL DEFAULT FALSE,
-  "VAL_TYPE" VARCHAR(8),
-  "USER_MANAGED" BOOLEAN DEFAULT FALSE,
-  "ENABLED" BOOLEAN DEFAULT TRUE,
-  "ORIGIN" VARCHAR(3),
-  "WORST_VALUE" DOUBLE,
-  "BEST_VALUE" DOUBLE,
-  "OPTIMIZED_BEST_VALUE" BOOLEAN,
-  "HIDDEN" BOOLEAN,
-  "DELETE_HISTORICAL_DATA" BOOLEAN
-);
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest/migrate_issue_changelog_debt.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest/migrate_issue_changelog_debt.xml
deleted file mode 100644 (file)
index 5116d3e..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<dataset>
-
-  <!-- Change from 1 day, 1 hour and 1 minute of debt to 2 days -->
-  <issue_changes ID="1" KEE="1" ISSUE_KEY="ABCD" USER_LOGIN ="[null]" CHANGE_TYPE="diff" CHANGE_DATA="technicalDebt=10101|20000,resolution=,status=RESOLVED|REOPENED"
-                 CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05" ISSUE_CHANGE_CREATION_DATE="2012-01-05"/>
-
-  <!-- No change on debt, should not be touched -->
-  <issue_changes ID="2" KEE="2" ISSUE_KEY="ABCD" USER_LOGIN ="[null]" CHANGE_TYPE="diff" CHANGE_DATA="status=RESOLVED|REOPENED"
-                 CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05" ISSUE_CHANGE_CREATION_DATE="2012-01-05"/>
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest/migrate_issue_changelog_debt_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest/migrate_issue_changelog_debt_result.xml
deleted file mode 100644 (file)
index 1f176fb..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<dataset>
-
-  <!-- Change from 1 day, 1 hour and 1 minute of debt to 2 days -->
-  <issue_changes ID="1" KEE="1" ISSUE_KEY="ABCD" USER_LOGIN ="[null]" CHANGE_TYPE="diff" CHANGE_DATA="technicalDebt=541|960,resolution=,status=RESOLVED|REOPENED"
-                 CREATED_AT="2012-01-05" UPDATED_AT="2014-02-19" ISSUE_CHANGE_CREATION_DATE="2012-01-05"/>
-
-  <!-- No change on debt, should not be touched -->
-  <issue_changes ID="2" KEE="2" ISSUE_KEY="ABCD" USER_LOGIN ="[null]" CHANGE_TYPE="diff" CHANGE_DATA="status=RESOLVED|REOPENED"
-                 CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05" ISSUE_CHANGE_CREATION_DATE="2012-01-05"/>
-
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest/schema.sql
deleted file mode 100644 (file)
index b6bcd85..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
--- 4.3
-
-CREATE TABLE "ISSUE_CHANGES" (
-  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "KEE" VARCHAR(50),
-  "ISSUE_KEY" VARCHAR(50) NOT NULL,
-  "USER_LOGIN" VARCHAR(40),
-  "CHANGE_TYPE" VARCHAR(40),
-  "CHANGE_DATA"  VARCHAR(16777215),
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP,
-  "ISSUE_CHANGE_CREATION_DATE" TIMESTAMP,
-);
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueMigrationTest/migrate_issues_debt.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueMigrationTest/migrate_issues_debt.xml
deleted file mode 100644 (file)
index 7717330..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<dataset>
-
-  <!-- 1 day, 1 hour and 1 minute of debt -->
-  <issues ID="1" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="1"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
-          TECHNICAL_DEBT="010101"/>
-
-  <!-- 1 day debt -->
-  <issues ID="2" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="2"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
-          TECHNICAL_DEBT="010000"/>
-
-  <!-- 1 hour debt -->
-  <issues ID="3" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="3"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
-          TECHNICAL_DEBT="100"/>
-
-  <!-- 1 minute debt -->
-  <issues ID="4" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="4"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
-          TECHNICAL_DEBT="1"/>
-
-
-  <!-- No debt, should not be touched -->
-  <issues ID="100" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="100"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
-          TECHNICAL_DEBT="[null]"/>
-
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueMigrationTest/migrate_issues_debt_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueMigrationTest/migrate_issues_debt_result.xml
deleted file mode 100644 (file)
index 1f0c371..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<dataset>
-
-  <!-- Previous debt value was 010101, it should be 1 day * 8 (nb of hours in day) * 60 + 1 hour * 60 + 1 minute = 541 minutes -->
-  <issues ID="1" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="1"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2014-02-19"
-          TECHNICAL_DEBT="541"/>
-
-  <!-- 1 day debt -->
-  <issues ID="2" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="2"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2014-02-19"
-          TECHNICAL_DEBT="480"/>
-
-  <!-- 1 hour debt -->
-  <issues ID="3" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="3"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2014-02-19"
-          TECHNICAL_DEBT="60"/>
-
-  <!-- 1 minute debt -->
-  <issues ID="4" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="4"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2014-02-19"
-          TECHNICAL_DEBT="1"/>
-
-
-  <!-- No debt, should not be touched -->
-  <issues ID="100" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="100"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
-          TECHNICAL_DEBT="[null]"/>
-
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueMigrationTest/schema.sql
deleted file mode 100644 (file)
index f3f71cf..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
--- 4.3
-
-CREATE TABLE "ISSUES" (
-  "ID" INTEGER 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,
-  "STATUS" VARCHAR(20),
-  "RESOLUTION" VARCHAR(20),
-  "CHECKSUM" VARCHAR(1000),
-  "REPORTER" VARCHAR(40),
-  "ASSIGNEE" VARCHAR(40),
-  "AUTHOR_LOGIN" VARCHAR(100),
-  "ACTION_PLAN_KEY" VARCHAR(50) NULL,
-  "ISSUE_ATTRIBUTES" VARCHAR(4000),
-  "ISSUE_CREATION_DATE" TIMESTAMP,
-  "ISSUE_CLOSE_DATE" TIMESTAMP,
-  "ISSUE_UPDATE_DATE" TIMESTAMP,
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP,
-  "TECHNICAL_DEBT" INTEGER
-);
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_new_technical_debt_measures.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_new_technical_debt_measures.xml
deleted file mode 100644 (file)
index fec9c9c..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<dataset>
-
-  <!-- Added Technical debt metric -->
-  <metrics delete_historical_data="[null]" id="1" name="new_technical_debt" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-
-  <!-- Another metric -->
-  <metrics delete_historical_data="[null]" id="2" name="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-
-
-  <!-- Measure with variations on all period -->
-  <project_measures id="1" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="0.1" variation_value_2="0.2" variation_value_3="0.3" variation_value_4="0.4" variation_value_5="0.5"/>
-
-  <!-- Measure with some variations -->
-  <project_measures id="2" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="0.1" variation_value_2="0.2" variation_value_3="0.0" variation_value_4="0.0" variation_value_5="0.0"/>
-
-  <!-- Change on another metric, should not be touched -->
-  <project_measures id="10" VALUE="20" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_new_technical_debt_measures_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_new_technical_debt_measures_result.xml
deleted file mode 100644 (file)
index 0c77c0f..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<dataset>
-
-  <!-- Measure with variations on all period -->
-  <project_measures id="1" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="48" variation_value_2="96" variation_value_3="144" variation_value_4="192" variation_value_5="240"/>
-
-  <!-- Measure with some variations -->
-  <project_measures id="2" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="48" variation_value_2="96" variation_value_3="0" variation_value_4="0" variation_value_5="0"/>
-
-  <!-- Change on another metric, should not be touched -->
-  <project_measures id="10" VALUE="20" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
-
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_sqale_measures.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_sqale_measures.xml
deleted file mode 100644 (file)
index b9081d8..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-<dataset>
-
-  <!-- sqale_effort_to_grade_X -->
-  <metrics delete_historical_data="[null]" id="2" name="sqale_effort_to_grade_a" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-  <metrics delete_historical_data="[null]" id="3" name="sqale_effort_to_grade_b" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-  <metrics delete_historical_data="[null]" id="4" name="sqale_effort_to_grade_c" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-  <metrics delete_historical_data="[null]" id="5" name="sqale_effort_to_grade_d" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-
-  <!-- debt by severity -->
-  <metrics delete_historical_data="[null]" id="6" name="blocker_remediation_cost" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-  <metrics delete_historical_data="[null]" id="7" name="critical_remediation_cost" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-  <metrics delete_historical_data="[null]" id="8" name="major_remediation_cost" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-  <metrics delete_historical_data="[null]" id="9" name="minor_remediation_cost" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-  <metrics delete_historical_data="[null]" id="10" name="info_remediation_cost" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-
-
-  <project_measures id="2" VALUE="1.0" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
-  <project_measures id="3" VALUE="1.0" METRIC_ID="3" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
-  <project_measures id="4" VALUE="1.0" METRIC_ID="4" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
-  <project_measures id="5" VALUE="1.0" METRIC_ID="5" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
-
-  <project_measures id="6" VALUE="1.0" METRIC_ID="6" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
-  <project_measures id="7" VALUE="1.0" METRIC_ID="7" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
-  <project_measures id="8" VALUE="1.0" METRIC_ID="8" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
-  <project_measures id="9" VALUE="1.0" METRIC_ID="9" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
-  <project_measures id="10" VALUE="1.0" METRIC_ID="10" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
-
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_sqale_measures_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_sqale_measures_result.xml
deleted file mode 100644 (file)
index b0e80bd..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-<dataset>
-
-  <project_measures id="2" VALUE="480" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
-  <project_measures id="3" VALUE="480" METRIC_ID="3" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
-  <project_measures id="4" VALUE="480" METRIC_ID="4" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
-  <project_measures id="5" VALUE="480" METRIC_ID="5" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
-
-  <project_measures id="6" VALUE="480" METRIC_ID="6" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
-  <project_measures id="7" VALUE="480" METRIC_ID="7" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
-  <project_measures id="8" VALUE="480" METRIC_ID="8" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
-  <project_measures id="9" VALUE="480" METRIC_ID="9" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
-  <project_measures id="10" VALUE="480" METRIC_ID="10" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
-
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_technical_debt_measures.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_technical_debt_measures.xml
deleted file mode 100644 (file)
index 80c512c..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<dataset>
-
-  <!-- Technical debt metric -->
-  <metrics delete_historical_data="[null]" id="1" name="sqale_index" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-
-  <!-- Another metric -->
-  <metrics delete_historical_data="[null]" id="2" name="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]"  domain="[null]" short_name=""
-           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-
-
-  <!-- Value 1 day of debt -->
-  <project_measures id="1" VALUE="1.0" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
-
-  <!-- Measure with variations on all period -->
-  <project_measures id="2" VALUE="2.0" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
-
-  <!-- Measure with some variations -->
-  <project_measures id="3" VALUE="3.0" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="0.1" variation_value_2="0.2" variation_value_3="0.0" variation_value_4="0.0" variation_value_5="0.0"/>
-
-  <!-- Change on another metric, should not be touched -->
-  <project_measures id="10" VALUE="20" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_technical_debt_measures_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/migrate_technical_debt_measures_result.xml
deleted file mode 100644 (file)
index 2a3e206..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<dataset>
-
-  <!-- Value 1 day, 1 hour and 1 minute of debt -->
-  <project_measures id="1" VALUE="480" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
-
-  <!-- Measure with variations on all period -->
-  <project_measures id="2" VALUE="960" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
-
-  <!-- Measure with some variations -->
-  <project_measures id="3" VALUE="1440" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="48" variation_value_2="96" variation_value_3="0" variation_value_4="0" variation_value_5="0"/>
-
-  <!-- Change on another metric, should not be touched -->
-  <project_measures id="10" VALUE="20" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
-                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
-
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasuresMigrationTest/schema.sql
deleted file mode 100644 (file)
index 1e29613..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
--- 4.3
-
-CREATE TABLE "PROJECT_MEASURES" (
-  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "VALUE" DOUBLE,
-  "METRIC_ID" INTEGER NOT NULL,
-  "SNAPSHOT_ID" INTEGER,
-  "RULE_ID" INTEGER,
-  "RULES_CATEGORY_ID" INTEGER,
-  "TEXT_VALUE" VARCHAR(96),
-  "TENDENCY" INTEGER,
-  "MEASURE_DATE" TIMESTAMP,
-  "PROJECT_ID" INTEGER,
-  "ALERT_STATUS" VARCHAR(5),
-  "ALERT_TEXT" VARCHAR(4000),
-  "URL" VARCHAR(2000),
-  "DESCRIPTION" VARCHAR(4000),
-  "RULE_PRIORITY" INTEGER,
-  "CHARACTERISTIC_ID" INTEGER,
-  "PERSON_ID" INTEGER,
-  "VARIATION_VALUE_1" DOUBLE,
-  "VARIATION_VALUE_2" DOUBLE,
-  "VARIATION_VALUE_3" DOUBLE,
-  "VARIATION_VALUE_4" DOUBLE,
-  "VARIATION_VALUE_5" DOUBLE
-);
-
-CREATE TABLE "METRICS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "NAME" VARCHAR(64) NOT NULL,
-  "DESCRIPTION" VARCHAR(255),
-  "DIRECTION" INTEGER NOT NULL DEFAULT 0,
-  "DOMAIN" VARCHAR(64),
-  "SHORT_NAME" VARCHAR(64),
-  "QUALITATIVE" BOOLEAN NOT NULL DEFAULT FALSE,
-  "VAL_TYPE" VARCHAR(8),
-  "USER_MANAGED" BOOLEAN DEFAULT FALSE,
-  "ENABLED" BOOLEAN DEFAULT TRUE,
-  "ORIGIN" VARCHAR(3),
-  "WORST_VALUE" DOUBLE,
-  "BEST_VALUE" DOUBLE,
-  "OPTIMIZED_BEST_VALUE" BOOLEAN,
-  "HIDDEN" BOOLEAN,
-  "DELETE_HISTORICAL_DATA" BOOLEAN
-);
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigrationTest/migrate_dev_cost_measures.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigrationTest/migrate_dev_cost_measures.xml
new file mode 100644 (file)
index 0000000..2d1633d
--- /dev/null
@@ -0,0 +1,12 @@
+<dataset>
+
+  <!-- development_cost -->
+  <metrics delete_historical_data="[null]" id="1" name="development_cost" VAL_TYPE="STRING" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+
+  <project_measures id="1" VALUE="1.0" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigrationTest/migrate_dev_cost_measures_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigrationTest/migrate_dev_cost_measures_result.xml
new file mode 100644 (file)
index 0000000..6db169e
--- /dev/null
@@ -0,0 +1,8 @@
+<dataset>
+
+  <project_measures id="1" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="480" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/DevelopmentCostMeasuresMigrationTest/schema.sql
new file mode 100644 (file)
index 0000000..1e29613
--- /dev/null
@@ -0,0 +1,45 @@
+-- 4.3
+
+CREATE TABLE "PROJECT_MEASURES" (
+  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "VALUE" DOUBLE,
+  "METRIC_ID" INTEGER NOT NULL,
+  "SNAPSHOT_ID" INTEGER,
+  "RULE_ID" INTEGER,
+  "RULES_CATEGORY_ID" INTEGER,
+  "TEXT_VALUE" VARCHAR(96),
+  "TENDENCY" INTEGER,
+  "MEASURE_DATE" TIMESTAMP,
+  "PROJECT_ID" INTEGER,
+  "ALERT_STATUS" VARCHAR(5),
+  "ALERT_TEXT" VARCHAR(4000),
+  "URL" VARCHAR(2000),
+  "DESCRIPTION" VARCHAR(4000),
+  "RULE_PRIORITY" INTEGER,
+  "CHARACTERISTIC_ID" INTEGER,
+  "PERSON_ID" INTEGER,
+  "VARIATION_VALUE_1" DOUBLE,
+  "VARIATION_VALUE_2" DOUBLE,
+  "VARIATION_VALUE_3" DOUBLE,
+  "VARIATION_VALUE_4" DOUBLE,
+  "VARIATION_VALUE_5" DOUBLE
+);
+
+CREATE TABLE "METRICS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "NAME" VARCHAR(64) NOT NULL,
+  "DESCRIPTION" VARCHAR(255),
+  "DIRECTION" INTEGER NOT NULL DEFAULT 0,
+  "DOMAIN" VARCHAR(64),
+  "SHORT_NAME" VARCHAR(64),
+  "QUALITATIVE" BOOLEAN NOT NULL DEFAULT FALSE,
+  "VAL_TYPE" VARCHAR(8),
+  "USER_MANAGED" BOOLEAN DEFAULT FALSE,
+  "ENABLED" BOOLEAN DEFAULT TRUE,
+  "ORIGIN" VARCHAR(3),
+  "WORST_VALUE" DOUBLE,
+  "BEST_VALUE" DOUBLE,
+  "OPTIMIZED_BEST_VALUE" BOOLEAN,
+  "HIDDEN" BOOLEAN,
+  "DELETE_HISTORICAL_DATA" BOOLEAN
+);
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueChangelogMigrationTest/migrate_issue_changelog_debt.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueChangelogMigrationTest/migrate_issue_changelog_debt.xml
new file mode 100644 (file)
index 0000000..5116d3e
--- /dev/null
@@ -0,0 +1,10 @@
+<dataset>
+
+  <!-- Change from 1 day, 1 hour and 1 minute of debt to 2 days -->
+  <issue_changes ID="1" KEE="1" ISSUE_KEY="ABCD" USER_LOGIN ="[null]" CHANGE_TYPE="diff" CHANGE_DATA="technicalDebt=10101|20000,resolution=,status=RESOLVED|REOPENED"
+                 CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05" ISSUE_CHANGE_CREATION_DATE="2012-01-05"/>
+
+  <!-- No change on debt, should not be touched -->
+  <issue_changes ID="2" KEE="2" ISSUE_KEY="ABCD" USER_LOGIN ="[null]" CHANGE_TYPE="diff" CHANGE_DATA="status=RESOLVED|REOPENED"
+                 CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05" ISSUE_CHANGE_CREATION_DATE="2012-01-05"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueChangelogMigrationTest/migrate_issue_changelog_debt_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueChangelogMigrationTest/migrate_issue_changelog_debt_result.xml
new file mode 100644 (file)
index 0000000..1f176fb
--- /dev/null
@@ -0,0 +1,11 @@
+<dataset>
+
+  <!-- Change from 1 day, 1 hour and 1 minute of debt to 2 days -->
+  <issue_changes ID="1" KEE="1" ISSUE_KEY="ABCD" USER_LOGIN ="[null]" CHANGE_TYPE="diff" CHANGE_DATA="technicalDebt=541|960,resolution=,status=RESOLVED|REOPENED"
+                 CREATED_AT="2012-01-05" UPDATED_AT="2014-02-19" ISSUE_CHANGE_CREATION_DATE="2012-01-05"/>
+
+  <!-- No change on debt, should not be touched -->
+  <issue_changes ID="2" KEE="2" ISSUE_KEY="ABCD" USER_LOGIN ="[null]" CHANGE_TYPE="diff" CHANGE_DATA="status=RESOLVED|REOPENED"
+                 CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05" ISSUE_CHANGE_CREATION_DATE="2012-01-05"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueChangelogMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueChangelogMigrationTest/schema.sql
new file mode 100644 (file)
index 0000000..b6bcd85
--- /dev/null
@@ -0,0 +1,13 @@
+-- 4.3
+
+CREATE TABLE "ISSUE_CHANGES" (
+  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "KEE" VARCHAR(50),
+  "ISSUE_KEY" VARCHAR(50) NOT NULL,
+  "USER_LOGIN" VARCHAR(40),
+  "CHANGE_TYPE" VARCHAR(40),
+  "CHANGE_DATA"  VARCHAR(16777215),
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP,
+  "ISSUE_CHANGE_CREATION_DATE" TIMESTAMP,
+);
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueMigrationTest/migrate_issues_debt.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueMigrationTest/migrate_issues_debt.xml
new file mode 100644 (file)
index 0000000..7717330
--- /dev/null
@@ -0,0 +1,44 @@
+<dataset>
+
+  <!-- 1 day, 1 hour and 1 minute of debt -->
+  <issues ID="1" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="1"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+          TECHNICAL_DEBT="010101"/>
+
+  <!-- 1 day debt -->
+  <issues ID="2" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="2"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+          TECHNICAL_DEBT="010000"/>
+
+  <!-- 1 hour debt -->
+  <issues ID="3" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="3"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+          TECHNICAL_DEBT="100"/>
+
+  <!-- 1 minute debt -->
+  <issues ID="4" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="4"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+          TECHNICAL_DEBT="1"/>
+
+
+  <!-- No debt, should not be touched -->
+  <issues ID="100" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="100"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+          TECHNICAL_DEBT="[null]"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueMigrationTest/migrate_issues_debt_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueMigrationTest/migrate_issues_debt_result.xml
new file mode 100644 (file)
index 0000000..1f0c371
--- /dev/null
@@ -0,0 +1,44 @@
+<dataset>
+
+  <!-- Previous debt value was 010101, it should be 1 day * 8 (nb of hours in day) * 60 + 1 hour * 60 + 1 minute = 541 minutes -->
+  <issues ID="1" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="1"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2014-02-19"
+          TECHNICAL_DEBT="541"/>
+
+  <!-- 1 day debt -->
+  <issues ID="2" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="2"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2014-02-19"
+          TECHNICAL_DEBT="480"/>
+
+  <!-- 1 hour debt -->
+  <issues ID="3" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="3"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2014-02-19"
+          TECHNICAL_DEBT="60"/>
+
+  <!-- 1 minute debt -->
+  <issues ID="4" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="4"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2014-02-19"
+          TECHNICAL_DEBT="1"/>
+
+
+  <!-- No debt, should not be touched -->
+  <issues ID="100" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="100"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+          TECHNICAL_DEBT="[null]"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/IssueMigrationTest/schema.sql
new file mode 100644 (file)
index 0000000..f3f71cf
--- /dev/null
@@ -0,0 +1,28 @@
+-- 4.3
+
+CREATE TABLE "ISSUES" (
+  "ID" INTEGER 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,
+  "STATUS" VARCHAR(20),
+  "RESOLUTION" VARCHAR(20),
+  "CHECKSUM" VARCHAR(1000),
+  "REPORTER" VARCHAR(40),
+  "ASSIGNEE" VARCHAR(40),
+  "AUTHOR_LOGIN" VARCHAR(100),
+  "ACTION_PLAN_KEY" VARCHAR(50) NULL,
+  "ISSUE_ATTRIBUTES" VARCHAR(4000),
+  "ISSUE_CREATION_DATE" TIMESTAMP,
+  "ISSUE_CLOSE_DATE" TIMESTAMP,
+  "ISSUE_UPDATE_DATE" TIMESTAMP,
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP,
+  "TECHNICAL_DEBT" INTEGER
+);
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_new_technical_debt_measures.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_new_technical_debt_measures.xml
new file mode 100644 (file)
index 0000000..fec9c9c
--- /dev/null
@@ -0,0 +1,29 @@
+<dataset>
+
+  <!-- Added Technical debt metric -->
+  <metrics delete_historical_data="[null]" id="1" name="new_technical_debt" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+
+  <!-- Another metric -->
+  <metrics delete_historical_data="[null]" id="2" name="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+
+
+  <!-- Measure with variations on all period -->
+  <project_measures id="1" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="0.1" variation_value_2="0.2" variation_value_3="0.3" variation_value_4="0.4" variation_value_5="0.5"/>
+
+  <!-- Measure with some variations -->
+  <project_measures id="2" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="0.1" variation_value_2="0.2" variation_value_3="0.0" variation_value_4="0.0" variation_value_5="0.0"/>
+
+  <!-- Change on another metric, should not be touched -->
+  <project_measures id="10" VALUE="20" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_new_technical_debt_measures_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_new_technical_debt_measures_result.xml
new file mode 100644 (file)
index 0000000..0c77c0f
--- /dev/null
@@ -0,0 +1,21 @@
+<dataset>
+
+  <!-- Measure with variations on all period -->
+  <project_measures id="1" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="48" variation_value_2="96" variation_value_3="144" variation_value_4="192" variation_value_5="240"/>
+
+  <!-- Measure with some variations -->
+  <project_measures id="2" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="48" variation_value_2="96" variation_value_3="0" variation_value_4="0" variation_value_5="0"/>
+
+  <!-- Change on another metric, should not be touched -->
+  <project_measures id="10" VALUE="20" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_sqale_measures.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_sqale_measures.xml
new file mode 100644 (file)
index 0000000..b9081d8
--- /dev/null
@@ -0,0 +1,64 @@
+<dataset>
+
+  <!-- sqale_effort_to_grade_X -->
+  <metrics delete_historical_data="[null]" id="2" name="sqale_effort_to_grade_a" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+  <metrics delete_historical_data="[null]" id="3" name="sqale_effort_to_grade_b" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+  <metrics delete_historical_data="[null]" id="4" name="sqale_effort_to_grade_c" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+  <metrics delete_historical_data="[null]" id="5" name="sqale_effort_to_grade_d" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+
+  <!-- debt by severity -->
+  <metrics delete_historical_data="[null]" id="6" name="blocker_remediation_cost" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+  <metrics delete_historical_data="[null]" id="7" name="critical_remediation_cost" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+  <metrics delete_historical_data="[null]" id="8" name="major_remediation_cost" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+  <metrics delete_historical_data="[null]" id="9" name="minor_remediation_cost" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+  <metrics delete_historical_data="[null]" id="10" name="info_remediation_cost" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+
+
+  <project_measures id="2" VALUE="1.0" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
+  <project_measures id="3" VALUE="1.0" METRIC_ID="3" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
+  <project_measures id="4" VALUE="1.0" METRIC_ID="4" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
+  <project_measures id="5" VALUE="1.0" METRIC_ID="5" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
+
+  <project_measures id="6" VALUE="1.0" METRIC_ID="6" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
+  <project_measures id="7" VALUE="1.0" METRIC_ID="7" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
+  <project_measures id="8" VALUE="1.0" METRIC_ID="8" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
+  <project_measures id="9" VALUE="1.0" METRIC_ID="9" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
+  <project_measures id="10" VALUE="1.0" METRIC_ID="10" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_sqale_measures_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_sqale_measures_result.xml
new file mode 100644 (file)
index 0000000..b0e80bd
--- /dev/null
@@ -0,0 +1,41 @@
+<dataset>
+
+  <project_measures id="2" VALUE="480" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
+  <project_measures id="3" VALUE="480" METRIC_ID="3" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
+  <project_measures id="4" VALUE="480" METRIC_ID="4" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
+  <project_measures id="5" VALUE="480" METRIC_ID="5" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
+
+  <project_measures id="6" VALUE="480" METRIC_ID="6" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
+  <project_measures id="7" VALUE="480" METRIC_ID="7" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
+  <project_measures id="8" VALUE="480" METRIC_ID="8" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
+  <project_measures id="9" VALUE="480" METRIC_ID="9" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
+  <project_measures id="10" VALUE="480" METRIC_ID="10" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_technical_debt_measures.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_technical_debt_measures.xml
new file mode 100644 (file)
index 0000000..80c512c
--- /dev/null
@@ -0,0 +1,35 @@
+<dataset>
+
+  <!-- Technical debt metric -->
+  <metrics delete_historical_data="[null]" id="1" name="sqale_index" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+
+  <!-- Another metric -->
+  <metrics delete_historical_data="[null]" id="2" name="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+
+
+  <!-- Value 1 day of debt -->
+  <project_measures id="1" VALUE="1.0" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+
+  <!-- Measure with variations on all period -->
+  <project_measures id="2" VALUE="2.0" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="1.0" variation_value_2="2.0" variation_value_3="3.0" variation_value_4="4.0" variation_value_5="5.0"/>
+
+  <!-- Measure with some variations -->
+  <project_measures id="3" VALUE="3.0" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="0.1" variation_value_2="0.2" variation_value_3="0.0" variation_value_4="0.0" variation_value_5="0.0"/>
+
+  <!-- Change on another metric, should not be touched -->
+  <project_measures id="10" VALUE="20" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_technical_debt_measures_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/migrate_technical_debt_measures_result.xml
new file mode 100644 (file)
index 0000000..2a3e206
--- /dev/null
@@ -0,0 +1,27 @@
+<dataset>
+
+  <!-- Value 1 day, 1 hour and 1 minute of debt -->
+  <project_measures id="1" VALUE="480" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+
+  <!-- Measure with variations on all period -->
+  <project_measures id="2" VALUE="960" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="480" variation_value_2="960" variation_value_3="1440" variation_value_4="1920" variation_value_5="2400"/>
+
+  <!-- Measure with some variations -->
+  <project_measures id="3" VALUE="1440" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="48" variation_value_2="96" variation_value_3="0" variation_value_4="0" variation_value_5="0"/>
+
+  <!-- Change on another metric, should not be touched -->
+  <project_measures id="10" VALUE="20" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt43/TechnicalDebtMeasuresMigrationTest/schema.sql
new file mode 100644 (file)
index 0000000..1e29613
--- /dev/null
@@ -0,0 +1,45 @@
+-- 4.3
+
+CREATE TABLE "PROJECT_MEASURES" (
+  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "VALUE" DOUBLE,
+  "METRIC_ID" INTEGER NOT NULL,
+  "SNAPSHOT_ID" INTEGER,
+  "RULE_ID" INTEGER,
+  "RULES_CATEGORY_ID" INTEGER,
+  "TEXT_VALUE" VARCHAR(96),
+  "TENDENCY" INTEGER,
+  "MEASURE_DATE" TIMESTAMP,
+  "PROJECT_ID" INTEGER,
+  "ALERT_STATUS" VARCHAR(5),
+  "ALERT_TEXT" VARCHAR(4000),
+  "URL" VARCHAR(2000),
+  "DESCRIPTION" VARCHAR(4000),
+  "RULE_PRIORITY" INTEGER,
+  "CHARACTERISTIC_ID" INTEGER,
+  "PERSON_ID" INTEGER,
+  "VARIATION_VALUE_1" DOUBLE,
+  "VARIATION_VALUE_2" DOUBLE,
+  "VARIATION_VALUE_3" DOUBLE,
+  "VARIATION_VALUE_4" DOUBLE,
+  "VARIATION_VALUE_5" DOUBLE
+);
+
+CREATE TABLE "METRICS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "NAME" VARCHAR(64) NOT NULL,
+  "DESCRIPTION" VARCHAR(255),
+  "DIRECTION" INTEGER NOT NULL DEFAULT 0,
+  "DOMAIN" VARCHAR(64),
+  "SHORT_NAME" VARCHAR(64),
+  "QUALITATIVE" BOOLEAN NOT NULL DEFAULT FALSE,
+  "VAL_TYPE" VARCHAR(8),
+  "USER_MANAGED" BOOLEAN DEFAULT FALSE,
+  "ENABLED" BOOLEAN DEFAULT TRUE,
+  "ORIGIN" VARCHAR(3),
+  "WORST_VALUE" DOUBLE,
+  "BEST_VALUE" DOUBLE,
+  "OPTIMIZED_BEST_VALUE" BOOLEAN,
+  "HIDDEN" BOOLEAN,
+  "DELETE_HISTORICAL_DATA" BOOLEAN
+);
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/migrate_violations.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/migrate_violations.xml
deleted file mode 100644 (file)
index 0d4a6e8..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-<dataset>
-  <snapshots id="10" root_project_id="10" project_id="11"/>
-  <users id="200" login="fabrice"/>
-  <users id="201" login="julien"/>
-  <action_plans id="999" kee="PLAN-999"/>
-
-  <!-- violation without review -->
-  <rule_failures id="1" snapshot_id="10" rule_id="20" failure_level="2" message="the message" line="1234" cost="3.14"
-                 created_at="2012-01-05" checksum="ABCDE" permanent_id="1"/>
-
-  <!-- violation with review -->
-  <rule_failures id="2" snapshot_id="10" rule_id="22" failure_level="2" message="another message" line="[null]" cost="[null]"
-                 created_at="2012-01-05" checksum="FGHIJ" permanent_id="2"/>
-  <reviews id="1" rule_failure_permanent_id="2" MANUAL_VIOLATION="[false]" MANUAL_SEVERITY="[true]" SEVERITY="BLOCKER" UPDATED_AT="2013-05-18"
-           STATUS="OPEN" RESOLUTION="[null]" USER_ID="[null]" ASSIGNEE_ID="201"/>
-
-  <review_comments ID="1" REVIEW_ID="1" USER_ID="200" REVIEW_TEXT="a comment" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
-
-  <!-- comment by unknown user -->
-  <review_comments ID="2" REVIEW_ID="1" USER_ID="999" REVIEW_TEXT="to be ignored because unknown user" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
-
-  <!-- manual violation -->
-  <rule_failures id="3" snapshot_id="10" rule_id="22" failure_level="2" message="another message" line="[null]" cost="[null]"
-                 created_at="2012-01-05" checksum="FGHIJ" permanent_id="3"/>
-  <reviews id="2" rule_failure_permanent_id="3" MANUAL_VIOLATION="[true]" MANUAL_SEVERITY="[true]" SEVERITY="BLOCKER" UPDATED_AT="2013-05-18"
-           STATUS="RESOLVED" RESOLUTION="FIXED" USER_ID="200" ASSIGNEE_ID="201"/>
-
-  <action_plans_reviews review_id="1" action_plan_id="999"/>
-
-
-
-  <!-- Already there from a past migration that crashed -->
-  <issues ID="1" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="[ignore]"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          CREATED_AT="2012-01-05" EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" UPDATED_AT="2012-01-05"/>
-  <issue_changes id="1" KEE="ABCDE" ISSUE_KEY="[ignore]" CHANGE_TYPE="comment" CHANGE_DATA="a comment" USER_LOGIN="fabrice" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/migrate_violations_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/migrate_violations_result.xml
deleted file mode 100644 (file)
index b94cc90..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-<dataset>
-
-  <snapshots id="10" root_project_id="10" project_id="11"/>
-  <users id="200" login="fabrice"/>
-  <users id="201" login="julien"/>
-  <action_plans id="999" kee="PLAN-999"/>
-
-  <!-- violation without review -->
-  <!--<rule_failures id="1" snapshot_id="10" rule_id="20" failure_level="2" message="the message" line="1234" cost="3.14"-->
-                 <!--created_at="2012-01-05" checksum="ABCDE" permanent_id="1"/>-->
-
-  <!-- violation with review -->
-  <!--<rule_failures id="2" snapshot_id="10" rule_id="22" failure_level="2" message="another message" line="[null]" cost="[null]"-->
-                 <!--created_at="2012-01-05" checksum="FGHIJ" permanent_id="2"/>-->
-  <reviews id="1" rule_failure_permanent_id="2" MANUAL_VIOLATION="[false]" MANUAL_SEVERITY="[true]" SEVERITY="BLOCKER" UPDATED_AT="2013-05-18"
-           STATUS="OPEN" RESOLUTION="[null]" USER_ID="[null]" ASSIGNEE_ID="201"/>
-
-  <review_comments ID="1" REVIEW_ID="1" USER_ID="200" REVIEW_TEXT="a comment" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
-
-  <!-- comment by unknown user -->
-  <review_comments ID="2" REVIEW_ID="1" USER_ID="999" REVIEW_TEXT="to be ignored because unknown user" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
-
-  <!-- manual violation -->
-  <!--<rule_failures id="3" snapshot_id="10" rule_id="22" failure_level="2" message="another message" line="[null]" cost="[null]"-->
-                 <!--created_at="2012-01-05" checksum="FGHIJ" permanent_id="3"/>-->
-  <reviews id="2" rule_failure_permanent_id="3" MANUAL_VIOLATION="[true]" MANUAL_SEVERITY="[true]" SEVERITY="BLOCKER" UPDATED_AT="2013-05-18"
-           STATUS="RESOLVED" RESOLUTION="FIXED" USER_ID="200" ASSIGNEE_ID="201"/>
-
-  <action_plans_reviews review_id="1" action_plan_id="999"/>
-
-
-
-  <!-- Already there from a past migration that crashed -->
-  <issues ID="1" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="[ignore]"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          CREATED_AT="2012-01-05" EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" UPDATED_AT="2012-01-05"/>
-  <issue_changes id="1" KEE="ABCDE" ISSUE_KEY="[ignore]" CHANGE_TYPE="comment" CHANGE_DATA="a comment" USER_LOGIN="fabrice" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
-
-
-
-
-
-  <issues ID="2" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MAJOR" KEE="[ignore]"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          CREATED_AT="2012-01-05" EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" UPDATED_AT="2012-01-05"/>
-
-  <issues ID="3" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="22" SEVERITY="BLOCKER" KEE="[ignore]"
-          ACTION_PLAN_KEY="PLAN-999" ASSIGNEE="julien" AUTHOR_LOGIN="[null]" CHECKSUM="FGHIJ"
-          CREATED_AT="2012-01-05" EFFORT_TO_FIX="[null]" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2013-05-18" LINE="[null]" MANUAL_SEVERITY="[true]" MESSAGE="another message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="CONFIRMED" UPDATED_AT="2013-05-18"/>
-
-  <issues ID="4" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="22" SEVERITY="BLOCKER" KEE="[ignore]"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="julien" AUTHOR_LOGIN="[null]" CHECKSUM="FGHIJ"
-          CREATED_AT="2012-01-05" EFFORT_TO_FIX="[null]" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2013-05-18" LINE="[null]" MANUAL_SEVERITY="[true]" MESSAGE="another message" REPORTER="fabrice"
-          RESOLUTION="FIXED" STATUS="RESOLVED" UPDATED_AT="2013-05-18"/>
-
-  <issue_changes id="2" KEE="[ignore]" ISSUE_KEY="[ignore]" CHANGE_TYPE="comment" CHANGE_DATA="a comment" USER_LOGIN="fabrice" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/no_violations_to_migrate.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/no_violations_to_migrate.xml
deleted file mode 100644 (file)
index 416efbc..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<dataset>
-  <snapshots id="10" root_project_id="10" project_id="11"/>
-  <users id="200" login="fabrice"/>
-  <users id="201" login="julien"/>
-  <action_plans id="999" kee="PLAN-999"/>
-
-  <!-- Already there from a past migration that crashed -->
-  <issues ID="1" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="[ignore]"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          CREATED_AT="2012-01-05" EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" UPDATED_AT="2012-01-05"/>
-  <issue_changes id="1" KEE="ABCDE" ISSUE_KEY="[ignore]" CHANGE_TYPE="comment" CHANGE_DATA="a comment" USER_LOGIN="fabrice" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/no_violations_to_migrate_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/no_violations_to_migrate_result.xml
deleted file mode 100644 (file)
index 416efbc..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<dataset>
-  <snapshots id="10" root_project_id="10" project_id="11"/>
-  <users id="200" login="fabrice"/>
-  <users id="201" login="julien"/>
-  <action_plans id="999" kee="PLAN-999"/>
-
-  <!-- Already there from a past migration that crashed -->
-  <issues ID="1" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="[ignore]"
-          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
-          CREATED_AT="2012-01-05" EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
-          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
-          RESOLUTION="[null]" STATUS="OPEN" UPDATED_AT="2012-01-05"/>
-  <issue_changes id="1" KEE="ABCDE" ISSUE_KEY="[ignore]" CHANGE_TYPE="comment" CHANGE_DATA="a comment" USER_LOGIN="fabrice" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
-</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation/ViolationMigrationTest/schema.sql
deleted file mode 100644 (file)
index eb8d051..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
--- 3.5
-
-CREATE TABLE "SNAPSHOTS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "CREATED_AT" TIMESTAMP,
-  "BUILD_DATE" TIMESTAMP,
-  "PROJECT_ID" INTEGER NOT NULL,
-  "PARENT_SNAPSHOT_ID" INTEGER,
-  "STATUS" VARCHAR(4) NOT NULL DEFAULT 'U',
-  "PURGE_STATUS" INTEGER,
-  "ISLAST" BOOLEAN NOT NULL DEFAULT FALSE,
-  "SCOPE" VARCHAR(3),
-  "QUALIFIER" VARCHAR(10),
-  "ROOT_SNAPSHOT_ID" INTEGER,
-  "VERSION" VARCHAR(500),
-  "PATH" VARCHAR(500),
-  "DEPTH" INTEGER,
-  "ROOT_PROJECT_ID" INTEGER,
-  "PERIOD1_MODE" VARCHAR(100),
-  "PERIOD1_PARAM" VARCHAR(100),
-  "PERIOD1_DATE" TIMESTAMP,
-  "PERIOD2_MODE" VARCHAR(100),
-  "PERIOD2_PARAM" VARCHAR(100),
-  "PERIOD2_DATE" TIMESTAMP,
-  "PERIOD3_MODE" VARCHAR(100),
-  "PERIOD3_PARAM" VARCHAR(100),
-  "PERIOD3_DATE" TIMESTAMP,
-  "PERIOD4_MODE" VARCHAR(100),
-  "PERIOD4_PARAM" VARCHAR(100),
-  "PERIOD4_DATE" TIMESTAMP,
-  "PERIOD5_MODE" VARCHAR(100),
-  "PERIOD5_PARAM" VARCHAR(100),
-  "PERIOD5_DATE" TIMESTAMP
-);
-
-CREATE TABLE "USERS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "LOGIN" VARCHAR(40),
-  "NAME" VARCHAR(200),
-  "EMAIL" VARCHAR(100),
-  "CRYPTED_PASSWORD" VARCHAR(40),
-  "SALT" VARCHAR(40),
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP,
-  "REMEMBER_TOKEN" VARCHAR(500),
-  "REMEMBER_TOKEN_EXPIRES_AT" TIMESTAMP,
-  "ACTIVE" BOOLEAN DEFAULT TRUE
-);
-
-
-CREATE TABLE "RULE_FAILURES" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "SNAPSHOT_ID" INTEGER NOT NULL,
-  "RULE_ID" INTEGER NOT NULL,
-  "FAILURE_LEVEL" INTEGER NOT NULL,
-  "MESSAGE" VARCHAR(4000),
-  "LINE" INTEGER,
-  "COST" DOUBLE,
-  "CREATED_AT" TIMESTAMP,
-  "CHECKSUM" VARCHAR(1000),
-  "PERMANENT_ID" INTEGER,
-  "SWITCHED_OFF" BOOLEAN,
-  "PERSON_ID" INTEGER
-);
-
-CREATE TABLE "ACTION_PLANS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "KEE" VARCHAR(100),
-  "NAME" VARCHAR(200),
-  "DESCRIPTION" VARCHAR(1000),
-  "DEADLINE" TIMESTAMP,
-  "USER_LOGIN" VARCHAR(40),
-  "PROJECT_ID" INTEGER,
-  "STATUS" VARCHAR(10),
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP
-);
-
-CREATE TABLE "ACTION_PLANS_REVIEWS" (
-  "ACTION_PLAN_ID" INTEGER,
-  "REVIEW_ID" INTEGER
-);
-
-CREATE TABLE "REVIEWS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP,
-  "USER_ID" INTEGER,
-  "ASSIGNEE_ID" INTEGER,
-  "TITLE" VARCHAR(500),
-  "STATUS" VARCHAR(10),
-  "SEVERITY" VARCHAR(10),
-  "RULE_FAILURE_PERMANENT_ID" INTEGER,
-  "PROJECT_ID" INTEGER,
-  "RESOURCE_ID" INTEGER,
-  "RESOURCE_LINE" INTEGER,
-  "RESOLUTION" VARCHAR(200),
-  "RULE_ID" INTEGER,
-  "MANUAL_VIOLATION" BOOLEAN NOT NULL,
-  "MANUAL_SEVERITY" BOOLEAN NOT NULL,
-  "DATA" VARCHAR(4000)
-);
-
-CREATE TABLE "REVIEW_COMMENTS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP,
-  "REVIEW_ID" INTEGER,
-  "USER_ID" INTEGER,
-  "REVIEW_TEXT" VARCHAR(16777215)
-);
-
-
-
--- 3.6
-
-CREATE TABLE "ISSUES" (
-  "ID" INTEGER 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,
-  "STATUS" VARCHAR(20),
-  "RESOLUTION" VARCHAR(20),
-  "CHECKSUM" VARCHAR(1000),
-  "REPORTER" VARCHAR(40),
-  "ASSIGNEE" VARCHAR(40),
-  "AUTHOR_LOGIN" VARCHAR(100),
-  "ACTION_PLAN_KEY" VARCHAR(50) NULL,
-  "ISSUE_ATTRIBUTES" VARCHAR(4000),
-  "ISSUE_CREATION_DATE" TIMESTAMP,
-  "ISSUE_CLOSE_DATE" TIMESTAMP,
-  "ISSUE_UPDATE_DATE" TIMESTAMP,
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP
-);
-
-CREATE TABLE "ISSUE_CHANGES" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "KEE" VARCHAR(50),
-  "ISSUE_KEY" VARCHAR(50) NOT NULL,
-  "USER_LOGIN" VARCHAR(40),
-  "CHANGE_TYPE" VARCHAR(40),
-  "CHANGE_DATA"  VARCHAR(16777215),
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP,
-);
\ No newline at end of file
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/migrate_violations.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/migrate_violations.xml
new file mode 100644 (file)
index 0000000..0d4a6e8
--- /dev/null
@@ -0,0 +1,39 @@
+<dataset>
+  <snapshots id="10" root_project_id="10" project_id="11"/>
+  <users id="200" login="fabrice"/>
+  <users id="201" login="julien"/>
+  <action_plans id="999" kee="PLAN-999"/>
+
+  <!-- violation without review -->
+  <rule_failures id="1" snapshot_id="10" rule_id="20" failure_level="2" message="the message" line="1234" cost="3.14"
+                 created_at="2012-01-05" checksum="ABCDE" permanent_id="1"/>
+
+  <!-- violation with review -->
+  <rule_failures id="2" snapshot_id="10" rule_id="22" failure_level="2" message="another message" line="[null]" cost="[null]"
+                 created_at="2012-01-05" checksum="FGHIJ" permanent_id="2"/>
+  <reviews id="1" rule_failure_permanent_id="2" MANUAL_VIOLATION="[false]" MANUAL_SEVERITY="[true]" SEVERITY="BLOCKER" UPDATED_AT="2013-05-18"
+           STATUS="OPEN" RESOLUTION="[null]" USER_ID="[null]" ASSIGNEE_ID="201"/>
+
+  <review_comments ID="1" REVIEW_ID="1" USER_ID="200" REVIEW_TEXT="a comment" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
+
+  <!-- comment by unknown user -->
+  <review_comments ID="2" REVIEW_ID="1" USER_ID="999" REVIEW_TEXT="to be ignored because unknown user" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
+
+  <!-- manual violation -->
+  <rule_failures id="3" snapshot_id="10" rule_id="22" failure_level="2" message="another message" line="[null]" cost="[null]"
+                 created_at="2012-01-05" checksum="FGHIJ" permanent_id="3"/>
+  <reviews id="2" rule_failure_permanent_id="3" MANUAL_VIOLATION="[true]" MANUAL_SEVERITY="[true]" SEVERITY="BLOCKER" UPDATED_AT="2013-05-18"
+           STATUS="RESOLVED" RESOLUTION="FIXED" USER_ID="200" ASSIGNEE_ID="201"/>
+
+  <action_plans_reviews review_id="1" action_plan_id="999"/>
+
+
+
+  <!-- Already there from a past migration that crashed -->
+  <issues ID="1" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="[ignore]"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          CREATED_AT="2012-01-05" EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" UPDATED_AT="2012-01-05"/>
+  <issue_changes id="1" KEE="ABCDE" ISSUE_KEY="[ignore]" CHANGE_TYPE="comment" CHANGE_DATA="a comment" USER_LOGIN="fabrice" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/migrate_violations_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/migrate_violations_result.xml
new file mode 100644 (file)
index 0000000..b94cc90
--- /dev/null
@@ -0,0 +1,64 @@
+<dataset>
+
+  <snapshots id="10" root_project_id="10" project_id="11"/>
+  <users id="200" login="fabrice"/>
+  <users id="201" login="julien"/>
+  <action_plans id="999" kee="PLAN-999"/>
+
+  <!-- violation without review -->
+  <!--<rule_failures id="1" snapshot_id="10" rule_id="20" failure_level="2" message="the message" line="1234" cost="3.14"-->
+                 <!--created_at="2012-01-05" checksum="ABCDE" permanent_id="1"/>-->
+
+  <!-- violation with review -->
+  <!--<rule_failures id="2" snapshot_id="10" rule_id="22" failure_level="2" message="another message" line="[null]" cost="[null]"-->
+                 <!--created_at="2012-01-05" checksum="FGHIJ" permanent_id="2"/>-->
+  <reviews id="1" rule_failure_permanent_id="2" MANUAL_VIOLATION="[false]" MANUAL_SEVERITY="[true]" SEVERITY="BLOCKER" UPDATED_AT="2013-05-18"
+           STATUS="OPEN" RESOLUTION="[null]" USER_ID="[null]" ASSIGNEE_ID="201"/>
+
+  <review_comments ID="1" REVIEW_ID="1" USER_ID="200" REVIEW_TEXT="a comment" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
+
+  <!-- comment by unknown user -->
+  <review_comments ID="2" REVIEW_ID="1" USER_ID="999" REVIEW_TEXT="to be ignored because unknown user" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
+
+  <!-- manual violation -->
+  <!--<rule_failures id="3" snapshot_id="10" rule_id="22" failure_level="2" message="another message" line="[null]" cost="[null]"-->
+                 <!--created_at="2012-01-05" checksum="FGHIJ" permanent_id="3"/>-->
+  <reviews id="2" rule_failure_permanent_id="3" MANUAL_VIOLATION="[true]" MANUAL_SEVERITY="[true]" SEVERITY="BLOCKER" UPDATED_AT="2013-05-18"
+           STATUS="RESOLVED" RESOLUTION="FIXED" USER_ID="200" ASSIGNEE_ID="201"/>
+
+  <action_plans_reviews review_id="1" action_plan_id="999"/>
+
+
+
+  <!-- Already there from a past migration that crashed -->
+  <issues ID="1" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="[ignore]"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          CREATED_AT="2012-01-05" EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" UPDATED_AT="2012-01-05"/>
+  <issue_changes id="1" KEE="ABCDE" ISSUE_KEY="[ignore]" CHANGE_TYPE="comment" CHANGE_DATA="a comment" USER_LOGIN="fabrice" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
+
+
+
+
+
+  <issues ID="2" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MAJOR" KEE="[ignore]"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          CREATED_AT="2012-01-05" EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" UPDATED_AT="2012-01-05"/>
+
+  <issues ID="3" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="22" SEVERITY="BLOCKER" KEE="[ignore]"
+          ACTION_PLAN_KEY="PLAN-999" ASSIGNEE="julien" AUTHOR_LOGIN="[null]" CHECKSUM="FGHIJ"
+          CREATED_AT="2012-01-05" EFFORT_TO_FIX="[null]" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2013-05-18" LINE="[null]" MANUAL_SEVERITY="[true]" MESSAGE="another message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="CONFIRMED" UPDATED_AT="2013-05-18"/>
+
+  <issues ID="4" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="22" SEVERITY="BLOCKER" KEE="[ignore]"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="julien" AUTHOR_LOGIN="[null]" CHECKSUM="FGHIJ"
+          CREATED_AT="2012-01-05" EFFORT_TO_FIX="[null]" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2013-05-18" LINE="[null]" MANUAL_SEVERITY="[true]" MESSAGE="another message" REPORTER="fabrice"
+          RESOLUTION="FIXED" STATUS="RESOLVED" UPDATED_AT="2013-05-18"/>
+
+  <issue_changes id="2" KEE="[ignore]" ISSUE_KEY="[ignore]" CHANGE_TYPE="comment" CHANGE_DATA="a comment" USER_LOGIN="fabrice" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/no_violations_to_migrate.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/no_violations_to_migrate.xml
new file mode 100644 (file)
index 0000000..416efbc
--- /dev/null
@@ -0,0 +1,14 @@
+<dataset>
+  <snapshots id="10" root_project_id="10" project_id="11"/>
+  <users id="200" login="fabrice"/>
+  <users id="201" login="julien"/>
+  <action_plans id="999" kee="PLAN-999"/>
+
+  <!-- Already there from a past migration that crashed -->
+  <issues ID="1" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="[ignore]"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          CREATED_AT="2012-01-05" EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" UPDATED_AT="2012-01-05"/>
+  <issue_changes id="1" KEE="ABCDE" ISSUE_KEY="[ignore]" CHANGE_TYPE="comment" CHANGE_DATA="a comment" USER_LOGIN="fabrice" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/no_violations_to_migrate_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/no_violations_to_migrate_result.xml
new file mode 100644 (file)
index 0000000..416efbc
--- /dev/null
@@ -0,0 +1,14 @@
+<dataset>
+  <snapshots id="10" root_project_id="10" project_id="11"/>
+  <users id="200" login="fabrice"/>
+  <users id="201" login="julien"/>
+  <action_plans id="999" kee="PLAN-999"/>
+
+  <!-- Already there from a past migration that crashed -->
+  <issues ID="1" COMPONENT_ID="11" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="[ignore]"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          CREATED_AT="2012-01-05" EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" UPDATED_AT="2012-01-05"/>
+  <issue_changes id="1" KEE="ABCDE" ISSUE_KEY="[ignore]" CHANGE_TYPE="comment" CHANGE_DATA="a comment" USER_LOGIN="fabrice" CREATED_AT="2012-04-28" UPDATED_AT="2012-04-29"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/violation36/ViolationMigrationTest/schema.sql
new file mode 100644 (file)
index 0000000..eb8d051
--- /dev/null
@@ -0,0 +1,152 @@
+-- 3.5
+
+CREATE TABLE "SNAPSHOTS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "CREATED_AT" TIMESTAMP,
+  "BUILD_DATE" TIMESTAMP,
+  "PROJECT_ID" INTEGER NOT NULL,
+  "PARENT_SNAPSHOT_ID" INTEGER,
+  "STATUS" VARCHAR(4) NOT NULL DEFAULT 'U',
+  "PURGE_STATUS" INTEGER,
+  "ISLAST" BOOLEAN NOT NULL DEFAULT FALSE,
+  "SCOPE" VARCHAR(3),
+  "QUALIFIER" VARCHAR(10),
+  "ROOT_SNAPSHOT_ID" INTEGER,
+  "VERSION" VARCHAR(500),
+  "PATH" VARCHAR(500),
+  "DEPTH" INTEGER,
+  "ROOT_PROJECT_ID" INTEGER,
+  "PERIOD1_MODE" VARCHAR(100),
+  "PERIOD1_PARAM" VARCHAR(100),
+  "PERIOD1_DATE" TIMESTAMP,
+  "PERIOD2_MODE" VARCHAR(100),
+  "PERIOD2_PARAM" VARCHAR(100),
+  "PERIOD2_DATE" TIMESTAMP,
+  "PERIOD3_MODE" VARCHAR(100),
+  "PERIOD3_PARAM" VARCHAR(100),
+  "PERIOD3_DATE" TIMESTAMP,
+  "PERIOD4_MODE" VARCHAR(100),
+  "PERIOD4_PARAM" VARCHAR(100),
+  "PERIOD4_DATE" TIMESTAMP,
+  "PERIOD5_MODE" VARCHAR(100),
+  "PERIOD5_PARAM" VARCHAR(100),
+  "PERIOD5_DATE" TIMESTAMP
+);
+
+CREATE TABLE "USERS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "LOGIN" VARCHAR(40),
+  "NAME" VARCHAR(200),
+  "EMAIL" VARCHAR(100),
+  "CRYPTED_PASSWORD" VARCHAR(40),
+  "SALT" VARCHAR(40),
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP,
+  "REMEMBER_TOKEN" VARCHAR(500),
+  "REMEMBER_TOKEN_EXPIRES_AT" TIMESTAMP,
+  "ACTIVE" BOOLEAN DEFAULT TRUE
+);
+
+
+CREATE TABLE "RULE_FAILURES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "SNAPSHOT_ID" INTEGER NOT NULL,
+  "RULE_ID" INTEGER NOT NULL,
+  "FAILURE_LEVEL" INTEGER NOT NULL,
+  "MESSAGE" VARCHAR(4000),
+  "LINE" INTEGER,
+  "COST" DOUBLE,
+  "CREATED_AT" TIMESTAMP,
+  "CHECKSUM" VARCHAR(1000),
+  "PERMANENT_ID" INTEGER,
+  "SWITCHED_OFF" BOOLEAN,
+  "PERSON_ID" INTEGER
+);
+
+CREATE TABLE "ACTION_PLANS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "KEE" VARCHAR(100),
+  "NAME" VARCHAR(200),
+  "DESCRIPTION" VARCHAR(1000),
+  "DEADLINE" TIMESTAMP,
+  "USER_LOGIN" VARCHAR(40),
+  "PROJECT_ID" INTEGER,
+  "STATUS" VARCHAR(10),
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP
+);
+
+CREATE TABLE "ACTION_PLANS_REVIEWS" (
+  "ACTION_PLAN_ID" INTEGER,
+  "REVIEW_ID" INTEGER
+);
+
+CREATE TABLE "REVIEWS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP,
+  "USER_ID" INTEGER,
+  "ASSIGNEE_ID" INTEGER,
+  "TITLE" VARCHAR(500),
+  "STATUS" VARCHAR(10),
+  "SEVERITY" VARCHAR(10),
+  "RULE_FAILURE_PERMANENT_ID" INTEGER,
+  "PROJECT_ID" INTEGER,
+  "RESOURCE_ID" INTEGER,
+  "RESOURCE_LINE" INTEGER,
+  "RESOLUTION" VARCHAR(200),
+  "RULE_ID" INTEGER,
+  "MANUAL_VIOLATION" BOOLEAN NOT NULL,
+  "MANUAL_SEVERITY" BOOLEAN NOT NULL,
+  "DATA" VARCHAR(4000)
+);
+
+CREATE TABLE "REVIEW_COMMENTS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP,
+  "REVIEW_ID" INTEGER,
+  "USER_ID" INTEGER,
+  "REVIEW_TEXT" VARCHAR(16777215)
+);
+
+
+
+-- 3.6
+
+CREATE TABLE "ISSUES" (
+  "ID" INTEGER 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,
+  "STATUS" VARCHAR(20),
+  "RESOLUTION" VARCHAR(20),
+  "CHECKSUM" VARCHAR(1000),
+  "REPORTER" VARCHAR(40),
+  "ASSIGNEE" VARCHAR(40),
+  "AUTHOR_LOGIN" VARCHAR(100),
+  "ACTION_PLAN_KEY" VARCHAR(50) NULL,
+  "ISSUE_ATTRIBUTES" VARCHAR(4000),
+  "ISSUE_CREATION_DATE" TIMESTAMP,
+  "ISSUE_CLOSE_DATE" TIMESTAMP,
+  "ISSUE_UPDATE_DATE" TIMESTAMP,
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP
+);
+
+CREATE TABLE "ISSUE_CHANGES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "KEE" VARCHAR(50),
+  "ISSUE_KEY" VARCHAR(50) NOT NULL,
+  "USER_LOGIN" VARCHAR(40),
+  "CHANGE_TYPE" VARCHAR(40),
+  "CHANGE_DATA"  VARCHAR(16777215),
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP,
+);
\ No newline at end of file