]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-15802 Add new 'branch_uuid' column to 'portfolio_references'
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Wed, 8 Dec 2021 22:01:17 +0000 (16:01 -0600)
committersonartech <sonartech@sonarsource.com>
Mon, 27 Dec 2021 20:02:47 +0000 (20:02 +0000)
21 files changed:
server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioMapper.java
server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioReferenceDto.java [deleted file]
server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/ReferenceDetailsDto.java [deleted file]
server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/ReferenceDto.java
server/sonar-db-dao/src/main/resources/org/sonar/db/portfolio/PortfolioMapper.xml
server/sonar-db-dao/src/schema/schema-sq.ddl
server/sonar-db-dao/src/test/java/org/sonar/db/portfolio/PortfolioDaoTest.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v93/AddBranchToPortfolioReferences.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v93/AddPkToPortfolioReferences.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v93/CreateIndexForPortfolioReferences.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v93/DbVersion93.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v93/DropUniqPortfolioReferencesIndex.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v93/AddBranchToPortfolioReferencesTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v93/CreateIndexForPortfolioReferencesTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v93/DropUniqPortfolioReferencesIndexTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v93/AddBranchToPortfolioReferencesTest/schema.sql [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v93/CreateIndexForPortfolioReferencesTest/schema.sql [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v93/DropUniqPortfolioReferencesIndexTest/schema.sql [new file with mode: 0644]

index bb512f589f6982b39d72197e3cccbbd7330c1048..691ce4c137bb6c4a18406d3885afddf8b36f20b2 100644 (file)
@@ -99,7 +99,7 @@ import org.sonar.db.plugin.PluginMapper;
 import org.sonar.db.portfolio.PortfolioDto;
 import org.sonar.db.portfolio.PortfolioMapper;
 import org.sonar.db.portfolio.PortfolioProjectDto;
-import org.sonar.db.portfolio.PortfolioReferenceDto;
+import org.sonar.db.portfolio.ReferenceDto;
 import org.sonar.db.project.ApplicationProjectDto;
 import org.sonar.db.project.ProjectBadgeTokenDto;
 import org.sonar.db.project.ProjectBadgeTokenMapper;
@@ -206,7 +206,7 @@ public class MyBatis implements Startable {
     confBuilder.loadAlias("Plugin", PluginDto.class);
     confBuilder.loadAlias("Portfolio", PortfolioDto.class);
     confBuilder.loadAlias("PortfolioProject", PortfolioProjectDto.class);
-    confBuilder.loadAlias("PortfolioReference", PortfolioReferenceDto.class);
+    confBuilder.loadAlias("PortfolioReference", ReferenceDto.class);
     confBuilder.loadAlias("PrIssue", PrIssueDto.class);
     confBuilder.loadAlias("ProjectQgateAssociation", ProjectQgateAssociationDto.class);
     confBuilder.loadAlias("Project", ProjectDto.class);
index 5a4739fd23d4b15f89d8f91fab6f6cdb1c4b6c64..a51da341d13c542f2f4dbff37bb4ea8f747e2b57 100644 (file)
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.utils.System2;
 import org.sonar.core.util.UuidFactory;
@@ -59,10 +60,6 @@ public class PortfolioDao implements Dao {
 
   /**
    * select all application projects belong to the hierarchy of a portfolio
-   *
-   * @param dbSession
-   * @param rootPortfolioUuid
-   * @return
    */
   public List<ApplicationProjectDto> selectAllApplicationProjects(DbSession dbSession, String rootPortfolioUuid) {
     return mapper(dbSession).selectAllApplicationProjects(rootPortfolioUuid);
@@ -128,12 +125,12 @@ public class PortfolioDao implements Dao {
   /*
    * Portfolio references
    */
+  public void addReference(DbSession dbSession, String portfolioUuid, String referenceUuid, @Nullable String branchUuid) {
+    mapper(dbSession).insertReference(uuidFactory.create(), portfolioUuid, referenceUuid, branchUuid, system2.now());
+  }
+
   public void addReference(DbSession dbSession, String portfolioUuid, String referenceUuid) {
-    mapper(dbSession).insertReference(new PortfolioReferenceDto()
-      .setUuid(uuidFactory.create())
-      .setPortfolioUuid(portfolioUuid)
-      .setReferenceUuid(referenceUuid)
-      .setCreatedAt(system2.now()));
+    mapper(dbSession).insertReference(uuidFactory.create(), portfolioUuid, referenceUuid, null, system2.now());
   }
 
   public List<ReferenceDto> selectAllReferencesToPortfolios(DbSession dbSession) {
@@ -177,17 +174,17 @@ public class PortfolioDao implements Dao {
   }
 
   @CheckForNull
-  public ReferenceDetailsDto selectReference(DbSession dbSession, String portfolioUuid, String referenceKey) {
+  public ReferenceDto selectReference(DbSession dbSession, String portfolioUuid, String referenceKey) {
     return selectReferenceToApp(dbSession, portfolioUuid, referenceKey)
       .or(() -> selectReferenceToPortfolio(dbSession, portfolioUuid, referenceKey))
       .orElse(null);
   }
 
-  public Optional<ReferenceDetailsDto> selectReferenceToApp(DbSession dbSession, String portfolioUuid, String referenceKey) {
+  public Optional<ReferenceDto> selectReferenceToApp(DbSession dbSession, String portfolioUuid, String referenceKey) {
     return Optional.ofNullable(mapper(dbSession).selectReferenceToApplication(portfolioUuid, referenceKey));
   }
 
-  public Optional<ReferenceDetailsDto> selectReferenceToPortfolio(DbSession dbSession, String portfolioUuid, String referenceKey) {
+  public Optional<ReferenceDto> selectReferenceToPortfolio(DbSession dbSession, String portfolioUuid, String referenceKey) {
     return Optional.ofNullable(mapper(dbSession).selectReferenceToPortfolio(portfolioUuid, referenceKey));
   }
 
index 57aa1060d8b22b50a786f91efda00ffe4487a237..18eb88c66b606aeba722b53187c81d76552c0793 100644 (file)
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 import org.apache.ibatis.annotations.Param;
 import org.sonar.db.project.ApplicationProjectDto;
 import org.sonar.db.project.ProjectDto;
@@ -42,7 +43,8 @@ public interface PortfolioMapper {
 
   void deleteReferencesByPortfolioOrReferenceUuids(@Param("uuids") Set<String> uuids);
 
-  void insertReference(PortfolioReferenceDto portfolioReference);
+  void insertReference(@Param("uuid") String uuid, @Param("portfolioUuid") String portfolioUuid, @Param("referenceUuid") String referenceUuid,
+    @Nullable @Param("branchUuid") String branchUuid, @Param("createdAt") long createdAt);
 
   void insertProject(@Param("uuid") String uuid, @Param("portfolioUuid") String portfolioUuid, @Param("projectUuid") String projectUuid, @Param("createdAt") long createdAt);
 
@@ -86,9 +88,9 @@ public interface PortfolioMapper {
 
   int deleteReference(@Param("portfolioUuid") String portfolioUuid, @Param("referenceUuid") String referenceUuid);
 
-  ReferenceDetailsDto selectReferenceToPortfolio(@Param("portfolioUuid") String portfolioUuid, @Param("referenceKey") String referenceKey);
+  ReferenceDto selectReferenceToPortfolio(@Param("portfolioUuid") String portfolioUuid, @Param("referenceKey") String referenceKey);
 
-  ReferenceDetailsDto selectReferenceToApplication(@Param("portfolioUuid") String portfolioUuid, @Param("referenceKey") String referenceKey);
+  ReferenceDto selectReferenceToApplication(@Param("portfolioUuid") String portfolioUuid, @Param("referenceKey") String referenceKey);
 
   void deleteAllProjects();
 
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioReferenceDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioReferenceDto.java
deleted file mode 100644 (file)
index 1a39ad0..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 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.db.portfolio;
-
-public class PortfolioReferenceDto {
-  private String uuid;
-  private String portfolioUuid;
-  private String referenceUuid;
-  private long createdAt;
-
-  public String getUuid() {
-    return uuid;
-  }
-
-  public PortfolioReferenceDto setUuid(String uuid) {
-    this.uuid = uuid;
-    return this;
-  }
-
-  public String getPortfolioUuid() {
-    return portfolioUuid;
-  }
-
-  public PortfolioReferenceDto setPortfolioUuid(String portfolioUuid) {
-    this.portfolioUuid = portfolioUuid;
-    return this;
-  }
-
-  public String getReferenceUuid() {
-    return referenceUuid;
-  }
-
-  public PortfolioReferenceDto setReferenceUuid(String referenceUuid) {
-    this.referenceUuid = referenceUuid;
-    return this;
-  }
-
-
-  public long getCreatedAt() {
-    return createdAt;
-  }
-
-  public PortfolioReferenceDto setCreatedAt(long createdAt) {
-    this.createdAt = createdAt;
-    return this;
-  }
-}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/ReferenceDetailsDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/ReferenceDetailsDto.java
deleted file mode 100644 (file)
index 7e75a7a..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 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.db.portfolio;
-
-public class ReferenceDetailsDto extends ReferenceDto {
-  private String targetName;
-  private String targetKey;
-
-  public String getTargetName() {
-    return targetName;
-  }
-
-  public ReferenceDetailsDto setTargetName(String targetName) {
-    this.targetName = targetName;
-    return this;
-  }
-
-  public String getTargetKey() {
-    return targetKey;
-  }
-
-  public ReferenceDetailsDto setTargetKey(String targetKey) {
-    this.targetKey = targetKey;
-    return this;
-  }
-}
index 1aa627165fe5c29c34b9bde455ea0ba972a2e6fa..80e1f6e8a39746782f8feb9bd499b82815616dd7 100644 (file)
  */
 package org.sonar.db.portfolio;
 
+import java.util.Set;
+
 public class ReferenceDto {
   private String sourceUuid;
   private String sourceRootUuid;
   private String targetUuid;
   private String targetRootUuid;
+  private String targetName;
+  private String targetKey;
+  private Set<String> branchUuids;
+
+  public String getTargetName() {
+    return targetName;
+  }
+
+  public ReferenceDto setTargetName(String targetName) {
+    this.targetName = targetName;
+    return this;
+  }
+
+  public String getTargetKey() {
+    return targetKey;
+  }
+
+  public ReferenceDto setTargetKey(String targetKey) {
+    this.targetKey = targetKey;
+    return this;
+  }
+
+  public Set<String> getBranchUuids() {
+    return branchUuids;
+  }
+
+  public ReferenceDto setBranchUuids(Set<String> branchUuids) {
+    this.branchUuids = branchUuids;
+    return this;
+  }
 
   public String getSourceUuid() {
     return sourceUuid;
index 16b8d7c99043adaa7e678b2c738f2bc3eaab28ae..5c43e2eba7d9e396abdf106cbb796415ba5d7c0b 100644 (file)
     ppb.branch_uuid as branchUuid
   </sql>
 
+  <sql id="portfolioReferenceColumns">
+    source.uuid as sourceUuid,
+    source.root_uuid as sourceRootUuid,
+    target.uuid as targetUuid,
+    target.root_uuid as targetRootUuid,
+    null as branchUuid,
+    target.name as targetName,
+    target.kee as targetKey
+  </sql>
+
+  <sql id="appReferenceColumns">
+    source.uuid as sourceUuid,
+    source.root_uuid as sourceRootUuid,
+    target.uuid as targetUuid,
+    target.uuid as targetRootUuid,
+    pr.branch_uuid as branchUuid,
+    target.name as targetName,
+    target.kee as targetKey
+  </sql>
+
   <resultMap id="portfolioProjectResult" type="PortfolioProject" autoMapping="true">
     <id property="uuid" column="portfolioProject_uuid"/>
     <collection property="branchUuids" ofType="string">
     </collection>
   </resultMap>
 
+  <resultMap id="referenceResult" type="PortfolioReference" autoMapping="true">
+    <id property="sourceUuid" column="sourceUuid"/>
+    <id property="targetUuid" column="targetUuid"/>
+    <collection property="branchUuids" ofType="string">
+      <result column="branchUuid"/>
+    </collection>
+  </resultMap>
+
   <select id="selectByUuid" parameterType="String" resultType="Portfolio">
     SELECT
       <include refid="portfolioColumns"/>
     AND reference_uuid = #{referenceUuid,jdbcType=VARCHAR}
   </delete>
 
-  <select id="selectReferenceToApplication" resultType="org.sonar.db.portfolio.ReferenceDetailsDto">
+  <select id="selectReferenceToApplication" resultMap="referenceResult">
     SELECT
-      source.uuid as sourceUuid,
-      source.root_uuid as sourceRootUuid,
-      target.uuid as targetUuid,
-      target.uuid as targetRootUuid,
-      target.name as targetName,
-      target.kee as targetKey
+    <include refid="appReferenceColumns"/>
     FROM portfolio_references pr
-     INNER JOIN portfolios source ON pr.portfolio_uuid = source.uuid
-     INNER JOIN projects target ON pr.reference_uuid = target.uuid AND target.qualifier = 'APP'
-     WHERE pr.portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR}
-     AND target.kee=#{referenceKey,jdbcType=VARCHAR}
+    INNER JOIN portfolios source ON pr.portfolio_uuid = source.uuid
+    INNER JOIN projects target ON pr.reference_uuid = target.uuid AND target.qualifier = 'APP'
+    WHERE pr.portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR}
+    AND target.kee=#{referenceKey,jdbcType=VARCHAR}
   </select>
 
-  <select id="selectReferenceToPortfolio" resultType="org.sonar.db.portfolio.ReferenceDetailsDto">
+  <select id="selectReferenceToPortfolio" resultMap="referenceResult">
     SELECT
-      source.uuid as sourceUuid,
-      source.root_uuid as sourceRootUuid,
-      target.uuid as targetUuid,
-      target.root_uuid as targetRootUuid,
-      target.name as targetName,
-      target.kee as targetKey
+    <include refid="portfolioReferenceColumns"/>
     FROM portfolio_references pr
-     INNER JOIN portfolios source ON pr.portfolio_uuid = source.uuid
-     INNER JOIN portfolios target ON pr.reference_uuid = target.uuid
-     WHERE pr.portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR}
-     AND target.kee=#{referenceKey,jdbcType=VARCHAR}
+    INNER JOIN portfolios source ON pr.portfolio_uuid = source.uuid
+    INNER JOIN portfolios target ON pr.reference_uuid = target.uuid
+    WHERE pr.portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR}
+    AND target.kee=#{referenceKey,jdbcType=VARCHAR}
   </select>
 
    <insert id="insert" parameterType="Portfolio">
     )
   </insert>
 
-  <select id="selectAllReferencesToPortfolios" resultType="org.sonar.db.portfolio.ReferenceDto">
+  <select id="selectAllReferencesToPortfolios" resultMap="referenceResult">
     SELECT
-      source.uuid as sourceUuid,
-      source.root_uuid as sourceRootUuid,
-      target.uuid as targetUuid,
-      target.root_uuid as targetRootUuid
+    <include refid="portfolioReferenceColumns"/>
     FROM portfolio_references pr
     INNER JOIN portfolios source ON pr.portfolio_uuid = source.uuid
     INNER JOIN portfolios target ON pr.reference_uuid = target.uuid
   </select>
 
-  <select id="selectAllReferencesToApplications" resultType="org.sonar.db.portfolio.ReferenceDto">
+  <select id="selectAllReferencesToApplications" resultMap="referenceResult">
     SELECT
-    source.uuid as sourceUuid,
-    source.root_uuid as sourceRootUuid,
-    target.uuid as targetUuid,
-    target.uuid as targetRootUuid
+    <include refid="appReferenceColumns"/>
     FROM portfolio_references pr
     INNER JOIN portfolios source ON pr.portfolio_uuid = source.uuid
-    INNER JOIN projects target ON pr.reference_uuid = target.uuid where target.qualifier = 'APP'
+    INNER JOIN projects target ON pr.reference_uuid = target.uuid
+    WHERE target.qualifier = 'APP'
   </select>
 
   <select id="selectAllDirectChildApplications" resultType="Project">
     WHERE pr.portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR}
   </select>
 
-  <select id="selectAllReferencesInHierarchy" resultType="org.sonar.db.portfolio.ReferenceDto">
+  <select id="selectAllReferencesInHierarchy" resultMap="referenceResult">
     (SELECT
-    source.uuid as sourceUuid,
-    source.root_uuid as sourceRootUuid,
-    target.uuid as targetUuid,
-    target.root_uuid as targetRootUuid
+    <include refid="portfolioReferenceColumns"/>
     FROM portfolio_references pr
     INNER JOIN portfolios source ON pr.portfolio_uuid = source.uuid
     INNER JOIN portfolios target ON pr.reference_uuid = target.uuid
     WHERE source.root_uuid = #{rootUuid,jdbcType=VARCHAR}
     UNION
     SELECT
-    source.uuid as sourceUuid,
-    source.root_uuid as sourceRootUuid,
-    target.uuid as targetUuid,
-    target.uuid as targetRootUuid
+    <include refid="appReferenceColumns"/>
     FROM portfolio_references pr
     INNER JOIN portfolios source ON pr.portfolio_uuid = source.uuid
     INNER JOIN projects target ON pr.reference_uuid = target.uuid
     END;
   </delete>
 
-  <insert id="insertReference" parameterType="PortfolioReference">
+  <insert id="insertReference" parameterType="map">
     INSERT INTO portfolio_references (
       uuid,
       portfolio_uuid,
       reference_uuid,
+      branch_uuid,
       created_at
     )
     VALUES (
-    #{uuid,jdbcType=VARCHAR},
-    #{portfolioUuid,jdbcType=VARCHAR},
-    #{referenceUuid,jdbcType=VARCHAR},
-    #{createdAt,jdbcType=BIGINT}
+      #{uuid,jdbcType=VARCHAR},
+      #{portfolioUuid,jdbcType=VARCHAR},
+      #{referenceUuid,jdbcType=VARCHAR},
+      #{branchUuid,jdbcType=VARCHAR},
+      #{createdAt,jdbcType=BIGINT}
     )
   </insert>
 
index 8958e1331f531084fcbe6d6e573404e4ce64491f..cbeabcbe8bc5fdb0edc14ed0c27159fd634b5b44 100644 (file)
@@ -585,10 +585,11 @@ CREATE TABLE "PORTFOLIO_REFERENCES"(
     "UUID" VARCHAR(40) NOT NULL,
     "PORTFOLIO_UUID" VARCHAR(40) NOT NULL,
     "REFERENCE_UUID" VARCHAR(40) NOT NULL,
-    "CREATED_AT" BIGINT NOT NULL
+    "CREATED_AT" BIGINT NOT NULL,
+    "BRANCH_UUID" VARCHAR(255)
 );
 ALTER TABLE "PORTFOLIO_REFERENCES" ADD CONSTRAINT "PK_PORTFOLIO_REFERENCES" PRIMARY KEY("UUID");
-CREATE UNIQUE INDEX "UNIQ_PORTFOLIO_REFERENCES" ON "PORTFOLIO_REFERENCES"("PORTFOLIO_UUID", "REFERENCE_UUID");
+CREATE UNIQUE INDEX "UNIQ_PORTFOLIO_REFERENCES" ON "PORTFOLIO_REFERENCES"("PORTFOLIO_UUID", "REFERENCE_UUID", "BRANCH_UUID");
 
 CREATE TABLE "PORTFOLIOS"(
     "UUID" VARCHAR(40) NOT NULL,
index 5a6c6b4818d11d2680d602dacbe11096dc442a94..8ab402434ac8eee5b71ea3b4908485fd72b89b43 100644 (file)
@@ -28,10 +28,12 @@ import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.audit.AuditPersister;
+import org.sonar.db.component.BranchDto;
 import org.sonar.db.project.ApplicationProjectDto;
 import org.sonar.db.project.ProjectDto;
 
 import static java.util.Collections.emptySet;
+import static java.util.Collections.singleton;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -229,8 +231,8 @@ public class PortfolioDaoTest {
     portfolioDao.addReference(session, "portfolio3", "app1");
 
     assertThat(portfolioDao.selectAllReferencesToPortfolios(session))
-      .extracting(ReferenceDto::getSourceUuid, ReferenceDto::getTargetUuid)
-      .containsOnly(tuple("portfolio1", "portfolio2"), tuple("portfolio2", "portfolio3"));
+      .extracting(ReferenceDto::getSourceUuid, ReferenceDto::getTargetUuid, ReferenceDto::getBranchUuids)
+      .containsOnly(tuple("portfolio1", "portfolio2", emptySet()), tuple("portfolio2", "portfolio3", emptySet()));
   }
 
   @Test
@@ -242,11 +244,14 @@ public class PortfolioDaoTest {
 
     portfolioDao.addReference(session, "portfolio1", "portfolio2");
     portfolioDao.addReference(session, "portfolio2", "portfolio3");
-    portfolioDao.addReference(session, "portfolio3", app1.getUuid());
+    portfolioDao.addReference(session, "portfolio3", app1.getUuid(), "branch1");
+    portfolioDao.addReference(session, "portfolio2", app1.getUuid());
 
     assertThat(portfolioDao.selectAllReferencesToApplications(session))
-      .extracting(ReferenceDto::getSourceUuid, ReferenceDto::getTargetUuid)
-      .containsOnly(tuple("portfolio3", app1.getUuid()));
+      .extracting(ReferenceDto::getSourceUuid, ReferenceDto::getTargetUuid, ReferenceDto::getTargetRootUuid, ReferenceDto::getBranchUuids)
+      .containsOnly(
+        tuple("portfolio3", app1.getUuid(), app1.getUuid(), singleton("branch1")),
+        tuple("portfolio2", app1.getUuid(), app1.getUuid(), emptySet()));
   }
 
   @Test
@@ -330,6 +335,26 @@ public class PortfolioDaoTest {
     assertThat(portfolioDao.selectReferenceToPortfolio(db.getSession(), portfolio.getUuid(), app1.getKey())).isEmpty();
   }
 
+  @Test
+  public void select_reference_to_app_with_branches() {
+    PortfolioDto portfolio = db.components().insertPrivatePortfolioDto("portfolio1");
+    ProjectDto app = db.components().insertPrivateApplicationDto(p -> p.setDbKey("app").setName("app"));
+    BranchDto branch1 = db.components().insertProjectBranch(app, b -> b.setExcludeFromPurge(true));
+    BranchDto branch2 = db.components().insertProjectBranch(app, b -> b.setExcludeFromPurge(true));
+
+    db.components().addPortfolioReference(portfolio, app.getUuid());
+    db.components().addPortfolioApplicationBranch(portfolio.getUuid(), app.getUuid(), branch1.getUuid());
+    db.components().addPortfolioApplicationBranch(portfolio.getUuid(), app.getUuid(), branch2.getUuid());
+
+    var appFromDb = portfolioDao.selectReferenceToApp(db.getSession(), portfolio.getUuid(), app.getKey());
+    assertThat(appFromDb).isPresent();
+
+    assertThat(appFromDb.get())
+      .extracting(ReferenceDto::getTargetKey, ReferenceDto::getTargetName, ReferenceDto::getBranchUuids)
+      .containsExactly("app", "app", Set.of(branch1.getUuid(), branch2.getUuid()));
+
+  }
+
   @Test
   public void select_reference_to_portfolio_by_key() {
     PortfolioDto portfolio1 = db.components().insertPrivatePortfolioDto("portfolio1");
index a08cc4ee0382bc430769e282f6c0676655abc2d1..2a8524b6fdb99251975e3dd1a7400b43a36dca20 100644 (file)
@@ -364,8 +364,13 @@ public class ComponentDbTester {
     return insertComponentAndBranchAndProject(ComponentTesting.newSubPortfolio(view), view.isPrivate(), defaults(), dtoPopulator);
   }
 
+  public void addPortfolioApplicationBranch(String portfolioUuid, String applicationUuid, String branchUuid) {
+    dbClient.portfolioDao().addReference(db.getSession(), portfolioUuid, applicationUuid, branchUuid);
+    db.commit();
+  }
+
   private ComponentDto insertComponentAndBranchAndProject(ComponentDto component, @Nullable Boolean isPrivate, Consumer<BranchDto> branchPopulator,
-    Consumer<ComponentDto> componentDtoPopulator, Consumer<ProjectDto> projectDtoPopulator) {
+                                                          Consumer<ComponentDto> componentDtoPopulator, Consumer<ProjectDto> projectDtoPopulator) {
     insertComponentImpl(component, isPrivate, componentDtoPopulator);
 
     ProjectDto projectDto = toProjectDto(component, System2.INSTANCE.now());
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v93/AddBranchToPortfolioReferences.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v93/AddBranchToPortfolioReferences.java
new file mode 100644 (file)
index 0000000..9ddc5fd
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.v93;
+
+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.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class AddBranchToPortfolioReferences extends DdlChange {
+  private static final String TABLE_NAME = "portfolio_references";
+  private static final String COLUMN_NAME = "branch_uuid";
+
+  public AddBranchToPortfolioReferences(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(VarcharColumnDef.newVarcharColumnDefBuilder().setColumnName(COLUMN_NAME).setIsNullable(true).setLimit(255).build())
+          .build());
+      }
+    }
+  }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v93/AddPkToPortfolioReferences.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v93/AddPkToPortfolioReferences.java
new file mode 100644 (file)
index 0000000..99d53d2
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.v93;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.sql.AddPrimaryKeyBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class AddPkToPortfolioReferences extends DdlChange {
+  private static final String TABLE_NAME = "portfolio_references";
+
+  public AddPkToPortfolioReferences(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new AddPrimaryKeyBuilder(TABLE_NAME, "uuid", "portfolio_uuid", "reference_uuid").build());
+  }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v93/CreateIndexForPortfolioReferences.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v93/CreateIndexForPortfolioReferences.java
new file mode 100644 (file)
index 0000000..49396d1
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.v93;
+
+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.sql.CreateIndexBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class CreateIndexForPortfolioReferences extends DdlChange {
+  private static final String TABLE_NAME = "portfolio_references";
+  private static final String INDEX_NAME = "uniq_portfolio_references";
+
+  public CreateIndexForPortfolioReferences(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    try (Connection c = getDatabase().getDataSource().getConnection()) {
+
+      if (!DatabaseUtils.indexExistsIgnoreCase(TABLE_NAME, INDEX_NAME, c)) {
+        context.execute(new CreateIndexBuilder()
+          .setTable(TABLE_NAME)
+          .setName(INDEX_NAME)
+          .addColumn("portfolio_uuid")
+          .addColumn("reference_uuid")
+          .addColumn("branch_uuid")
+          .setUnique(true)
+          .build());
+      }
+    }
+  }
+}
index b3ca24d032ab3edb62778bc59d0a9565d10faf05..db2ce3563e4834d82c65f1613a424deb1ead4ef4 100644 (file)
@@ -26,6 +26,11 @@ public class DbVersion93 implements DbVersion {
   @Override
   public void addSteps(MigrationStepRegistry registry) {
     registry
-      .add(6201, "Fix usage of deprecated column in MSSQL", FixUsageOfDeprecatedColumnsMsSQL.class);
+      .add(6201, "Fix usage of deprecated column in MSSQL", FixUsageOfDeprecatedColumnsMsSQL.class)
+      .add(6202, "Drop index 'uniq_portfolio_references'", DropUniqPortfolioReferencesIndex.class)
+      .add(6203, "Add column 'branch_uuid' to 'portfolio_references'", AddBranchToPortfolioReferences.class)
+      .add(6204, "Create index 'uniq_portfolio_references'", CreateIndexForPortfolioReferences.class)
+
+    ;
   }
 }
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v93/DropUniqPortfolioReferencesIndex.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v93/DropUniqPortfolioReferencesIndex.java
new file mode 100644 (file)
index 0000000..abba98c
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.v93;
+
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DropIndexChange;
+
+public class DropUniqPortfolioReferencesIndex extends DropIndexChange {
+  private static final String INDEX_NAME = "uniq_portfolio_references";
+  private static final String TABLE_NAME = "portfolio_references";
+
+  public DropUniqPortfolioReferencesIndex(Database db) {
+    super(db, INDEX_NAME, TABLE_NAME);
+  }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v93/AddBranchToPortfolioReferencesTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v93/AddBranchToPortfolioReferencesTest.java
new file mode 100644 (file)
index 0000000..3138385
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.v93;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+
+public class AddBranchToPortfolioReferencesTest {
+  private static final String TABLE_NAME = "portfolio_references";
+  private static final String COLUMN_NAME = "branch_uuid";
+
+  @Rule
+  public final CoreDbTester db = CoreDbTester.createForSchema(AddBranchToPortfolioReferencesTest.class, "schema.sql");
+
+  private final AddBranchToPortfolioReferences underTest = new AddBranchToPortfolioReferences(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.VARCHAR, 255, true);
+  }
+
+  @Test
+  public void migration_should_be_reentrant() throws SQLException {
+    db.assertColumnDoesNotExist(TABLE_NAME, COLUMN_NAME);
+    underTest.execute();
+    underTest.execute();
+    db.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, Types.VARCHAR, 255, true);
+  }
+
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v93/CreateIndexForPortfolioReferencesTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v93/CreateIndexForPortfolioReferencesTest.java
new file mode 100644 (file)
index 0000000..f2ec81d
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.v93;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+
+public class CreateIndexForPortfolioReferencesTest {
+  private final static String TABLE_NAME = "portfolio_references";
+  private final static String INDEX_NAME = "uniq_portfolio_references";
+
+  @Rule
+  public final CoreDbTester db = CoreDbTester.createForSchema(CreateIndexForPortfolioReferencesTest.class, "schema.sql");
+
+  private final CreateIndexForPortfolioReferences underTest = new CreateIndexForPortfolioReferences(db.database());
+
+  @Test
+  public void should_create_index() throws SQLException {
+    db.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME);
+    underTest.execute();
+    db.assertUniqueIndex(TABLE_NAME, INDEX_NAME, "portfolio_uuid", "reference_uuid", "branch_uuid");
+  }
+
+  @Test
+  public void migration_should_be_reentrant() throws SQLException {
+    db.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME);
+
+    underTest.execute();
+    //re-entrant
+    underTest.execute();
+
+    db.assertUniqueIndex(TABLE_NAME, INDEX_NAME, "portfolio_uuid", "reference_uuid", "branch_uuid");
+  }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v93/DropUniqPortfolioReferencesIndexTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v93/DropUniqPortfolioReferencesIndexTest.java
new file mode 100644 (file)
index 0000000..aee0c7b
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.v93;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+
+public class DropUniqPortfolioReferencesIndexTest {
+  private static final String INDEX_NAME = "uniq_portfolio_references";
+  private static final String TABLE_NAME = "portfolio_references";
+
+  @Rule
+  public final CoreDbTester db = CoreDbTester.createForSchema(DropUniqPortfolioReferencesIndexTest.class, "schema.sql");
+
+  private final DropUniqPortfolioReferencesIndex underTest = new DropUniqPortfolioReferencesIndex(db.database());
+
+  @Test
+  public void migration_should_drop_unique_index() throws SQLException {
+    db.assertUniqueIndex(TABLE_NAME, INDEX_NAME, "portfolio_uuid", "reference_uuid");
+    underTest.execute();
+    db.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME);
+  }
+
+  @Test
+  public void migration_should_be_reentrant() throws SQLException {
+    db.assertUniqueIndex(TABLE_NAME, INDEX_NAME, "portfolio_uuid", "reference_uuid");
+    underTest.execute();
+    // re-entrant
+    underTest.execute();
+    db.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME);
+  }
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v93/AddBranchToPortfolioReferencesTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v93/AddBranchToPortfolioReferencesTest/schema.sql
new file mode 100644 (file)
index 0000000..accb58c
--- /dev/null
@@ -0,0 +1,8 @@
+CREATE TABLE "PORTFOLIO_REFERENCES"(
+    "UUID" VARCHAR(40) NOT NULL,
+    "PORTFOLIO_UUID" VARCHAR(40) NOT NULL,
+    "REFERENCE_UUID" VARCHAR(40) NOT NULL,
+    "CREATED_AT" BIGINT NOT NULL
+);
+ALTER TABLE "PORTFOLIO_REFERENCES" ADD CONSTRAINT "PK_PORTFOLIO_REFERENCES" PRIMARY KEY("UUID");
+CREATE UNIQUE INDEX "UNIQ_PORTFOLIO_REFERENCES" ON "PORTFOLIO_REFERENCES"("PORTFOLIO_UUID", "REFERENCE_UUID");
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v93/CreateIndexForPortfolioReferencesTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v93/CreateIndexForPortfolioReferencesTest/schema.sql
new file mode 100644 (file)
index 0000000..c48664a
--- /dev/null
@@ -0,0 +1,8 @@
+CREATE TABLE "PORTFOLIO_REFERENCES"(
+    "UUID" VARCHAR(40) NOT NULL,
+    "PORTFOLIO_UUID" VARCHAR(40) NOT NULL,
+    "REFERENCE_UUID" VARCHAR(40) NOT NULL,
+    "BRANCH_UUID" VARCHAR(255),
+    "CREATED_AT" BIGINT NOT NULL
+);
+ALTER TABLE "PORTFOLIO_REFERENCES" ADD CONSTRAINT "PK_PORTFOLIO_REFERENCES" PRIMARY KEY("UUID");
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v93/DropUniqPortfolioReferencesIndexTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v93/DropUniqPortfolioReferencesIndexTest/schema.sql
new file mode 100644 (file)
index 0000000..accb58c
--- /dev/null
@@ -0,0 +1,8 @@
+CREATE TABLE "PORTFOLIO_REFERENCES"(
+    "UUID" VARCHAR(40) NOT NULL,
+    "PORTFOLIO_UUID" VARCHAR(40) NOT NULL,
+    "REFERENCE_UUID" VARCHAR(40) NOT NULL,
+    "CREATED_AT" BIGINT NOT NULL
+);
+ALTER TABLE "PORTFOLIO_REFERENCES" ADD CONSTRAINT "PK_PORTFOLIO_REFERENCES" PRIMARY KEY("UUID");
+CREATE UNIQUE INDEX "UNIQ_PORTFOLIO_REFERENCES" ON "PORTFOLIO_REFERENCES"("PORTFOLIO_UUID", "REFERENCE_UUID");