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;
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);
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;
/**
* 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);
/*
* 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) {
}
@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));
}
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;
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);
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();
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-}
*/
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;
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>
"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,
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;
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
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
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");
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());
--- /dev/null
+/*
+ * 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());
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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());
+ }
+}
--- /dev/null
+/*
+ * 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());
+ }
+ }
+ }
+}
@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)
+
+ ;
}
}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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");
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+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");
--- /dev/null
+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");
--- /dev/null
+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");