import org.sonar.server.db.migrations.v451.AddMissingCustomRuleParametersMigration;
import org.sonar.server.db.migrations.v451.DeleteUnescapedActivities;
import org.sonar.server.db.migrations.v50.*;
+import org.sonar.server.db.migrations.v51.FeedIssueTags;
import java.util.List;
ReplaceIssueFiltersProjectKeyByUuid.class,
FeedSnapshotSourcesUpdatedAt.class,
FeedFileSources.class,
- FeedIssueLongDates.class
+ FeedIssueLongDates.class,
+
+ // 5.1
+ FeedIssueTags.class
);
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.db.migrations.v51;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Maps;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.Database;
+import org.sonar.server.db.migrations.*;
+import org.sonar.server.db.migrations.MassUpdate.Handler;
+import org.sonar.server.db.migrations.Select.Row;
+import org.sonar.server.db.migrations.Select.RowHandler;
+
+import java.sql.SQLException;
+import java.util.Map;
+
+
+/**
+ * SONAR-5897
+ */
+public class FeedIssueTags extends BaseDataChange {
+
+ private static final Joiner TAG_JOINER = Joiner.on(',').skipNulls();
+
+ private final long now;
+
+ public FeedIssueTags(Database db, System2 system) {
+ super(db);
+ this.now = system.now();
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+
+ final Map<Integer, String> tagsByRuleId = Maps.newHashMap();
+ context.prepareSelect("SELECT id, system_tags, tags FROM rules").scroll(new RowHandler() {
+ @Override
+ public void handle(Row row) throws SQLException {
+ Integer id = row.getInt(1);
+ tagsByRuleId.put(id, TAG_JOINER.join(row.getString(2), row.getString(3)));
+ }
+ });
+
+ MassUpdate update = context.prepareMassUpdate().rowPluralName("issues");
+ update.select("SELECT id, rule_id FROM issues WHERE tags IS NULL");
+ update.update("UPDATE issues SET tags = ?, updated_at = ? WHERE id = ?");
+ update.execute(new Handler() {
+ @Override
+ public boolean handle(Row row, SqlStatement update) throws SQLException {
+ Long id = row.getLong(1);
+ Integer ruleId = row.getInt(2);
+ boolean updated = false;
+ if (tagsByRuleId.get(ruleId) != null) {
+ updated = true;
+ update.setString(1, tagsByRuleId.get(ruleId));
+ update.setLong(2, now);
+ update.setLong(3, id);
+ }
+ return updated;
+ }
+ });
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.db.migrations.v51;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.TestDatabase;
+
+import java.util.Date;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class FeedIssueTagsTest {
+
+ @ClassRule
+ public static TestDatabase db = new TestDatabase().schema(FeedIssueTagsTest.class, "schema.sql");
+
+ FeedIssueTags migration;
+
+ System2 system;
+
+ @Before
+ public void setUp() throws Exception {
+ db.executeUpdateSql("truncate table rules");
+ db.executeUpdateSql("truncate table issues");
+
+ system = mock(System2.class);
+ Date now = DateUtils.parseDateTime("2014-12-08T17:33:00+0100");
+ when(system.now()).thenReturn(now.getTime());
+ migration = new FeedIssueTags(db.database(), system);
+ }
+
+ @Test
+ public void migrate_empty_db() throws Exception {
+ migration.execute();
+ }
+
+ @Test
+ public void migrate_with_rule_tags() throws Exception {
+ db.prepareDbUnit(this.getClass(), "before.xml");
+ migration.execute();
+ }
+}
--- /dev/null
+<dataset>
+
+ <issues id="1" kee="ABC" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="10"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ action_plan_key="[null]"
+ tags="tag1,tag2,tag3,tag4"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+ created_at="1500000000000"
+ updated_at="1418056380000"
+ />
+
+ <issues id="2" kee="DEF" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="10"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ tags="polop,palap"
+ action_plan_key="[null]"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+ created_at="1500000000000"
+ updated_at="1500000000000"
+ />
+
+ <issues id="3" kee="GHI" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="20"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ action_plan_key="[null]"
+ tags="tag3,tag4"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+ created_at="1500000000000"
+ updated_at="1418056380000"
+ />
+
+ <issues id="4" kee="JKL" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="30"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ action_plan_key="[null]"
+ tags="tag1,tag2"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+ created_at="1500000000000"
+ updated_at="1418056380000"
+ />
+
+ <issues id="5" kee="MNO" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="40"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ action_plan_key="[null]"
+ tags="[null]"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+ created_at="1500000000000"
+ updated_at="1500000000000"
+ />
+
+ <issues id="6" kee="PQR" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="666"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ action_plan_key="[null]"
+ tags="[null]"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+ created_at="1500000000000"
+ updated_at="1500000000000"
+ />
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="10" plugin_rule_key="Rule1" plugin_name="xoo" name="Rule1" description="Rule1" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" plugin_config_key="[null]"
+ tags="tag3,tag4" system_tags="tag1,tag2"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]" created_at="2014-01-01" updated_at="2014-01-01"/>
+
+ <rules id="20" plugin_rule_key="Rule2" plugin_name="xoo" name="Rule2" description="Rule2" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" plugin_config_key="[null]"
+ tags="tag3,tag4" system_tags="[null]"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]" created_at="2014-01-01" updated_at="2014-01-01"/>
+
+ <rules id="30" plugin_rule_key="Rule3" plugin_name="xoo" name="Rule3" description="Rule3" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" plugin_config_key="[null]"
+ tags="[null]" system_tags="tag1,tag2"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]" created_at="2014-01-01" updated_at="2014-01-01"/>
+
+ <rules id="40" plugin_rule_key="Rule4" plugin_name="xoo" name="Rule4" description="Rule4" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" plugin_config_key="[null]"
+ tags="[null]" system_tags="[null]"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]" created_at="2014-01-01" updated_at="2014-01-01"/>
+
+
+ <issues id="1" kee="ABC" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="10"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ action_plan_key="[null]"
+ tags="[null]"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+ created_at="1500000000000"
+ updated_at="1500000000000"
+ />
+
+ <!-- re-entrant migration - ignore the issues that are already fed with new dates -->
+ <issues id="2" kee="DEF" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="10"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ tags="polop,palap"
+ action_plan_key="[null]"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+ created_at="1500000000000"
+ updated_at="1500000000000"
+ />
+
+ <issues id="3" kee="GHI" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="20"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ action_plan_key="[null]"
+ tags="[null]"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+ created_at="1500000000000"
+ updated_at="1500000000000"
+ />
+
+ <issues id="4" kee="JKL" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="30"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ action_plan_key="[null]"
+ tags="[null]"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+ created_at="1500000000000"
+ updated_at="1500000000000"
+ />
+
+ <issues id="5" kee="MNO" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="40"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ action_plan_key="[null]"
+ tags="[null]"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+ created_at="1500000000000"
+ updated_at="1500000000000"
+ />
+
+ <issues id="6" kee="PQR" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="666"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ action_plan_key="[null]"
+ tags="[null]"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+ created_at="1500000000000"
+ updated_at="1500000000000"
+ />
+
+</dataset>
--- /dev/null
+CREATE TABLE "RULES" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "PLUGIN_RULE_KEY" VARCHAR(200) NOT NULL,
+ "PLUGIN_NAME" VARCHAR(255) NOT NULL,
+ "DESCRIPTION" VARCHAR(16777215),
+ "DESCRIPTION_FORMAT" VARCHAR(20),
+ "PRIORITY" INTEGER,
+ "IS_TEMPLATE" BOOLEAN DEFAULT FALSE,
+ "TEMPLATE_ID" INTEGER,
+ "PLUGIN_CONFIG_KEY" VARCHAR(500),
+ "NAME" VARCHAR(200),
+ "STATUS" VARCHAR(40),
+ "LANGUAGE" VARCHAR(20),
+ "NOTE_DATA" CLOB(2147483647),
+ "NOTE_USER_LOGIN" VARCHAR(255),
+ "NOTE_CREATED_AT" TIMESTAMP,
+ "NOTE_UPDATED_AT" TIMESTAMP,
+ "CHARACTERISTIC_ID" INTEGER,
+ "DEFAULT_CHARACTERISTIC_ID" INTEGER,
+ "REMEDIATION_FUNCTION" VARCHAR(20),
+ "DEFAULT_REMEDIATION_FUNCTION" VARCHAR(20),
+ "REMEDIATION_COEFF" VARCHAR(20),
+ "DEFAULT_REMEDIATION_COEFF" VARCHAR(20),
+ "REMEDIATION_OFFSET" VARCHAR(20),
+ "DEFAULT_REMEDIATION_OFFSET" VARCHAR(20),
+ "EFFORT_TO_FIX_DESCRIPTION" VARCHAR(4000),
+ "TAGS" VARCHAR(4000),
+ "SYSTEM_TAGS" VARCHAR(4000),
+ "CREATED_AT" TIMESTAMP,
+ "UPDATED_AT" TIMESTAMP
+);
+
+CREATE TABLE "ISSUES" (
+ "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "KEE" VARCHAR(50) UNIQUE NOT NULL,
+ "COMPONENT_ID" INTEGER NOT NULL,
+ "ROOT_COMPONENT_ID" INTEGER,
+ "RULE_ID" INTEGER,
+ "SEVERITY" VARCHAR(10),
+ "MANUAL_SEVERITY" BOOLEAN NOT NULL,
+ "MESSAGE" VARCHAR(4000),
+ "LINE" INTEGER,
+ "EFFORT_TO_FIX" DOUBLE,
+ "TECHNICAL_DEBT" INTEGER,
+ "STATUS" VARCHAR(20),
+ "RESOLUTION" VARCHAR(20),
+ "CHECKSUM" VARCHAR(1000),
+ "REPORTER" VARCHAR(255),
+ "ASSIGNEE" VARCHAR(255),
+ "AUTHOR_LOGIN" VARCHAR(255),
+ "ACTION_PLAN_KEY" VARCHAR(50) NULL,
+ "ISSUE_ATTRIBUTES" VARCHAR(4000),
+ "TAGS" VARCHAR(4000),
+ "ISSUE_CREATION_DATE" TIMESTAMP,
+ "ISSUE_CLOSE_DATE" TIMESTAMP,
+ "ISSUE_UPDATE_DATE" TIMESTAMP,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT
+);
--- /dev/null
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+
+#
+# SonarQube 5.1
+# SONAR-5897
+#
+class FeedIssueTags < ActiveRecord::Migration
+
+ def self.up
+ execute_java_migration('org.sonar.server.db.migrations.v51.FeedIssueTags')
+ end
+
+end
*/
public class DatabaseVersion implements BatchComponent, ServerComponent {
- public static final int LAST_VERSION = 750;
+ public static final int LAST_VERSION = 751;
/**
* List of all the tables.
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('719');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('720');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('750');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('751');
INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null);
ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;