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;
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
+++ /dev/null
-/*
- * 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));
- }
-
- }
-}
+++ /dev/null
-/*
- * 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);
- }
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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);
- }
- }
-
-}
+++ /dev/null
-/*
- * 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;
--- /dev/null
+/*
+ * 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));
+ }
+
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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;
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
# 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')
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
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
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
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
+++ /dev/null
-/*
- * 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);
- }
-
-}
+++ /dev/null
-/*
- * 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");
- }
-
-}
+++ /dev/null
-/*
- * 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=");
- }
-}
+++ /dev/null
-/*
- * 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");
- }
-
-}
+++ /dev/null
-/*
- * 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");
- }
-
-}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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");
+ }
+
+}
--- /dev/null
+/*
+ * 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=");
+ }
+}
--- /dev/null
+/*
+ * 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");
+ }
+
+}
--- /dev/null
+/*
+ * 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");
+ }
+
+}
+++ /dev/null
-/*
- * 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]");
- }
-}
+++ /dev/null
-/*
- * 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() {
- }
- }
-}
+++ /dev/null
-/*
- * 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);
- }
- }
-}
--- /dev/null
+/*
+ * 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]");
+ }
+}
--- /dev/null
+/*
+ * 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() {
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
+++ /dev/null
-<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>
+++ /dev/null
-<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>
+++ /dev/null
--- 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
-);
+++ /dev/null
-<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>
+++ /dev/null
-<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>
+++ /dev/null
--- 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,
-);
+++ /dev/null
-<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>
+++ /dev/null
-<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>
+++ /dev/null
--- 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
-);
+++ /dev/null
-<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>
+++ /dev/null
-<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>
+++ /dev/null
-<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>
+++ /dev/null
-<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>
+++ /dev/null
-<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>
+++ /dev/null
-<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>
+++ /dev/null
--- 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
-);
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+-- 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
+);
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+-- 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,
+);
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+-- 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
+);
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+-- 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
+);
+++ /dev/null
-<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>
+++ /dev/null
-<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>
+++ /dev/null
-<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>
+++ /dev/null
-<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>
+++ /dev/null
--- 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
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+-- 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