diff options
23 files changed, 747 insertions, 113 deletions
diff --git a/server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java b/server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java index 1feb4af67ad..15c4ff52275 100644 --- a/server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java +++ b/server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java @@ -74,6 +74,7 @@ public final class SqTables { "plugins", "portfolios", "portfolio_projects", + "portfolio_proj_branches", "portfolio_references", "projects", "project_alm_settings", diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java index 6ef83f82a46..298be87c731 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java @@ -203,7 +203,6 @@ public class MyBatis implements Startable { confBuilder.loadAlias("Portfolio", PortfolioDto.class); confBuilder.loadAlias("PortfolioProject", PortfolioProjectDto.class); confBuilder.loadAlias("PortfolioReference", PortfolioReferenceDto.class); - confBuilder.loadAlias("PrIssue", PrIssueDto.class); confBuilder.loadAlias("ProjectQgateAssociation", ProjectQgateAssociationDto.class); confBuilder.loadAlias("Project", ProjectDto.class); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDao.java index 5a70462b650..4682d92edfd 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDao.java @@ -19,12 +19,9 @@ */ package org.sonar.db.portfolio; -import java.util.Collection; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; import org.sonar.api.resources.Qualifiers; import org.sonar.api.utils.System2; import org.sonar.core.util.UuidFactory; @@ -32,9 +29,9 @@ import org.sonar.db.Dao; import org.sonar.db.DbSession; import org.sonar.db.audit.AuditPersister; import org.sonar.db.audit.model.ComponentNewValue; -import org.sonar.db.project.ProjectDto; import static com.google.common.base.Preconditions.checkArgument; +import static java.lang.String.format; import static java.util.Collections.emptyList; import static java.util.Collections.singleton; import static org.sonar.db.DatabaseUtils.executeLargeInputs; @@ -50,6 +47,9 @@ public class PortfolioDao implements Dao { this.auditPersister = auditPersister; } + /* + * Select portfolios + */ public List<PortfolioDto> selectAllRoots(DbSession dbSession) { return mapper(dbSession).selectAllRoots(); } @@ -81,6 +81,9 @@ public class PortfolioDao implements Dao { return mapper(dbSession).selectByUuids(uuids); } + /* + * Modify portfolios + */ public void insert(DbSession dbSession, PortfolioDto portfolio) { checkArgument(portfolio.isRoot() == (portfolio.getUuid().equals(portfolio.getRootUuid()))); mapper(dbSession).insert(portfolio); @@ -106,20 +109,9 @@ public class PortfolioDao implements Dao { auditPersister.updateComponent(dbSession, toComponentNewValue(portfolio)); } - private static ComponentNewValue toComponentNewValue(PortfolioDto portfolio) { - return new ComponentNewValue(portfolio.getUuid(), portfolio.getName(), portfolio.getKey(), portfolio.isPrivate(), - portfolio.getDescription(), qualifier(portfolio)); - } - - private static String qualifier(PortfolioDto portfolioDto) { - return portfolioDto.isRoot() ? Qualifiers.VIEW : Qualifiers.SUBVIEW; - } - - public Map<String, String> selectKeysByUuids(DbSession dbSession, Collection<String> uuids) { - return executeLargeInputs(uuids, uuids1 -> mapper(dbSession).selectByUuids(uuids1)).stream() - .collect(Collectors.toMap(PortfolioDto::getUuid, PortfolioDto::getKey)); - } - + /* + * Portfolio references + */ public void addReference(DbSession dbSession, String portfolioUuid, String referenceUuid) { mapper(dbSession).insertReference(new PortfolioReferenceDto() .setUuid(uuidFactory.create()) @@ -168,8 +160,11 @@ public class PortfolioDao implements Dao { return mapper(dbSession).selectReference(portfolioUuid, referenceKey); } - public List<ProjectDto> selectProjects(DbSession dbSession, String portfolioUuid) { - return mapper(dbSession).selectProjects(portfolioUuid); + /* + * Manual selection of projects + */ + public List<PortfolioProjectDto> selectPortfolioProjects(DbSession dbSession, String portfolioUuid) { + return mapper(dbSession).selectPortfolioProjects(portfolioUuid); } public List<PortfolioProjectDto> selectAllProjectsInHierarchy(DbSession dbSession, String rootUuid) { @@ -180,12 +175,15 @@ public class PortfolioDao implements Dao { return mapper(dbSession).selectAllPortfolioProjects(); } - public void addProject(DbSession dbSession, String portfolioUuid, String projectUuid) { - mapper(dbSession).insertProject(new PortfolioProjectDto() - .setUuid(uuidFactory.create()) - .setPortfolioUuid(portfolioUuid) - .setProjectUuid(projectUuid) - .setCreatedAt(system2.now())); + public PortfolioProjectDto selectPortfolioProjectOrFail(DbSession dbSession, String portfolioUuid, String projectUuid) { + return Optional.ofNullable(mapper(dbSession).selectPortfolioProject(portfolioUuid, projectUuid)).orElseThrow(() -> + new IllegalArgumentException(format("Project '%s' not selected in portfolio '%s'", projectUuid, portfolioUuid))); + } + + public String addProject(DbSession dbSession, String portfolioUuid, String projectUuid) { + String uuid = uuidFactory.create(); + mapper(dbSession).insertProject(uuid, portfolioUuid, projectUuid, system2.now()); + return uuid; } public void deleteProjects(DbSession dbSession, String portfolioUuid) { @@ -200,8 +198,30 @@ public class PortfolioDao implements Dao { mapper(dbSession).deleteAllProjects(); } + public Set<String> selectBranches(DbSession dbSession, String portfolioProjectUuid) { + return mapper(dbSession).selectBranches(portfolioProjectUuid); + } + + public void addBranch(DbSession dbSession, String portfolioProjectUuid, String branchKey) { + mapper(dbSession).insertBranch(uuidFactory.create(), portfolioProjectUuid, branchKey, system2.now()); + } + + public void deleteBranch(DbSession dbSession, String portfolioUuid, String projectUuid, String branchKey) { + mapper(dbSession).deleteBranch(portfolioUuid, projectUuid, branchKey); + } + + /* + * Utils + */ private static PortfolioMapper mapper(DbSession session) { return session.getMapper(PortfolioMapper.class); } + private static ComponentNewValue toComponentNewValue(PortfolioDto portfolio) { + return new ComponentNewValue(portfolio.getUuid(), portfolio.isPrivate(), portfolio.getName(), portfolio.getKey(), portfolio.getDescription(), qualifier(portfolio)); + } + + private static String qualifier(PortfolioDto portfolioDto) { + return portfolioDto.isRoot() ? Qualifiers.VIEW : Qualifiers.SUBVIEW; + } } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDto.java index 6b6c790c9b8..48195cc50ea 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDto.java @@ -33,6 +33,7 @@ public class PortfolioDto { private String name; private String description; private boolean isPrivate = false; + private String branchName; private String rootUuid; private String parentUuid; @@ -69,6 +70,15 @@ public class PortfolioDto { return this; } + @CheckForNull + public String getBranchName() { + return branchName; + } + + public void setBranchName(@Nullable String branchName) { + this.branchName = branchName; + } + public String getSelectionMode() { return selectionMode; } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioMapper.java index c337e8a1b46..02052e05db8 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioMapper.java @@ -24,13 +24,12 @@ import java.util.List; import java.util.Set; import javax.annotation.CheckForNull; import org.apache.ibatis.annotations.Param; -import org.sonar.db.project.ProjectDto; public interface PortfolioMapper { @CheckForNull PortfolioDto selectByKey(String key); - List<PortfolioDto> selectByKeys(@Param("keys")List<String> keys); + List<PortfolioDto> selectByKeys(@Param("keys") List<String> keys); @CheckForNull PortfolioDto selectByUuid(String uuid); @@ -47,7 +46,7 @@ public interface PortfolioMapper { void insertReference(PortfolioReferenceDto portfolioReference); - void insertProject(PortfolioProjectDto portfolioProject); + void insertProject(@Param("uuid") String uuid, @Param("portfolioUuid") String portfolioUuid, @Param("projectUuid") String projectUuid, @Param("createdAt") long createdAt); List<PortfolioDto> selectTree(String portfolioUuid); @@ -55,7 +54,9 @@ public interface PortfolioMapper { List<PortfolioDto> selectReferencers(String referenceUuid); - List<ProjectDto> selectProjects(String portfolioUuid); + List<PortfolioProjectDto> selectPortfolioProjects(String portfolioUuid); + + PortfolioProjectDto selectPortfolioProject(@Param("portfolioUuid") String portfolioUuid, @Param("projectUuid") String projectUuid); List<ReferenceDto> selectAllReferencesToPortfolios(); @@ -93,5 +94,12 @@ public interface PortfolioMapper { List<ReferenceDto> selectAllReferencesInHierarchy(String rootUuid); + void deleteBranch(@Param("portfolioProjectUuid") String portfolioProjectUuid, @Param("branchKey") String branchKey); + + void deleteBranch(@Param("portfolioUuid") String portfolioUuid, @Param("projectUuid") String projectUuid, @Param("branchKey") String branchKey); + + void insertBranch(@Param("uuid") String uuid, @Param("portfolioProjectUuid") String portfolioProjectUuid, @Param("branchKey") String branchKey, + @Param("createdAt") long createdAt); + Set<String> selectBranches(String portfolioProjectUuid); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioProjectDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioProjectDto.java index ccdf338235b..e78de8efbe6 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioProjectDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioProjectDto.java @@ -19,10 +19,15 @@ */ package org.sonar.db.portfolio; +import java.util.Set; + public class PortfolioProjectDto { private String uuid; private String portfolioUuid; + private String portfolioKey; private String projectUuid; + private String projectKey; + private Set<String> branchKeys; private long createdAt; public String getUuid() { @@ -60,4 +65,30 @@ public class PortfolioProjectDto { this.createdAt = createdAt; return this; } + + public String getPortfolioKey() { + return portfolioKey; + } + + public PortfolioProjectDto setPortfolioKey(String portfolioKey) { + this.portfolioKey = portfolioKey; + return this; + } + + public String getProjectKey() { + return projectKey; + } + + public PortfolioProjectDto setProjectKey(String projectKey) { + this.projectKey = projectKey; + return this; + } + + public Set<String> getBranchKeys() { + return branchKeys; + } + + public void setBranchKeys(Set<String> branchKeys) { + this.branchKeys = branchKeys; + } } diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/portfolio/PortfolioMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/portfolio/PortfolioMapper.xml index e39f210d60f..519d19ea785 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/portfolio/PortfolioMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/portfolio/PortfolioMapper.xml @@ -2,19 +2,20 @@ <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd"> <mapper namespace="org.sonar.db.portfolio.PortfolioMapper"> - <sql id="portfolioColumns"> - p.uuid as uuid, - p.kee as kee, - p.name as name, - p.description as description, - p.private as isPrivate, - p.root_uuid as rootUuid, - p.parent_uuid as parentUuid, - p.selection_mode as selectionMode, - p.selection_expression as selectionExpression, - p.created_at as createdAt, - p.updated_at as updatedAt - </sql> + <sql id="portfolioColumns"> + p.uuid as uuid, + p.kee as kee, + p.name as name, + p.description as description, + p.private as isPrivate, + p.branch_name as branchName, + p.root_uuid as rootUuid, + p.parent_uuid as parentUuid, + p.selection_mode as selectionMode, + p.selection_expression as selectionExpression, + p.created_at as createdAt, + p.updated_at as updatedAt + </sql> <sql id="projectColumns"> p.uuid as uuid, @@ -28,6 +29,24 @@ p.updated_at as updatedAt </sql> + <sql id="portfolioProjectColumns"> + pp.uuid as portfolioProject_uuid, + pp.project_uuid as projectUuid, + pp.portfolio_uuid as portfolioUuid, + pf.kee as portfolioKey, + pp.project_uuid as projectUuid, + p.kee as projectKey, + pp.created_at as createdAt, + ppb.branch_key as branchKey + </sql> + + <resultMap id="portfolioProjectResult" type="PortfolioProject" autoMapping="true"> + <id property="uuid" column="portfolioProject_uuid" /> + <collection property="branchKeys" ofType="string"> + <result column="branchKey" /> + </collection> + </resultMap> + <select id="selectByUuid" parameterType="String" resultType="Portfolio"> SELECT <include refid="portfolioColumns"/> @@ -80,38 +99,54 @@ p.parent_uuid is null </select> - <select id="selectProjects" resultType="Project"> + <select id="selectPortfolioProjectBranches" resultType="string"> + SELECT ppb.branch_key + FROM portfolio_proj_branches ppb + WHERE ppb.portfolio_project_uuid = #{id} + </select> + + <select id="selectPortfolioProjects" resultMap="portfolioProjectResult"> SELECT - <include refid="projectColumns"/> + <include refid="portfolioProjectColumns"/> FROM portfolio_projects pp INNER JOIN projects p on p.uuid = pp.project_uuid + INNER JOIN portfolios pf on pf.uuid = pp.portfolio_uuid + LEFT OUTER JOIN portfolio_proj_branches ppb on pp.uuid = ppb.portfolio_project_uuid WHERE pp.portfolio_uuid=#{portfolioUuid,jdbcType=VARCHAR} </select> - <select id="selectAllPortfolioProjects" resultType="org.sonar.db.portfolio.PortfolioProjectDto"> + <select id="selectPortfolioProject" resultMap="portfolioProjectResult"> + SELECT + <include refid="portfolioProjectColumns"/> + FROM portfolio_projects pp + INNER JOIN projects p on p.uuid = pp.project_uuid + INNER JOIN portfolios pf on pf.uuid = pp.portfolio_uuid + LEFT OUTER JOIN portfolio_proj_branches ppb on pp.uuid = ppb.portfolio_project_uuid + WHERE + pp.portfolio_uuid=#{portfolioUuid,jdbcType=VARCHAR} + and pp.project_uuid=#{projectUuid,jdbcType=VARCHAR} + + </select> + + <select id="selectAllPortfolioProjects" resultMap="portfolioProjectResult"> SELECT - pp.uuid, - pp.project_uuid as projectUuid, - pp.portfolio_uuid as portfolioUuid, - pp.project_uuid as projectUuid, - pp.created_at as createdAt + <include refid="portfolioProjectColumns"/> FROM portfolio_projects pp INNER JOIN projects p on p.uuid = pp.project_uuid + INNER JOIN portfolios pf on pf.uuid = pp.portfolio_uuid + LEFT OUTER JOIN portfolio_proj_branches ppb on pp.uuid = ppb.portfolio_project_uuid </select> - <select id="selectAllProjectsInHierarchy" resultType="org.sonar.db.portfolio.PortfolioProjectDto"> + <select id="selectAllProjectsInHierarchy" resultMap="portfolioProjectResult"> SELECT - pp.uuid, - pp.project_uuid as projectUuid, - pp.portfolio_uuid as portfolioUuid, - pp.project_uuid as projectUuid, - pp.created_at as createdAt + <include refid="portfolioProjectColumns"/> FROM portfolio_projects pp - INNER JOIN portfolios p - ON pp.portfolio_uuid = p.uuid + INNER JOIN projects p on p.uuid = pp.project_uuid + INNER JOIN portfolios pf on pp.portfolio_uuid = pf.uuid + LEFT OUTER JOIN portfolio_proj_branches ppb on pp.uuid = ppb.portfolio_project_uuid where - p.root_uuid = #{rootUuid,jdbcType=VARCHAR} + pf.root_uuid = #{rootUuid,jdbcType=VARCHAR} </select> <select id="selectReferenceUuids" resultType="String"> @@ -192,6 +227,7 @@ private, root_uuid, parent_uuid, + branch_name, selection_mode, selection_expression, created_at, @@ -205,6 +241,7 @@ #{isPrivate,jdbcType=BOOLEAN}, #{rootUuid,jdbcType=VARCHAR}, #{parentUuid,jdbcType=VARCHAR}, + #{branchName,jdbcType=VARCHAR}, #{selectionMode,jdbcType=VARCHAR}, #{selectionExpression,jdbcType=VARCHAR}, #{createdAt,jdbcType=BIGINT}, @@ -276,6 +313,12 @@ </delete> <delete id="deleteProjectsByPortfolioUuids" parameterType="String"> + delete from portfolio_proj_branches + where portfolio_project_uuid in + (select uuid from portfolio_projects + where portfolio_uuid in + <foreach collection="uuids" open="(" close=")" item="uuid" separator=",">#{uuid,jdbcType=VARCHAR}</foreach>); + DELETE FROM portfolio_projects WHERE portfolio_uuid in <foreach collection="uuids" open="(" close=")" item="uuid" separator=",">#{uuid,jdbcType=VARCHAR}</foreach> </delete> @@ -289,7 +332,8 @@ </delete> <delete id="deleteAllProjects" parameterType="String"> - DELETE FROM portfolio_projects + DELETE FROM portfolio_projects; + DELETE FROM portfolio_proj_branches </delete> <insert id="insertReference" parameterType="PortfolioReference"> @@ -321,18 +365,28 @@ </delete> <delete id="deleteProjects" parameterType="String"> + delete from portfolio_proj_branches + where portfolio_project_uuid = + (select uuid from portfolio_projects + where portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR}); + delete from portfolio_projects where portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR} </delete> - <delete id="deleteProject" parameterType="map"> + <delete id="deleteProject" parameterType="map"> + delete from portfolio_proj_branches + where portfolio_project_uuid = + (select uuid from portfolio_projects + where portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR} + and project_uuid = #{projectUuid,jdbcType=VARCHAR}); + delete from portfolio_projects where portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR} - and - project_uuid = #{projectUuid,jdbcType=VARCHAR} + and project_uuid = #{projectUuid,jdbcType=VARCHAR} </delete> - <insert id="insertProject" parameterType="PortfolioProject"> + <insert id="insertProject" parameterType="map"> INSERT INTO portfolio_projects ( uuid, portfolio_uuid, @@ -347,6 +401,30 @@ ) </insert> + <insert id="insertBranch" parameterType="map"> + INSERT INTO portfolio_proj_branches ( + uuid, + portfolio_project_uuid, + branch_key, + created_at + ) + VALUES ( + #{uuid,jdbcType=VARCHAR}, + #{portfolioProjectUuid,jdbcType=VARCHAR}, + #{branchKey,jdbcType=VARCHAR}, + #{createdAt,jdbcType=BIGINT} + ) + </insert> + + <delete id="deleteBranch" parameterType="map"> + delete from portfolio_proj_branches + where portfolio_project_uuid = + (select uuid from portfolio_projects + where portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR} + and project_uuid = #{projectUuid,jdbcType=VARCHAR}) + and branch_key = #{branchKey,jdbcType=VARCHAR} + </delete> + <update id="update" parameterType="Portfolio"> update portfolios set name = #{name,jdbcType=VARCHAR}, @@ -354,6 +432,7 @@ selection_mode = #{selectionMode,jdbcType=VARCHAR}, selection_expression = #{selectionExpression,jdbcType=VARCHAR}, parent_uuid = #{parentUuid,jdbcType=VARCHAR}, + branch_name = #{branchName,jdbcType=VARCHAR}, root_uuid = #{rootUuid,jdbcType=VARCHAR}, updated_at = #{updatedAt,jdbcType=BIGINT} where diff --git a/server/sonar-db-dao/src/schema/schema-sq.ddl b/server/sonar-db-dao/src/schema/schema-sq.ddl index 7a9d8390bba..8591380930a 100644 --- a/server/sonar-db-dao/src/schema/schema-sq.ddl +++ b/server/sonar-db-dao/src/schema/schema-sq.ddl @@ -564,6 +564,14 @@ CREATE TABLE "PLUGINS"( ALTER TABLE "PLUGINS" ADD CONSTRAINT "PK_PLUGINS" PRIMARY KEY("UUID"); CREATE UNIQUE INDEX "PLUGINS_KEY" ON "PLUGINS"("KEE"); +CREATE TABLE "PORTFOLIO_PROJ_BRANCHES"( + "UUID" VARCHAR(40) NOT NULL, + "PORTFOLIO_PROJECT_UUID" VARCHAR(40) NOT NULL, + "BRANCH_KEY" VARCHAR(255) NOT NULL, + "CREATED_AT" BIGINT NOT NULL +); +ALTER TABLE "PORTFOLIO_PROJ_BRANCHES" ADD CONSTRAINT "PK_PORTFOLIO_PROJ_BRANCHES" PRIMARY KEY("UUID"); + CREATE TABLE "PORTFOLIO_PROJECTS"( "UUID" VARCHAR(40) NOT NULL, "PORTFOLIO_UUID" VARCHAR(40) NOT NULL, @@ -593,7 +601,8 @@ CREATE TABLE "PORTFOLIOS"( "SELECTION_MODE" VARCHAR(50) NOT NULL, "SELECTION_EXPRESSION" VARCHAR(4000), "CREATED_AT" BIGINT NOT NULL, - "UPDATED_AT" BIGINT NOT NULL + "UPDATED_AT" BIGINT NOT NULL, + "BRANCH_NAME" VARCHAR(255) ); ALTER TABLE "PORTFOLIOS" ADD CONSTRAINT "PK_PORTFOLIOS" PRIMARY KEY("UUID"); CREATE UNIQUE INDEX "UNIQ_PORTFOLIOS_KEE" ON "PORTFOLIOS"("KEE"); diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/portfolio/PortfolioDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/portfolio/PortfolioDaoTest.java index 593f311cad3..83a30202e65 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/portfolio/PortfolioDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/portfolio/PortfolioDaoTest.java @@ -31,8 +31,8 @@ import org.sonar.db.audit.AuditPersister; import org.sonar.db.project.ProjectDto; import static java.util.Collections.emptySet; -import static java.util.Map.entry; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.tuple; import static org.mockito.ArgumentMatchers.any; @@ -153,13 +153,18 @@ public class PortfolioDaoTest { @Test public void delete() { + ProjectDto proj1 = db.components().insertPrivateProjectDto("proj1"); + ProjectDto app1 = db.components().insertPrivateApplicationDto(); + PortfolioDto p1 = db.components().insertPrivatePortfolioDto("p1"); PortfolioDto p2 = db.components().insertPrivatePortfolioDto("p2"); PortfolioDto p3 = db.components().insertPrivatePortfolioDto("p3"); PortfolioDto p4 = db.components().insertPrivatePortfolioDto("p4"); - portfolioDao.addProject(session, "p1", "proj1"); - portfolioDao.addProject(session, "p2", "proj1"); + db.components().addPortfolioProject(p1, proj1); + db.components().addPortfolioProject(p2, proj1); + db.components().addPortfolioProjectBranch(p1, proj1, "branch1"); + db.components().addPortfolioProjectBranch(p2, proj1, "branch2"); portfolioDao.addReference(session, "p1", "app1"); portfolioDao.addReference(session, "p2", "app1"); @@ -168,6 +173,8 @@ public class PortfolioDaoTest { portfolioDao.delete(session, p1); portfolioDao.delete(session, p3); + assertThat(db.select(session, "select branch_key from portfolio_proj_branches")).extracting(m -> m.values().iterator().next()) + .containsOnly("branch2"); assertThat(db.select(session, "select uuid from portfolios")).extracting(m -> m.values().iterator().next()) .containsOnly("p2", "p4"); assertThat(db.select(session, "select portfolio_uuid from portfolio_references")).extracting(m -> m.values().iterator().next()) @@ -207,16 +214,6 @@ public class PortfolioDaoTest { .extracting("name", "key", "uuid", "description", "private", "rootUuid", "parentUuid", "selectionMode", "selectionExpression") .containsExactly("newName", "KEY_name", "name", "newDesc", true, "root", "parent", "newMode", "newExp"); verify(audit).updateComponent(any(), any()); - - } - - @Test - public void selectKeysByUuids() { - PortfolioDto root = db.components().insertPrivatePortfolioDto(); - PortfolioDto child1 = addPortfolio(root); - - assertThat(portfolioDao.selectKeysByUuids(session, Set.of(root.getUuid(), child1.getUuid()))) - .containsOnly(entry(root.getUuid(), root.getKey()), entry(child1.getUuid(), child1.getKey())); } @Test @@ -253,7 +250,7 @@ public class PortfolioDaoTest { @Test public void add_and_select_references() { - assertThat(portfolioDao.selectProjects(session, "portfolio1")).isEmpty(); + assertThat(portfolioDao.selectPortfolioProjects(session, "portfolio1")).isEmpty(); portfolioDao.addReference(session, "portfolio1", "app1"); portfolioDao.addReference(session, "portfolio1", "app2"); portfolioDao.addReference(session, "portfolio2", "app3"); @@ -378,17 +375,21 @@ public class PortfolioDaoTest { @Test public void insert_and_select_projects() { - db.components().insertPrivateProject("project1"); - db.components().insertPrivateProject("project2"); + PortfolioDto portfolio1 = db.components().insertPublicPortfolioDto(); + PortfolioDto portfolio2 = db.components().insertPublicPortfolioDto(); + PortfolioDto portfolio3 = db.components().insertPublicPortfolioDto(); - assertThat(portfolioDao.selectProjects(session, "portfolio1")).isEmpty(); - portfolioDao.addProject(session, "portfolio1", "project1"); - portfolioDao.addProject(session, "portfolio1", "project2"); - portfolioDao.addProject(session, "portfolio2", "project2"); + ProjectDto project1 = db.components().insertPrivateProjectDto("project1"); + ProjectDto project2 = db.components().insertPrivateProjectDto("project2"); + + assertThat(portfolioDao.selectPortfolioProjects(session, portfolio1.getUuid())).isEmpty(); + db.components().addPortfolioProject(portfolio1, project1); + db.components().addPortfolioProject(portfolio1, project2); + db.components().addPortfolioProject(portfolio2, project2); db.commit(); - assertThat(portfolioDao.selectProjects(session, "portfolio1")).extracting(ProjectDto::getUuid).containsOnly("project1", "project2"); - assertThat(portfolioDao.selectProjects(session, "portfolio2")).extracting(ProjectDto::getUuid).containsOnly("project2"); - assertThat(portfolioDao.selectProjects(session, "portfolio3")).isEmpty(); + assertThat(portfolioDao.selectPortfolioProjects(session, portfolio1.getUuid())).extracting(PortfolioProjectDto::getProjectUuid).containsOnly("project1", "project2"); + assertThat(portfolioDao.selectPortfolioProjects(session, portfolio2.getUuid())).extracting(PortfolioProjectDto::getProjectUuid).containsOnly("project2"); + assertThat(portfolioDao.selectPortfolioProjects(session, portfolio3.getUuid())).isEmpty(); assertThat(db.countRowsOfTable("portfolio_projects")).isEqualTo(3); assertThat(db.select(session, "select created_at from portfolio_projects")) @@ -398,56 +399,91 @@ public class PortfolioDaoTest { @Test public void delete_projects() { - db.components().insertPrivateProject("project1"); - db.components().insertPrivateProject("project2"); + db.components().insertPrivatePortfolioDto("portfolio1"); + db.components().insertPrivatePortfolioDto("portfolio2"); - assertThat(portfolioDao.selectProjects(session, "portfolio1")).isEmpty(); + db.components().insertPrivateProjectDto("project1"); + db.components().insertPrivateProjectDto("project2"); + + assertThat(portfolioDao.selectPortfolioProjects(session, "portfolio1")).isEmpty(); portfolioDao.addProject(session, "portfolio1", "project1"); portfolioDao.addProject(session, "portfolio1", "project2"); portfolioDao.addProject(session, "portfolio2", "project2"); - assertThat(portfolioDao.selectProjects(session, "portfolio1")).isNotEmpty(); + assertThat(portfolioDao.selectPortfolioProjects(session, "portfolio1")).isNotEmpty(); portfolioDao.deleteProjects(session, "portfolio1"); - assertThat(portfolioDao.selectProjects(session, "portfolio1")).isEmpty(); - assertThat(portfolioDao.selectProjects(session, "portfolio2")).extracting(ProjectDto::getUuid).containsOnly("project2"); + assertThat(portfolioDao.selectPortfolioProjects(session, "portfolio1")).isEmpty(); + assertThat(portfolioDao.selectPortfolioProjects(session, "portfolio2")).extracting(PortfolioProjectDto::getProjectUuid).containsOnly("project2"); + } + + @Test + public void add_and_delete_selected_branches() { + PortfolioDto portfolio1 = db.components().insertPrivatePortfolioDto("portfolio1"); + ProjectDto project1 = db.components().insertPrivateProjectDto("project1"); + db.components().addPortfolioProject(portfolio1, project1); + + assertThat(db.countRowsOfTable(db.getSession(), "portfolio_proj_branches")).isZero(); + assertThat(portfolioDao.selectPortfolioProjectOrFail(db.getSession(), portfolio1.getUuid(), project1.getUuid()).getBranchKeys()).isEmpty(); + + db.components().addPortfolioProjectBranch(portfolio1, project1, "branch1"); + assertThat(db.countRowsOfTable(db.getSession(), "portfolio_proj_branches")).isOne(); + PortfolioProjectDto portfolioProject = portfolioDao.selectPortfolioProjectOrFail(db.getSession(), portfolio1.getUuid(), project1.getUuid()); + assertThat(portfolioProject.getBranchKeys()).containsOnly("branch1"); + + portfolioDao.deleteBranch(db.getSession(), portfolio1.getUuid(), project1.getUuid(), "branch1"); + assertThat(db.countRowsOfTable(db.getSession(), "portfolio_proj_branches")).isZero(); + assertThat(portfolioDao.selectPortfolioProjectOrFail(db.getSession(), portfolio1.getUuid(), project1.getUuid()).getBranchKeys()).isEmpty(); + } + + @Test + public void delete_nonexisting_branch_doesnt_fail() { + DbSession session = db.getSession(); + assertThatCode(() -> portfolioDao.deleteBranch(session, "nonexisting1", "nonexisting2", "branch1")) + .doesNotThrowAnyException(); } @Test public void delete_project() { - db.components().insertPrivateProject("project1"); - db.components().insertPrivateProject("project2"); + db.components().insertPrivatePortfolioDto("portfolio1"); + db.components().insertPrivatePortfolioDto("portfolio2"); - assertThat(portfolioDao.selectProjects(session, "portfolio1")).isEmpty(); + db.components().insertPrivateProjectDto("project1"); + db.components().insertPrivateProjectDto("project2"); + + assertThat(portfolioDao.selectPortfolioProjects(session, "portfolio1")).isEmpty(); portfolioDao.addProject(session, "portfolio1", "project1"); portfolioDao.addProject(session, "portfolio1", "project2"); portfolioDao.addProject(session, "portfolio2", "project2"); - assertThat(portfolioDao.selectProjects(session, "portfolio1")).isNotEmpty(); + assertThat(portfolioDao.selectPortfolioProjects(session, "portfolio1")).isNotEmpty(); portfolioDao.deleteProject(session, "portfolio1", "project2"); - assertThat(portfolioDao.selectProjects(session, "portfolio1")).extracting(ProjectDto::getUuid).containsOnly("project1"); - assertThat(portfolioDao.selectProjects(session, "portfolio2")).extracting(ProjectDto::getUuid).containsOnly("project2"); + assertThat(portfolioDao.selectPortfolioProjects(session, "portfolio1")).extracting(PortfolioProjectDto::getProjectUuid).containsOnly("project1"); + assertThat(portfolioDao.selectPortfolioProjects(session, "portfolio2")).extracting(PortfolioProjectDto::getProjectUuid).containsOnly("project2"); } @Test public void selectAllProjectsInHierarchy() { - db.components().insertPrivateProject("p1"); - db.components().insertPrivateProject("p2"); - db.components().insertPrivateProject("p3"); - db.components().insertPrivateProject("p4"); + ProjectDto p1 = db.components().insertPrivateProjectDto("p1"); + ProjectDto p2 = db.components().insertPrivateProjectDto("p2"); + ProjectDto p3 = db.components().insertPrivateProjectDto("p3"); + ProjectDto p4 = db.components().insertPrivateProjectDto("p4"); PortfolioDto root = db.components().insertPrivatePortfolioDto("root"); PortfolioDto child1 = addPortfolio(root, "child1"); PortfolioDto child11 = addPortfolio(child1, "child11"); PortfolioDto root2 = db.components().insertPrivatePortfolioDto("root2"); - portfolioDao.addProject(session, root.getUuid(), "p1"); - portfolioDao.addProject(session, child1.getUuid(), "p2"); - portfolioDao.addProject(session, child11.getUuid(), "p3"); - portfolioDao.addProject(session, root2.getUuid(), "p4"); + db.components().addPortfolioProject(root, p1); + db.components().addPortfolioProject(child1, p2); + db.components().addPortfolioProject(child11, p3); + db.components().addPortfolioProject(root2, p4); + + db.components().addPortfolioProjectBranch(root, p1, "branch1"); session.commit(); assertThat(portfolioDao.selectAllProjectsInHierarchy(session, root.getUuid())) - .extracting(PortfolioProjectDto::getProjectUuid).containsExactly("p1", "p2", "p3"); + .extracting(PortfolioProjectDto::getProjectUuid, PortfolioProjectDto::getBranchKeys) + .containsExactlyInAnyOrder(tuple("p1", Set.of("branch1")), tuple("p2", emptySet()), tuple("p3", emptySet())); assertThat(portfolioDao.selectAllProjectsInHierarchy(session, "nonexisting")).isEmpty(); } @@ -463,14 +499,18 @@ public class PortfolioDaoTest { PortfolioDto child11 = addPortfolio(child1); PortfolioDto root2 = db.components().insertPrivatePortfolioDto(); - portfolioDao.addProject(session, root.getUuid(), "p1"); + String portfolioProjectUuid = portfolioDao.addProject(session, root.getUuid(), "p1"); portfolioDao.addProject(session, child1.getUuid(), "p2"); portfolioDao.addProject(session, child11.getUuid(), "p3"); portfolioDao.addProject(session, root2.getUuid(), "p4"); + portfolioDao.addBranch(session, portfolioProjectUuid, "branch1"); + assertThat(db.countRowsOfTable(session, "portfolio_projects")).isEqualTo(4); + assertThat(db.countRowsOfTable(session, "portfolio_proj_branches")).isOne(); portfolioDao.deleteAllProjects(session); assertThat(db.countRowsOfTable(session, "portfolio_projects")).isZero(); + assertThat(db.countRowsOfTable(session, "portfolio_proj_branches")).isZero(); } private PortfolioDto addPortfolio(PortfolioDto parent) { diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java index 402b3a5b401..b47fe7a9d99 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java @@ -28,6 +28,7 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.portfolio.PortfolioDto; +import org.sonar.db.portfolio.PortfolioProjectDto; import org.sonar.db.project.ProjectDto; import static com.google.common.base.Preconditions.checkArgument; @@ -301,6 +302,12 @@ public class ComponentDbTester { db.commit(); } + public void addPortfolioProjectBranch(PortfolioDto portfolio, ProjectDto project, String branchKey) { + PortfolioProjectDto portfolioProject = dbClient.portfolioDao().selectPortfolioProjectOrFail(dbSession, portfolio.getUuid(), project.getUuid()); + dbClient.portfolioDao().addBranch(db.getSession(), portfolioProject.getUuid(), branchKey); + db.commit(); + } + public final ComponentDto insertPublicApplication() { return insertPublicApplication(defaults()); } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfolioProjects.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfolioProjects.java new file mode 100644 index 00000000000..d6effed7021 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfolioProjects.java @@ -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.v92; + +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 AddBranchToPortfolioProjects extends DdlChange { + private static final String TABLE_NAME = "portfolio_projects"; + private static final String COLUMN_NAME = "branch_uuid"; + + public AddBranchToPortfolioProjects(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(VarcharColumnDef.UUID_SIZE).build()) + .build()); + } + } + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfolios.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfolios.java new file mode 100644 index 00000000000..e546d9f4b6b --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfolios.java @@ -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.v92; + +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 AddBranchToPortfolios extends DdlChange { + private static final String TABLE_NAME = "portfolios"; + private static final String COLUMN_NAME = "branch_name"; + + public AddBranchToPortfolios(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/v92/AddIndexToPortfolioProjects.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/AddIndexToPortfolioProjects.java new file mode 100644 index 00000000000..2354ed6364e --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/AddIndexToPortfolioProjects.java @@ -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.v92; + +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 AddIndexToPortfolioProjects extends DdlChange { + private static final String TABLE_NAME = "portfolio_projects"; + private static final String INDEX_NAME = "uniq_portfolio_projects"; + + public AddIndexToPortfolioProjects(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() + .setName(INDEX_NAME) + .setTable(TABLE_NAME) + .addColumn("portfolio_uuid") + .addColumn("project_uuid") + .addColumn("branch_uuid") + .build()); + } + } + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/CreatePortfolioProjectBranchesTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/CreatePortfolioProjectBranchesTable.java new file mode 100644 index 00000000000..bbb8cc5996b --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/CreatePortfolioProjectBranchesTable.java @@ -0,0 +1,56 @@ +/* + * 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.v92; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.db.DatabaseUtils; +import org.sonar.server.platform.db.migration.sql.CreateTableBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +import static org.sonar.server.platform.db.migration.def.BigIntegerColumnDef.newBigIntegerColumnDefBuilder; +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE; +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; + +public class CreatePortfolioProjectBranchesTable extends DdlChange { + private final static String TABLE_NAME = "portfolio_proj_branches"; + + public CreatePortfolioProjectBranchesTable(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + if (!tableExists()) { + context.execute(new CreateTableBuilder(getDialect(), TABLE_NAME) + .addPkColumn(newVarcharColumnDefBuilder().setColumnName("uuid").setIsNullable(false).setLimit(UUID_SIZE).build()) + .addColumn(newVarcharColumnDefBuilder().setColumnName("portfolio_project_uuid").setIsNullable(false).setLimit(UUID_SIZE).build()) + .addColumn(newVarcharColumnDefBuilder().setColumnName("branch_key").setIsNullable(false).setLimit(255).build()) + .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").setIsNullable(false).build()) + .build()); + } + } + + private boolean tableExists() throws SQLException { + try (var connection = getDatabase().getDataSource().getConnection()) { + return DatabaseUtils.tableExists(TABLE_NAME, connection); + } + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/DbVersion92.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/DbVersion92.java index dc49c24d94c..9eb256422a0 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/DbVersion92.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/DbVersion92.java @@ -32,6 +32,9 @@ public class DbVersion92 implements DbVersion { .add(6104, "Create qgate_user_permissions Table", CreateQGateUserPermissionsTable.class) .add(6105, "Create qgate_group_permissions Table", CreateQGateGroupPermissionsTable.class) .add(6106, "Create column sonarlint_ad_seen in 'users'", AddSonarlintAdSeenColumnInUsersTable.class) - .add(6107, "Upsert value of sonarlint_ad_seen in 'users'", UpsertSonarlintAdSeenValue.class); + .add(6107, "Upsert value of sonarlint_ad_seen in 'users'", UpsertSonarlintAdSeenValue.class) + .add(6108, "Create table 'portfolio_proj_branches'", CreatePortfolioProjectBranchesTable.class) + .add(6109, "Add column 'branch_name' to table 'portfolios'", AddBranchToPortfolios.class) + ; } } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/DropPortfolioProjectsIndex.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/DropPortfolioProjectsIndex.java new file mode 100644 index 00000000000..7fb2e8a45b1 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v92/DropPortfolioProjectsIndex.java @@ -0,0 +1,31 @@ +/* + * 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.v92; + +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.step.DropIndexChange; + +public class DropPortfolioProjectsIndex extends DropIndexChange { + private static final String TABLE_NAME = "portfolio_projects"; + + public DropPortfolioProjectsIndex(Database db) { + super(db, "uniq_portfolio_projects", TABLE_NAME); + } +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfoliosTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfoliosTest.java new file mode 100644 index 00000000000..9952f7f2fe0 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfoliosTest.java @@ -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.v92; + +import java.sql.SQLException; +import java.sql.Types; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.db.CoreDbTester; + +public class AddBranchToPortfoliosTest { + private static final String TABLE_NAME = "portfolios"; + private static final String COLUMN_NAME = "branch_name"; + + @Rule + public final CoreDbTester db = CoreDbTester.createForSchema(AddBranchToPortfoliosTest.class, "schema.sql"); + + private final AddBranchToPortfolios underTest = new AddBranchToPortfolios(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/v92/AddIndexToPortfolioProjectsTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v92/AddIndexToPortfolioProjectsTest.java new file mode 100644 index 00000000000..44703cea564 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v92/AddIndexToPortfolioProjectsTest.java @@ -0,0 +1,50 @@ +/* + * 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.v92; + +import java.sql.SQLException; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.db.CoreDbTester; + +public class AddIndexToPortfolioProjectsTest { + private static final String TABLE_NAME = "portfolio_projects"; + private static final String INDEX_NAME = "uniq_portfolio_projects"; + + @Rule + public final CoreDbTester db = CoreDbTester.createForSchema(AddIndexToPortfolioProjectsTest.class, "schema.sql"); + + private final AddIndexToPortfolioProjects underTest = new AddIndexToPortfolioProjects(db.database()); + + @Test + public void migration_should_drop_PK_on_events() throws SQLException { + db.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME); + underTest.execute(); + db.assertIndex(TABLE_NAME, INDEX_NAME, "portfolio_uuid", "project_uuid", "branch_uuid"); + } + + @Test + public void migration_should_be_reentant() throws SQLException { + db.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME); + underTest.execute(); + underTest.execute(); + db.assertIndex(TABLE_NAME, INDEX_NAME, "portfolio_uuid", "project_uuid", "branch_uuid"); + } +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v92/CreatePortfolioProjectBranchesTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v92/CreatePortfolioProjectBranchesTableTest.java new file mode 100644 index 00000000000..66d45f07dd4 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v92/CreatePortfolioProjectBranchesTableTest.java @@ -0,0 +1,54 @@ +/* + * 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.v92; + +import java.sql.SQLException; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.db.CoreDbTester; + +public class CreatePortfolioProjectBranchesTableTest { + private static final String TABLE_NAME = "portfolio_proj_branches"; + + @Rule + public final CoreDbTester db = CoreDbTester.createEmpty(); + + private final CreatePortfolioProjectBranchesTable underTest = new CreatePortfolioProjectBranchesTable(db.database()); + + @Test + public void migration_should_create_table() throws SQLException { + db.assertTableDoesNotExist(TABLE_NAME); + + underTest.execute(); + + db.assertTableExists(TABLE_NAME); + } + + @Test + public void migration_should_be_reentrant() throws SQLException { + db.assertTableDoesNotExist(TABLE_NAME); + + underTest.execute(); + //re-entrant + underTest.execute(); + + db.assertTableExists(TABLE_NAME); + } +} diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfolioProjectsTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfolioProjectsTest/schema.sql new file mode 100644 index 00000000000..ac76fc460a9 --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfolioProjectsTest/schema.sql @@ -0,0 +1,7 @@ +CREATE TABLE "PORTFOLIO_PROJECTS"( + "UUID" VARCHAR(40) NOT NULL, + "PORTFOLIO_UUID" VARCHAR(40) NOT NULL, + "PROJECT_UUID" VARCHAR(40) NOT NULL, + "CREATED_AT" BIGINT NOT NULL +); +ALTER TABLE "PORTFOLIO_PROJECTS" ADD CONSTRAINT "PK_PORTFOLIO_PROJECTS" PRIMARY KEY("UUID"); diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfoliosTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfoliosTest/schema.sql new file mode 100644 index 00000000000..2ce8cf9b9f2 --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v92/AddBranchToPortfoliosTest/schema.sql @@ -0,0 +1,15 @@ +CREATE TABLE "PORTFOLIOS"( + "UUID" VARCHAR(40) NOT NULL, + "KEE" VARCHAR(400) NOT NULL, + "NAME" VARCHAR(2000) NOT NULL, + "DESCRIPTION" VARCHAR(2000), + "ROOT_UUID" VARCHAR(40) NOT NULL, + "PARENT_UUID" VARCHAR(40), + "PRIVATE" BOOLEAN NOT NULL, + "SELECTION_MODE" VARCHAR(50) NOT NULL, + "SELECTION_EXPRESSION" VARCHAR(4000), + "CREATED_AT" BIGINT NOT NULL, + "UPDATED_AT" BIGINT NOT NULL +); +ALTER TABLE "PORTFOLIOS" ADD CONSTRAINT "PK_PORTFOLIOS" PRIMARY KEY("UUID"); +CREATE UNIQUE INDEX "UNIQ_PORTFOLIOS_KEE" ON "PORTFOLIOS"("KEE"); diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v92/AddIndexToPortfolioProjectsTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v92/AddIndexToPortfolioProjectsTest/schema.sql new file mode 100644 index 00000000000..6dcd03a8a16 --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v92/AddIndexToPortfolioProjectsTest/schema.sql @@ -0,0 +1,8 @@ +CREATE TABLE "PORTFOLIO_PROJECTS"( + "UUID" VARCHAR(40) NOT NULL, + "PORTFOLIO_UUID" VARCHAR(40) NOT NULL, + "PROJECT_UUID" VARCHAR(40) NOT NULL, + "BRANCH_UUID" VARCHAR(40), + "CREATED_AT" BIGINT NOT NULL +); +ALTER TABLE "PORTFOLIO_PROJECTS" ADD CONSTRAINT "PK_PORTFOLIO_PROJECTS" PRIMARY KEY("UUID"); diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v92/DropPortfolioProjectsIndexTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v92/DropPortfolioProjectsIndexTest/schema.sql new file mode 100644 index 00000000000..7722fbcf49e --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v92/DropPortfolioProjectsIndexTest/schema.sql @@ -0,0 +1,8 @@ +CREATE TABLE "PORTFOLIO_PROJECTS"( + "UUID" VARCHAR(40) NOT NULL, + "PORTFOLIO_UUID" VARCHAR(40) NOT NULL, + "PROJECT_UUID" VARCHAR(40) NOT NULL, + "CREATED_AT" BIGINT NOT NULL +); +ALTER TABLE "PORTFOLIO_PROJECTS" ADD CONSTRAINT "PK_PORTFOLIO_PROJECTS" PRIMARY KEY("UUID"); +CREATE UNIQUE INDEX "UNIQ_PORTFOLIO_PROJECTS" ON "PORTFOLIO_PROJECTS"("PORTFOLIO_UUID", "PROJECT_UUID"); |