]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-17592 adding column messageFormattings to issues table
authorLukasz Jarocki <lukasz.jarocki@sonarsource.com>
Wed, 23 Nov 2022 14:16:10 +0000 (15:16 +0100)
committersonartech <sonartech@sonarsource.com>
Thu, 1 Dec 2022 20:03:11 +0000 (20:03 +0000)
server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDto.java
server/sonar-db-dao/src/main/protobuf/db-issues.proto
server/sonar-db-dao/src/schema/schema-sq.ddl
server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueDtoTest.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/AddMessageFormattingsColumnToIssueTable.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/DbVersion98.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v98/AddMessageFormattingsColumnToIssueTableTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v98/AddMessageFormattingsColumnToIssueTableTest/schema.sql [new file with mode: 0644]

index 2e9fa59db6762f4eda8c5a64994db9ddd97569b8..1cbc7ee2660197bd26886458edeb9415fe713411 100644 (file)
@@ -60,6 +60,7 @@ public final class IssueDto implements Serializable {
   private String severity;
   private boolean manualSeverity;
   private String message;
+  private byte[] messageFormattings;
   private Integer line;
   private Double gap;
   private Long effort;
@@ -114,6 +115,7 @@ public final class IssueDto implements Serializable {
       .setLine(issue.line())
       .setLocations((DbIssues.Locations) issue.getLocations())
       .setMessage(issue.message())
+      .setMessageFormattings((byte[]) null)
       .setGap(issue.gap())
       .setEffort(issue.effortInMinutes())
       .setResolution(issue.resolution())
@@ -163,6 +165,7 @@ public final class IssueDto implements Serializable {
       .setLine(issue.line())
       .setLocations((DbIssues.Locations) issue.getLocations())
       .setMessage(issue.message())
+      .setMessageFormattings((byte[]) null)
       .setGap(issue.gap())
       .setEffort(issue.effortInMinutes())
       .setResolution(issue.resolution())
@@ -262,6 +265,25 @@ public final class IssueDto implements Serializable {
     return this;
   }
 
+  public IssueDto setMessageFormattings(@Nullable byte[] messageFormattings) {
+    this.messageFormattings = messageFormattings;
+    return this;
+  }
+
+  public IssueDto setMessageFormattings(@Nullable DbIssues.MessageFormattings messageFormattings) {
+    if (messageFormattings == null) {
+      this.messageFormattings = null;
+    } else {
+      this.messageFormattings = messageFormattings.toByteArray();
+    }
+    return this;
+  }
+
+  @CheckForNull
+  public byte[] getMessageFormattings() {
+    return messageFormattings;
+  }
+
   @CheckForNull
   public Integer getLine() {
     return line;
index a094ea162ca332f8ab9f380722b58aa9bb40250e..8672388eecca48818c979f9122987f41c5c684c7 100644 (file)
@@ -54,4 +54,18 @@ message Location {
   optional sonarqube.db.commons.TextRange text_range = 2;
   optional string msg = 3;
   optional string checksum = 4;
+  repeated MessageFormatting msgFormattings = 5;
+}
+message MessageFormattings {
+  repeated MessageFormatting messageFormatting = 1;
+}
+
+message MessageFormatting {
+  required int32 start = 1;
+  required int32 end = 2;
+  required MessageFormattingType type = 3;
+}
+
+enum MessageFormattingType {
+  CODE = 0;
 }
index 3e0f5bcdde0092121ab58734e8b1da47ea45f67d..023646e06ff87dd947b5b683b475ae5bece452c8 100644 (file)
@@ -428,7 +428,8 @@ CREATE TABLE "ISSUES"(
     "ISSUE_TYPE" TINYINT,
     "FROM_HOTSPOT" BOOLEAN,
     "QUICK_FIX_AVAILABLE" BOOLEAN,
-    "RULE_DESCRIPTION_CONTEXT_KEY" CHARACTER VARYING(50)
+    "RULE_DESCRIPTION_CONTEXT_KEY" CHARACTER VARYING(50),
+    "MESSAGE_FORMATTINGS" BINARY LARGE OBJECT
 );
 ALTER TABLE "ISSUES" ADD CONSTRAINT "PK_ISSUES" PRIMARY KEY("KEE");
 CREATE INDEX "ISSUES_ASSIGNEE" ON "ISSUES"("ASSIGNEE" NULLS FIRST);
index 53c2eb6e3e8de54bb78f31e2c14321b90afb0152..d90e7fc671fac45466974c988a45e7c51f9b8c7a 100644 (file)
@@ -32,6 +32,7 @@ import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rules.RuleType;
 import org.sonar.api.utils.Duration;
 import org.sonar.core.issue.DefaultIssue;
+import org.sonar.db.protobuf.DbIssues;
 import org.sonar.db.rule.RuleDto;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -40,8 +41,12 @@ public class IssueDtoTest {
 
   private static final String TEST_CONTEXT_KEY = "test_context_key";
 
+  private static final DbIssues.MessageFormattings EXAMPLE_MESSAGE_FORMATTINGS = DbIssues.MessageFormattings.newBuilder()
+    .addMessageFormatting(DbIssues.MessageFormatting.newBuilder().setStart(0).setEnd(1).setType(DbIssues.MessageFormattingType.CODE)
+      .build()).build();
+
   @Test
-  public void set_issue_fields() {
+  public void toDefaultIssue_set_issue_fields() {
     Date createdAt = DateUtils.addDays(new Date(), -5);
     Date updatedAt = DateUtils.addDays(new Date(), -3);
     Date closedAt = DateUtils.addDays(new Date(), -1);
@@ -64,6 +69,7 @@ public class IssueDtoTest {
       .setLine(6)
       .setSeverity("BLOCKER")
       .setMessage("message")
+      .setMessageFormattings(EXAMPLE_MESSAGE_FORMATTINGS)
       .setManualSeverity(true)
       .setAssigneeUuid("perceval")
       .setAuthorLogin("pierre")
@@ -89,6 +95,7 @@ public class IssueDtoTest {
     assertThat(issue.line()).isEqualTo(6);
     assertThat(issue.severity()).isEqualTo("BLOCKER");
     assertThat(issue.message()).isEqualTo("message");
+    //assertThat(issue.getMessageFormatting()).isEqualTo(EXAMPLE_MESSAGE_FORMATTING); //TODO fix later SONAR-17592
     assertThat(issue.manualSeverity()).isTrue();
     assertThat(issue.assignee()).isEqualTo("perceval");
     assertThat(issue.authorLogin()).isEqualTo("pierre");
@@ -150,20 +157,20 @@ public class IssueDtoTest {
       containsExactly("key", RuleType.BUG.getDbConstant(), RuleKey.of("repo", "rule"));
 
     assertThat(issueDto).extracting(IssueDto::getIssueCreationDate, IssueDto::getIssueCloseDate,
-      IssueDto::getIssueUpdateDate, IssueDto::getSelectedAt, IssueDto::getUpdatedAt, IssueDto::getCreatedAt)
+        IssueDto::getIssueUpdateDate, IssueDto::getSelectedAt, IssueDto::getUpdatedAt, IssueDto::getCreatedAt)
       .containsExactly(dateNow, dateNow, dateNow, dateNow.getTime(), now, now);
 
     assertThat(issueDto).extracting(IssueDto::getLine, IssueDto::getMessage,
-      IssueDto::getGap, IssueDto::getEffort, IssueDto::getResolution, IssueDto::getStatus, IssueDto::getSeverity)
+        IssueDto::getGap, IssueDto::getEffort, IssueDto::getResolution, IssueDto::getStatus, IssueDto::getSeverity)
       .containsExactly(1, "message", 1.0, 1L, Issue.RESOLUTION_FALSE_POSITIVE, Issue.STATUS_CLOSED, "BLOCKER");
 
     assertThat(issueDto).extracting(IssueDto::getTags, IssueDto::getAuthorLogin)
       .containsExactly(Set.of("todo"), "admin");
 
     assertThat(issueDto).extracting(IssueDto::isManualSeverity, IssueDto::getChecksum, IssueDto::getAssigneeUuid,
-      IssueDto::isExternal, IssueDto::getComponentUuid, IssueDto::getComponentKey,
-      IssueDto::getModuleUuidPath, IssueDto::getProjectUuid, IssueDto::getProjectKey,
-      IssueDto::getRuleUuid)
+        IssueDto::isExternal, IssueDto::getComponentUuid, IssueDto::getComponentKey,
+        IssueDto::getModuleUuidPath, IssueDto::getProjectUuid, IssueDto::getProjectKey,
+        IssueDto::getRuleUuid)
       .containsExactly(true, "123", "123", true, "123", "componentKey",
         "path/to/module/uuid", "123", "projectKey", "ruleUuid");
 
@@ -184,19 +191,19 @@ public class IssueDtoTest {
       containsExactly("key", RuleType.BUG.getDbConstant(), RuleKey.of("repo", "rule"));
 
     assertThat(issueDto).extracting(IssueDto::getIssueCreationDate, IssueDto::getIssueCloseDate,
-      IssueDto::getIssueUpdateDate, IssueDto::getSelectedAt, IssueDto::getUpdatedAt)
+        IssueDto::getIssueUpdateDate, IssueDto::getSelectedAt, IssueDto::getUpdatedAt)
       .containsExactly(dateNow, dateNow, dateNow, dateNow.getTime(), now);
 
     assertThat(issueDto).extracting(IssueDto::getLine, IssueDto::getMessage,
-      IssueDto::getGap, IssueDto::getEffort, IssueDto::getResolution, IssueDto::getStatus, IssueDto::getSeverity)
+        IssueDto::getGap, IssueDto::getEffort, IssueDto::getResolution, IssueDto::getStatus, IssueDto::getSeverity)
       .containsExactly(1, "message", 1.0, 1L, Issue.RESOLUTION_FALSE_POSITIVE, Issue.STATUS_CLOSED, "BLOCKER");
 
     assertThat(issueDto).extracting(IssueDto::getTags, IssueDto::getAuthorLogin)
       .containsExactly(Set.of("todo"), "admin");
 
     assertThat(issueDto).extracting(IssueDto::isManualSeverity, IssueDto::getChecksum, IssueDto::getAssigneeUuid,
-      IssueDto::isExternal, IssueDto::getComponentUuid, IssueDto::getComponentKey,
-      IssueDto::getModuleUuidPath, IssueDto::getProjectUuid, IssueDto::getProjectKey)
+        IssueDto::isExternal, IssueDto::getComponentUuid, IssueDto::getComponentKey,
+        IssueDto::getModuleUuidPath, IssueDto::getProjectUuid, IssueDto::getProjectKey)
       .containsExactly(true, "123", "123", true, "123", "componentKey",
         "path/to/module/uuid", "123", "projectKey");
 
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/AddMessageFormattingsColumnToIssueTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/AddMessageFormattingsColumnToIssueTable.java
new file mode 100644 (file)
index 0000000..9bd7e59
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.db.migration.version.v98;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
+import org.sonar.server.platform.db.migration.def.BlobColumnDef;
+import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class AddMessageFormattingsColumnToIssueTable extends DdlChange {
+  private static final String TABLE_NAME = "issues";
+  private static final String COLUMN_NAME = "message_formattings";
+
+  public AddMessageFormattingsColumnToIssueTable(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    try (Connection c = getDatabase().getDataSource().getConnection()) {
+      if (!DatabaseUtils.tableColumnExists(c, TABLE_NAME, COLUMN_NAME)) {
+        context.execute(new AddColumnsBuilder(getDialect(), TABLE_NAME)
+          .addColumn(BlobColumnDef.newBlobColumnDefBuilder().setColumnName(COLUMN_NAME).setIsNullable(true).build())
+          .build());
+      }
+    }
+  }
+}
index ab5da5a55db699136f77b47997b6adda45037d47..b06c1e7b0d84c9f4a3e4c387e3bfcade5a212be0 100644 (file)
@@ -31,6 +31,7 @@ public class DbVersion98 implements DbVersion {
       .add(6702, "Move project measure variations to values", MoveProjectMeasureVariationToValue.class)
       .add(6703, "Drop project measure variation column", DropProjectMeasureVariationColumn.class)
       .add(6704, "Update sonar-users group description", UpsertSonarUsersDescription.class)
+      .add(6705, "Add message_formattings column to issue table", AddMessageFormattingsColumnToIssueTable.class)
       ;
   }
 }
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v98/AddMessageFormattingsColumnToIssueTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v98/AddMessageFormattingsColumnToIssueTableTest.java
new file mode 100644 (file)
index 0000000..a368a28
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.db.migration.version.v98;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+
+public class AddMessageFormattingsColumnToIssueTableTest {
+  private static final String TABLE_NAME = "issues";
+  private static final String COLUMN_NAME = "message_formattings";
+
+  @Rule
+  public final CoreDbTester db = CoreDbTester.createForSchema(AddMessageFormattingsColumnToIssueTableTest.class, "schema.sql");
+
+  private final AddMessageFormattingsColumnToIssueTable underTest = new AddMessageFormattingsColumnToIssueTable(db.database());
+
+  @Test
+  public void migration_should_add_column() throws SQLException {
+    db.assertColumnDoesNotExist(TABLE_NAME, COLUMN_NAME);
+    underTest.execute();
+    db.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, Types.BLOB, null, true);
+  }
+
+  @Test
+  public void migration_should_be_reentrant() throws SQLException {
+    db.assertColumnDoesNotExist(TABLE_NAME, COLUMN_NAME);
+    underTest.execute();
+    // re-entrant
+    underTest.execute();
+    db.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, Types.BLOB, null, true);
+  }
+
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v98/AddMessageFormattingsColumnToIssueTableTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v98/AddMessageFormattingsColumnToIssueTableTest/schema.sql
new file mode 100644 (file)
index 0000000..b03e42c
--- /dev/null
@@ -0,0 +1,30 @@
+CREATE TABLE "ISSUES"(
+    "KEE" VARCHAR(50) NOT NULL,
+    "RULE_UUID" VARCHAR(40),
+    "SEVERITY" VARCHAR(10),
+    "MANUAL_SEVERITY" BOOLEAN NOT NULL,
+    "MESSAGE" VARCHAR(4000),
+    "LINE" INTEGER,
+    "GAP" DOUBLE,
+    "STATUS" VARCHAR(20),
+    "RESOLUTION" VARCHAR(20),
+    "CHECKSUM" VARCHAR(1000),
+    "REPORTER" VARCHAR(255),
+    "ASSIGNEE" VARCHAR(255),
+    "AUTHOR_LOGIN" VARCHAR(255),
+    "ACTION_PLAN_KEY" VARCHAR(50),
+    "ISSUE_ATTRIBUTES" VARCHAR(4000),
+    "EFFORT" INTEGER,
+    "CREATED_AT" BIGINT,
+    "UPDATED_AT" BIGINT,
+    "ISSUE_CREATION_DATE" BIGINT,
+    "ISSUE_UPDATE_DATE" BIGINT,
+    "ISSUE_CLOSE_DATE" BIGINT,
+    "TAGS" VARCHAR(4000),
+    "COMPONENT_UUID" VARCHAR(50),
+    "PROJECT_UUID" VARCHAR(50),
+    "LOCATIONS" BLOB,
+    "ISSUE_TYPE" TINYINT,
+    "FROM_HOTSPOT" BOOLEAN,
+     CONSTRAINT pk_issues PRIMARY KEY (KEE)
+);
\ No newline at end of file