]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6846 don't fail on duplicate row in snapshot_sources 969/head
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Fri, 13 May 2016 07:59:47 +0000 (09:59 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Fri, 13 May 2016 11:28:07 +0000 (13:28 +0200)
sonar-db/src/main/java/org/sonar/db/version/v50/FeedFileSources.java
sonar-db/src/test/java/org/sonar/db/version/v50/FeedFileSourcesTest.java
sonar-db/src/test/resources/org/sonar/db/version/v50/FeedFileSourcesTest/schema.sql

index 83424ff4d5dcc321f5b2a061bb3beb6bd98e5ffe..bf45c9ee42405902cca8ef34c635b8f2982fa2c7 100644 (file)
@@ -96,7 +96,10 @@ public class FeedFileSources extends BaseDataChange {
 
     // duplication_data
     "m13.text_value, " +
-    "m13.measure_data  " +
+    "m13.measure_data, " +
+
+    // to detect multiple rows in snapshot_sources for the same snapshot
+    "s.id " +
 
     "FROM snapshots s " +
     "JOIN snapshot_sources ss " +
@@ -137,15 +140,17 @@ public class FeedFileSources extends BaseDataChange {
     "f.enabled = ? " +
     "AND f.scope = 'FIL' " +
     "AND p.scope = 'PRJ' AND p.qualifier = 'TRK' " +
-    "AND fs.file_uuid IS NULL";
+    "AND fs.file_uuid IS NULL " +
+    "ORDER BY s.id, ss.id desc";
 
   public FeedFileSources(Database db, System2 system) {
     super(db);
     this.system = system;
   }
-  
+
   private static final class FileSourceBuilder implements MassUpdate.Handler {
     private final long now;
+    private long previousSnapshotId = -1;
 
     public FileSourceBuilder(System2 system) {
       now = system.now();
@@ -183,6 +188,12 @@ public class FeedFileSources extends BaseDataChange {
       byte[] longOverallCovCond = row.getNullableBytes(28);
       byte[] shortDuplicationData = row.getNullableBytes(29);
       byte[] longDuplicationData = row.getNullableBytes(30);
+      long snapshotId = row.getLong(31);
+
+      if (snapshotId == previousSnapshotId) {
+        return false;
+      }
+      this.previousSnapshotId = snapshotId;
 
       String[] sourceData = new FileSourceDto(source,
         ofNullableBytes(shortRevisions, longRevisions),
@@ -197,8 +208,7 @@ public class FeedFileSources extends BaseDataChange {
         ofNullableBytes(shortOverallHits, longOverallHits),
         ofNullableBytes(shortOverallCond, longOverallCond),
         ofNullableBytes(shortOverallCovCond, longOverallCovCond),
-        ofNullableBytes(shortDuplicationData, longDuplicationData)
-        ).getSourceData();
+        ofNullableBytes(shortDuplicationData, longDuplicationData)).getSourceData();
 
       update.setString(1, projectUuid)
         .setString(2, fileUuid)
@@ -210,7 +220,7 @@ public class FeedFileSources extends BaseDataChange {
 
       return true;
     }
-    
+
     private static String ofNullableBytes(@Nullable byte[] shortBytes, @Nullable byte[] longBytes) {
       byte[] result;
       if (shortBytes == null) {
index 665d31b9023d1c90ed33ee3b5141d005efae8558..371b45f8fa0d22080b3e3a34043e9917ae3e73c1 100644 (file)
@@ -66,6 +66,28 @@ public class FeedFileSourcesTest {
     migration.execute();
   }
 
+  @Test
+  public void migrate_ignores_duplicate_multiple_rows_in_snapshot_source_for_the_same_snapshot() throws Exception {
+    db.prepareDbUnit(getClass(), "before.xml");
+    db.executeUpdateSql("insert into snapshot_sources " +
+        "(snapshot_id, data, updated_at) " +
+        "values " +
+        "(6, 'class Foo {\r\n  // Empty\r\n}\r\n', '2014-10-31 16:44:02.000')");
+
+    db.executeUpdateSql("insert into snapshot_sources " +
+        "(snapshot_id, data, updated_at) " +
+        "values " +
+        "(6, 'class Bar {\r\n  // Empty\r\n}\r\n', '2014-10-31 16:44:02.000')");
+
+    migration.execute();
+
+    List<Map<String, Object>> results = getFileSources();
+    assertThat(results).hasSize(2);
+
+    // the lastest inserted row is the one taken into account
+    assertThat(results.get(1).get("data")).isEqualTo(",,,,,,,,,,,,,,,class Bar {\r\n,,,,,,,,,,,,,,,  // Empty\r\n,,,,,,,,,,,,,,,}\r\n,,,,,,,,,,,,,,,\r\n");
+  }
+
   @Test
   public void migrate_sources_with_no_scm_no_coverage() throws Exception {
     db.prepareDbUnit(getClass(), "before.xml");
@@ -82,8 +104,7 @@ public class FeedFileSourcesTest {
 
     migration.execute();
 
-    List<Map<String, Object>> results = db.select("select project_uuid as \"projectUuid\", file_uuid as \"fileUuid\", created_at as \"createdAt\", " +
-      "updated_at as \"updatedAt\", data as \"data\", data as \"data\", line_hashes as \"lineHashes\", data_hash as \"dataHash\"  from file_sources");
+    List<Map<String, Object>> results = getFileSources();
     assertThat(results).hasSize(2);
 
     assertThat(results.get(0).get("projectUuid")).isEqualTo("uuid-MyProject");
@@ -243,8 +264,7 @@ public class FeedFileSourcesTest {
 
     migration.execute();
 
-    List<Map<String, Object>> results = db.select("select project_uuid as \"projectUuid\", file_uuid as \"fileUuid\", created_at as \"createdAt\", " +
-      "updated_at as \"updatedAt\", data as \"data\", data as \"data\", line_hashes as \"lineHashes\", data_hash as \"dataHash\"  from file_sources");
+    List<Map<String, Object>> results = getFileSources();
     assertThat(results).hasSize(2);
 
     assertThat(results.get(0).get("projectUuid")).isEqualTo("uuid-MyProject");
@@ -305,8 +325,7 @@ public class FeedFileSourcesTest {
 
     // db.assertDbUnit(getClass(), "after-with-invalid-duplication.xml", "file_sources");
 
-    List<Map<String, Object>> results = db.select("select project_uuid as \"projectUuid\", file_uuid as \"fileUuid\", created_at as \"createdAt\", " +
-      "updated_at as \"updatedAt\", data as \"data\", data as \"data\", line_hashes as \"lineHashes\", data_hash as \"dataHash\"  from file_sources");
+    List<Map<String, Object>> results = getFileSources();
     assertThat(results).hasSize(2);
 
     assertThat(results.get(0).get("projectUuid")).isEqualTo("uuid-MyProject");
@@ -326,6 +345,11 @@ public class FeedFileSourcesTest {
     assertThat(results.get(1).get("createdAt")).isEqualTo(NOW);
   }
 
+  private List<Map<String, Object>> getFileSources() {
+    return db.select("select project_uuid as \"projectUuid\", file_uuid as \"fileUuid\", created_at as \"createdAt\", " +
+        "updated_at as \"updatedAt\", data as \"data\", data as \"data\", line_hashes as \"lineHashes\", data_hash as \"dataHash\"  from file_sources");
+  }
+
   private String formatLongDate(long dateInMs) {
     return DateUtils.formatDateTime(DateUtils.longToDate(dateInMs));
   }
index 481ea89ba0ab6ccc633c51afbaac54bc0bc26da7..2b1406f5af909342d5bb1dab11461d2c29440914 100644 (file)
@@ -117,3 +117,9 @@ CREATE TABLE "FILE_SOURCES" (
   "CREATED_AT" BIGINT NOT NULL,
   "UPDATED_AT" BIGINT NOT NULL
 );
+
+CREATE INDEX "FILE_SOURCES_PROJECT_UUID" ON "FILE_SOURCES" ("PROJECT_UUID");
+
+CREATE UNIQUE INDEX "FILE_SOURCES_FILE_UUID_UNIQ" ON "FILE_SOURCES" ("FILE_UUID");
+
+CREATE INDEX "FILE_SOURCES_UPDATED_AT" ON "FILE_SOURCES" ("UPDATED_AT");