]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-17352 Migrate copy component UUIDs
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Tue, 11 Oct 2022 19:31:58 +0000 (14:31 -0500)
committersonartech <sonartech@sonarsource.com>
Wed, 12 Oct 2022 20:03:44 +0000 (20:03 +0000)
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v97/DbVersion97.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v97/FixCopyComponentUuid.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v97/FixCopyComponentUuidTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v97/FixCopyComponentUuidTest/schema.sql [new file with mode: 0644]

index 8de3f411b3461a04a4847f79ab344836c60bbb26..e79a9ea9f414571c3aa8cc65b24876ab0bbebfd4 100644 (file)
@@ -35,7 +35,8 @@ public class DbVersion97 implements DbVersion {
       .add(6605, "Create index for 'branch_uuid' in 'components'", CreateIndexForComponentsBranchUuid.class)
 
       .add(6606, "Drop index for 'kee' in 'components'", DropIndexForComponentsKey.class)
-      .add(6607, "Remove branch information from 'kee' in 'components'", RemoveBranchInformationFromComponentsKey.class)
-      .add(6608, "Add unique index on 'kee','branch_uuid' in 'components'", CreateUniqueIndexForComponentsKeeAndBranchUuid.class);
+      .add(6607, "Fix copy component UUID", FixCopyComponentUuid.class)
+      .add(6608, "Remove branch information from 'kee' in 'components'", RemoveBranchInformationFromComponentsKey.class)
+      .add(6609, "Add unique index on 'kee','branch_uuid' in 'components'", CreateUniqueIndexForComponentsKeeAndBranchUuid.class);
   }
 }
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v97/FixCopyComponentUuid.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v97/FixCopyComponentUuid.java
new file mode 100644 (file)
index 0000000..0494f7c
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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.v97;
+
+import java.sql.SQLException;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.MassUpdate;
+
+public class FixCopyComponentUuid extends DataChange {
+  private static final String BRANCH_IDENTIFIER = ":BRANCH:";
+  private static final String SELECT_QUERY = "select kee, uuid, copy_component_uuid from components where copy_component_uuid is not null";
+  private static final String UPDATE_QUERY = "update components set copy_component_uuid = ? where uuid = ?";
+
+  public FixCopyComponentUuid(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    MassUpdate massUpdate = context.prepareMassUpdate();
+    massUpdate.select(SELECT_QUERY);
+    massUpdate.update(UPDATE_QUERY);
+    massUpdate.execute((row, update) -> {
+      String componentKey = row.getString(1);
+      String componentUuid = row.getString(2);
+      String copyComponentUuid = row.getString(3);
+
+      String branchKey = StringUtils.substringAfterLast(componentKey, BRANCH_IDENTIFIER);
+
+      if (StringUtils.isEmpty(branchKey)) {
+        return false;
+      }
+
+      String branchUuid = context.prepareSelect("select uuid from project_branches where project_uuid = ? and branch_type = 'BRANCH' and kee = ?")
+        .setString(1, copyComponentUuid)
+        .setString(2, branchKey)
+        .get(t -> t.getString(1));
+
+      if (branchUuid != null && !branchUuid.equals(copyComponentUuid)) {
+        update.setString(1, branchUuid)
+          .setString(2, componentUuid);
+        return true;
+      }
+
+      return false;
+    });
+  }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v97/FixCopyComponentUuidTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v97/FixCopyComponentUuidTest.java
new file mode 100644 (file)
index 0000000..d0d4da7
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * 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.v97;
+
+import java.sql.SQLException;
+import java.util.Map;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DataChange;
+
+import static java.util.Map.entry;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FixCopyComponentUuidTest {
+  @Rule
+  public final CoreDbTester db = CoreDbTester.createForSchema(FixCopyComponentUuidTest.class, "schema.sql");
+
+  private DataChange underTest;
+
+  @Before
+  public void before() {
+    underTest = new FixCopyComponentUuid(db.database());
+  }
+
+  @Test
+  public void updates_copy_component_uuid() throws SQLException {
+    insert();
+
+    underTest.execute();
+
+    checkResults();
+  }
+
+  @Test
+  public void should_be_reentrant() throws SQLException {
+    insert();
+
+    underTest.execute();
+    underTest.execute();
+
+    checkResults();
+  }
+
+  public void checkResults() {
+    assertThat(getCopyComponentUuidByUuid())
+      .containsOnly(
+        entry("uuid1", ""),
+        entry("uuid2", ""),
+        entry("uuid3", ""),
+        entry("uuid4", "uuid1"),
+        entry("uuid5", ""),
+        entry("uuid6", "uuid2")
+      );
+  }
+
+  private void insert() {
+    // project with a branch
+    insertBranch("uuid1", "uuid1", "master");
+    insertBranch("uuid2", "uuid1", "branch1");
+    insertComponents("uuid1", "project1", null, null);
+    insertComponents("uuid2", "project1:BRANCH:branch1", "uuid1", null);
+
+    // app
+    insertBranch("uuid3", "uuid3", "master");
+    insertComponents("uuid3", "app", null, null);
+    insertComponents("uuid4", "appb1project1", null, "uuid1");
+
+    // app branch
+    insertBranch("uuid5", "uuid3", "b1");
+    insertComponents("uuid5", "app:BRANCH:b1", "uuid3", null);
+    // this copyComponentUuid needs to be fixed to point to uuid2
+    insertComponents("uuid6", "appb1project1:BRANCH:branch1", "uuid3", "uuid1");
+  }
+
+  private Map<String, String> getCopyComponentUuidByUuid() {
+    return db.select("select uuid, copy_component_uuid from components").stream()
+      .collect(Collectors.toMap(e -> (String) e.get("UUID"), e -> e.get("COPY_COMPONENT_UUID") == null ? "" : (String) e.get("COPY_COMPONENT_UUID")));
+  }
+
+  private void insertBranch(String uuid, String projectUuid, String key) {
+    db.executeInsert("project_branches",
+      "kee", key,
+      "uuid", uuid,
+      "project_uuid", projectUuid,
+      "branch_type", "BRANCH",
+      "need_issue_sync", "false",
+      "created_at", "1",
+      "updated_at", "1");
+  }
+
+  private void insertComponents(String uuid, String key, @Nullable String mainBranchUuid, @Nullable String copyComponentUuid) {
+    db.executeInsert("components",
+      "enabled", true,
+      "uuid", uuid,
+      "kee", key,
+      "branch_uuid", "branch_uuid",
+      "root_uuid", "root_uuid",
+      "uuid_path", "uuid_path",
+      "private", false,
+      "copy_component_uuid", copyComponentUuid,
+      "main_branch_project_uuid", mainBranchUuid);
+  }
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v97/FixCopyComponentUuidTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v97/FixCopyComponentUuidTest/schema.sql
new file mode 100644 (file)
index 0000000..2337dc2
--- /dev/null
@@ -0,0 +1,57 @@
+CREATE TABLE "COMPONENTS"(
+                             "UUID" CHARACTER VARYING(50) NOT NULL,
+                             "KEE" CHARACTER VARYING(1000),
+                             "DEPRECATED_KEE" CHARACTER VARYING(400),
+                             "NAME" CHARACTER VARYING(2000),
+                             "LONG_NAME" CHARACTER VARYING(2000),
+                             "DESCRIPTION" CHARACTER VARYING(2000),
+                             "ENABLED" BOOLEAN DEFAULT TRUE NOT NULL,
+                             "SCOPE" CHARACTER VARYING(3),
+                             "QUALIFIER" CHARACTER VARYING(10),
+                             "PRIVATE" BOOLEAN NOT NULL,
+                             "ROOT_UUID" CHARACTER VARYING(50) NOT NULL,
+                             "LANGUAGE" CHARACTER VARYING(20),
+                             "COPY_COMPONENT_UUID" CHARACTER VARYING(50),
+                             "PATH" CHARACTER VARYING(2000),
+                             "UUID_PATH" CHARACTER VARYING(1500) NOT NULL,
+                             "BRANCH_UUID" CHARACTER VARYING(50) NOT NULL,
+                             "MODULE_UUID" CHARACTER VARYING(50),
+                             "MODULE_UUID_PATH" CHARACTER VARYING(1500),
+                             "MAIN_BRANCH_PROJECT_UUID" CHARACTER VARYING(50),
+                             "B_CHANGED" BOOLEAN,
+                             "B_NAME" CHARACTER VARYING(500),
+                             "B_LONG_NAME" CHARACTER VARYING(500),
+                             "B_DESCRIPTION" CHARACTER VARYING(2000),
+                             "B_ENABLED" BOOLEAN,
+                             "B_QUALIFIER" CHARACTER VARYING(10),
+                             "B_LANGUAGE" CHARACTER VARYING(20),
+                             "B_COPY_COMPONENT_UUID" CHARACTER VARYING(50),
+                             "B_PATH" CHARACTER VARYING(2000),
+                             "B_UUID_PATH" CHARACTER VARYING(1500),
+                             "B_MODULE_UUID" CHARACTER VARYING(50),
+                             "B_MODULE_UUID_PATH" CHARACTER VARYING(1500),
+                             "CREATED_AT" TIMESTAMP
+);
+CREATE INDEX "PROJECTS_MODULE_UUID" ON "COMPONENTS"("MODULE_UUID" NULLS FIRST);
+CREATE INDEX "PROJECTS_QUALIFIER" ON "COMPONENTS"("QUALIFIER" NULLS FIRST);
+CREATE INDEX "PROJECTS_ROOT_UUID" ON "COMPONENTS"("ROOT_UUID" NULLS FIRST);
+CREATE INDEX "IDX_MAIN_BRANCH_PRJ_UUID" ON "COMPONENTS"("MAIN_BRANCH_PROJECT_UUID" NULLS FIRST);
+CREATE UNIQUE INDEX "COMPONENTS_UUID" ON "COMPONENTS"("UUID" NULLS FIRST);
+CREATE INDEX "COMPONENTS_BRANCH_UUID" ON "COMPONENTS"("BRANCH_UUID" NULLS FIRST);
+
+CREATE TABLE "PROJECT_BRANCHES"(
+    "UUID" CHARACTER VARYING(50) NOT NULL,
+    "PROJECT_UUID" CHARACTER VARYING(50) NOT NULL,
+    "KEE" CHARACTER VARYING(255) NOT NULL,
+    "BRANCH_TYPE" CHARACTER VARYING(12) NOT NULL,
+    "MERGE_BRANCH_UUID" CHARACTER VARYING(50),
+    "PULL_REQUEST_BINARY" BINARY LARGE OBJECT,
+    "MANUAL_BASELINE_ANALYSIS_UUID" CHARACTER VARYING(40),
+    "CREATED_AT" BIGINT NOT NULL,
+    "UPDATED_AT" BIGINT NOT NULL,
+    "EXCLUDE_FROM_PURGE" BOOLEAN DEFAULT FALSE NOT NULL,
+    "NEED_ISSUE_SYNC" BOOLEAN NOT NULL
+);
+ALTER TABLE "PROJECT_BRANCHES" ADD CONSTRAINT "PK_PROJECT_BRANCHES" PRIMARY KEY("UUID");
+CREATE UNIQUE INDEX "UNIQ_PROJECT_BRANCHES" ON "PROJECT_BRANCHES"("BRANCH_TYPE" NULLS FIRST, "PROJECT_UUID" NULLS FIRST, "KEE" NULLS FIRST);
+