From db45509677d7a93a44f87c388d0f628c0716287e Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Mon, 1 Oct 2018 17:29:50 +0200 Subject: [PATCH] SONAR-11310 add and use target columns in CE_ACTIVITY & CE_QUEUE --- .../org/sonar/db/version/schema-h2.ddl | 16 +- .../java/org/sonar/db/ce/CeActivityDao.java | 3 +- .../org/sonar/db/ce/CeActivityMapper.java | 4 +- .../org/sonar/db/ce/CeActivityMapper.xml | 47 ++-- .../org/sonar/db/ce/CeQueueMapper.xml | 22 +- .../org/sonar/db/purge/PurgeMapper.xml | 16 +- .../org/sonar/db/ce/CeActivityDaoTest.java | 215 +++++++++++++++++- .../v74/AddLastKeyColumnsToCeActivity.java | 119 ++++++++++ ...dMainComponentUuidColumnsToCeActivity.java | 32 +++ .../AddMainComponentUuidColumnsToCeQueue.java | 32 +++ .../AddMainComponentUuidColumnsToCeTable.java | 81 +++++++ .../db/migration/version/v74/DbVersion74.java | 6 + .../PopulateLastKeyColumnsToCeActivity.java | 79 +++++++ ...eMainComponentUuidColumnsToCeActivity.java | 46 ++++ ...lateMainComponentUuidColumnsToCeQueue.java | 32 +++ ...lateMainComponentUuidColumnsToCeTable.java | 62 +++++ .../version/v74/DbVersion74Test.java | 2 +- .../server/platform/ws/MigrateDataAction.java | 12 +- 18 files changed, 782 insertions(+), 44 deletions(-) create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddLastKeyColumnsToCeActivity.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddMainComponentUuidColumnsToCeActivity.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddMainComponentUuidColumnsToCeQueue.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddMainComponentUuidColumnsToCeTable.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateLastKeyColumnsToCeActivity.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateMainComponentUuidColumnsToCeActivity.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateMainComponentUuidColumnsToCeQueue.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateMainComponentUuidColumnsToCeTable.java diff --git a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl index 81a1b3b17a0..b7fa9b36bc7 100644 --- a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl +++ b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl @@ -669,6 +669,7 @@ CREATE TABLE "CE_QUEUE" ( "UUID" VARCHAR(40) NOT NULL, "TASK_TYPE" VARCHAR(15) NOT NULL, "COMPONENT_UUID" VARCHAR(40) NULL, + "MAIN_COMPONENT_UUID" VARCHAR(40) NULL, "TMP_COMPONENT_UUID" VARCHAR(40) NULL, "TMP_MAIN_COMPONENT_UUID" VARCHAR(40) NULL, "STATUS" VARCHAR(15) NOT NULL, @@ -680,7 +681,8 @@ CREATE TABLE "CE_QUEUE" ( "UPDATED_AT" BIGINT NOT NULL ); CREATE UNIQUE INDEX "CE_QUEUE_UUID" ON "CE_QUEUE" ("UUID"); -CREATE INDEX "CE_QUEUE_COMPONENT_UUID" ON "CE_QUEUE" ("COMPONENT_UUID"); +CREATE INDEX "CE_QUEUE_COMPONENT" ON "CE_QUEUE" ("COMPONENT_UUID"); +CREATE INDEX "CE_QUEUE_MAIN_COMPONENT" ON "CE_QUEUE" ("MAIN_COMPONENT_UUID"); CREATE INDEX "CE_QUEUE_TMP_CPNT_UUID" ON "CE_QUEUE" ("TMP_COMPONENT_UUID"); CREATE INDEX "CE_QUEUE_TMP_MAIN_CPNT_UUID" ON "CE_QUEUE" ("TMP_MAIN_COMPONENT_UUID"); CREATE INDEX "CE_QUEUE_STATUS" ON "CE_QUEUE" ("STATUS"); @@ -691,12 +693,15 @@ CREATE TABLE "CE_ACTIVITY" ( "UUID" VARCHAR(40) NOT NULL, "TASK_TYPE" VARCHAR(15) NOT NULL, "COMPONENT_UUID" VARCHAR(40) NULL, + "MAIN_COMPONENT_UUID" VARCHAR(40) NULL, "TMP_COMPONENT_UUID" VARCHAR(40) NULL, "TMP_MAIN_COMPONENT_UUID" VARCHAR(40) NULL, "ANALYSIS_UUID" VARCHAR(50) NULL, "STATUS" VARCHAR(15) NOT NULL, "IS_LAST" BOOLEAN, "IS_LAST_KEY" VARCHAR(55), + "MAIN_IS_LAST" BOOLEAN, + "MAIN_IS_LAST_KEY" VARCHAR(55), "TMP_IS_LAST" BOOLEAN, "TMP_IS_LAST_KEY" VARCHAR(55), "TMP_MAIN_IS_LAST" BOOLEAN, @@ -715,11 +720,14 @@ CREATE TABLE "CE_ACTIVITY" ( "ERROR_TYPE" VARCHAR(20) ); CREATE UNIQUE INDEX "CE_ACTIVITY_UUID" ON "CE_ACTIVITY" ("UUID"); +CREATE INDEX "CE_ACTIVITY_COMPONENT" ON "CE_ACTIVITY" ("COMPONENT_UUID"); +CREATE INDEX "CE_ACTIVITY_MAIN_COMPONENT" ON "CE_ACTIVITY" ("COMPONENT_UUID"); CREATE INDEX "CE_ACTIVITY_COMPONENT_UUID" ON "CE_ACTIVITY" ("COMPONENT_UUID"); CREATE INDEX "CE_ACTIVITY_TMP_CPNT_UUID" ON "CE_ACTIVITY" ("TMP_COMPONENT_UUID"); -CREATE INDEX "CE_ACTIVITY_TMP_MAIN_CPNT_UUID" ON "CE_ACTIVITY" ("TMP_MAIN_COMPONENT_UUID"); -CREATE INDEX "CE_ACTIVITY_ISLASTKEY" ON "CE_ACTIVITY" ("IS_LAST_KEY"); -CREATE INDEX "CE_ACTIVITY_ISLAST_STATUS" ON "CE_ACTIVITY" ("IS_LAST", "STATUS"); +CREATE INDEX "CE_ACTIVITY_ISLAST_KEY" ON "CE_ACTIVITY" ("IS_LAST_KEY"); +CREATE INDEX "CE_ACTIVITY_ISLAST" ON "CE_ACTIVITY" ("IS_LAST", "STATUS"); +CREATE INDEX "CE_ACTIVITY_MAIN_ISLAST_KEY" ON "CE_ACTIVITY" ("MAIN_IS_LAST_KEY"); +CREATE INDEX "CE_ACTIVITY_MAIN_ISLAST" ON "CE_ACTIVITY" ("MAIN_IS_LAST", "STATUS"); CREATE INDEX "CE_ACTIVITY_T_ISLAST_KEY" ON "CE_ACTIVITY" ("TMP_IS_LAST_KEY"); CREATE INDEX "CE_ACTIVITY_T_ISLAST" ON "CE_ACTIVITY" ("TMP_IS_LAST", "STATUS"); CREATE INDEX "CE_ACTIVITY_T_MAIN_ISLAST_KEY" ON "CE_ACTIVITY" ("TMP_MAIN_IS_LAST_KEY"); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeActivityDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeActivityDao.java index 6791b86ee08..71c6c5ea4ba 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeActivityDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeActivityDao.java @@ -51,7 +51,8 @@ public class CeActivityDao implements Dao { CeActivityMapper ceActivityMapper = mapper(dbSession); if (isLast) { - ceActivityMapper.clearIsLast(dto.getIsLastKey(), dto.getMainIsLastKey(), dto.getUpdatedAt()); + ceActivityMapper.clearIsLast(dto.getIsLastKey(), dto.getUpdatedAt()); + ceActivityMapper.clearMainIsLast(dto.getMainIsLastKey(), dto.getUpdatedAt()); } ceActivityMapper.insert(dto); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeActivityMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeActivityMapper.java index bc36fd2d9dd..42b7fedab7c 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeActivityMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeActivityMapper.java @@ -38,7 +38,9 @@ public interface CeActivityMapper { void insert(CeActivityDto dto); - void clearIsLast(@Param("isLastKey") String isLastKey, @Param("mainIsLastKey") String mainIsLastKey, @Param("updatedAt") long updatedAt); + void clearIsLast(@Param("isLastKey") String isLastKey, @Param("updatedAt") long updatedAt); + + void clearMainIsLast(@Param("mainIsLastKey") String mainIsLastKey, @Param("updatedAt") long updatedAt); void deleteByUuids(@Param("uuids") List uuids); } diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml index b5be2b8d9aa..213a996e172 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml @@ -19,8 +19,8 @@ ca.id, ca.uuid, ca.task_type as taskType, - ca.tmp_component_uuid as componentUuid, - ca.tmp_main_component_uuid as mainComponentUuid, + ca.component_uuid as componentUuid, + ca.main_component_uuid as mainComponentUuid, ca.analysis_uuid as analysisUuid, ca.status as status, ca.submitter_uuid as submitterUuid, @@ -30,10 +30,10 @@ ca.executed_at as executedAt, ca.created_at as createdAt, ca.updated_at as updatedAt, - ca.tmp_is_last as isLast, - ca.tmp_is_last_key as isLastKey, - ca.tmp_main_is_last as mainIsLast, - ca.tmp_main_is_last_key as mainIsLastKey, + ca.is_last as isLast, + ca.is_last_key as isLastKey, + ca.main_is_last as mainIsLast, + ca.main_is_last_key as mainIsLastKey, ca.execution_time_ms as executionTimeMs, ca.error_message as errorMessage, ca.error_type as errorType, @@ -86,10 +86,10 @@ left outer join ce_scanner_context csc on csc.task_uuid = ca.uuid - and ca.tmp_main_is_last=${_true} + and ca.main_is_last=${_true} - and ca.tmp_main_component_uuid in + and ca.main_component_uuid in #{cUuid,jdbcType=VARCHAR} @@ -127,21 +127,27 @@ from ce_activity where - tmp_main_is_last=${_true} + main_is_last=${_true} and status=#{status,jdbcType=VARCHAR} - and tmp_main_component_uuid=#{mainComponentUuid,jdbcType=VARCHAR} + and main_component_uuid=#{mainComponentUuid,jdbcType=VARCHAR} insert into ce_activity ( uuid, + component_uuid, + main_component_uuid, tmp_component_uuid, tmp_main_component_uuid, analysis_uuid, status, task_type, + is_last, + is_last_key, + main_is_last, + main_is_last_key, tmp_is_last, tmp_is_last_key, tmp_main_is_last, @@ -163,6 +169,8 @@ #{uuid,jdbcType=VARCHAR}, #{componentUuid,jdbcType=VARCHAR}, #{mainComponentUuid,jdbcType=VARCHAR}, + #{componentUuid,jdbcType=VARCHAR}, + #{mainComponentUuid,jdbcType=VARCHAR}, #{analysisUuid,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{taskType,jdbcType=VARCHAR}, @@ -170,6 +178,10 @@ #{isLastKey,jdbcType=VARCHAR}, #{mainIsLast,jdbcType=BOOLEAN}, #{mainIsLastKey,jdbcType=VARCHAR}, + #{isLast,jdbcType=BOOLEAN}, + #{isLastKey,jdbcType=VARCHAR}, + #{mainIsLast,jdbcType=BOOLEAN}, + #{mainIsLastKey,jdbcType=VARCHAR}, #{submitterUuid,jdbcType=VARCHAR}, #{submittedAt,jdbcType=BIGINT}, #{workerUuid,jdbcType=VARCHAR}, @@ -187,13 +199,22 @@ update ce_activity set + is_last=${_false}, + updated_at=#{updatedAt,jdbcType=BIGINT} + where + is_last=${_true} + and is_last_key=#{isLastKey,jdbcType=VARCHAR} + + + + update ce_activity set + main_is_last=${_false}, tmp_is_last=${_false}, tmp_main_is_last=${_false}, updated_at=#{updatedAt,jdbcType=BIGINT} where - (tmp_is_last=${_true} and tmp_is_last_key=#{isLastKey,jdbcType=VARCHAR}) - or - (tmp_main_is_last=${_true} and tmp_main_is_last_key=#{mainIsLastKey,jdbcType=VARCHAR}) + main_is_last=${_true} + and main_is_last_key=#{mainIsLastKey,jdbcType=VARCHAR} diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeQueueMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeQueueMapper.xml index 3135f04da16..ea523ace644 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeQueueMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeQueueMapper.xml @@ -6,8 +6,8 @@ cq.uuid, cq.task_type as taskType, - cq.tmp_component_uuid as componentUuid, - cq.tmp_main_component_uuid as mainComponentUuid, + cq.component_uuid as componentUuid, + cq.main_component_uuid as mainComponentUuid, cq.status as status, cq.submitter_uuid as submitterUuid, cq.worker_uuid as workerUuid, @@ -45,23 +45,23 @@ where status=#{status,jdbcType=VARCHAR} - and tmp_main_component_uuid=#{mainComponentUuid,jdbcType=VARCHAR} + and main_component_uuid=#{mainComponentUuid,jdbcType=VARCHAR} @@ -107,7 +107,7 @@ ce_queue cq - and cq.tmp_main_component_uuid in + and cq.main_component_uuid in #{mainComponentUuid,jdbcType=VARCHAR} @@ -177,7 +177,7 @@ from ce_queue cq2 where - cq.tmp_main_component_uuid=cq2.tmp_main_component_uuid + cq.main_component_uuid=cq2.main_component_uuid and cq2.status <> 'PENDING' ) @@ -212,6 +212,8 @@ ( uuid, task_type, + component_uuid, + main_component_uuid, tmp_component_uuid, tmp_main_component_uuid, status, @@ -225,6 +227,8 @@ #{taskType,jdbcType=VARCHAR}, #{componentUuid,jdbcType=VARCHAR}, #{mainComponentUuid,jdbcType=VARCHAR}, + #{componentUuid,jdbcType=VARCHAR}, + #{mainComponentUuid,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{submitterUuid,jdbcType=VARCHAR}, 0, diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml index 1cca92d67d3..074b447023f 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml @@ -315,45 +315,45 @@ delete from ce_scanner_context where - task_uuid in (select uuid from ce_activity where tmp_main_component_uuid=#{projectUuid,jdbcType=VARCHAR}) + task_uuid in (select uuid from ce_activity where main_component_uuid=#{projectUuid,jdbcType=VARCHAR}) delete from ce_task_characteristics where - task_uuid in (select uuid from ce_activity where tmp_main_component_uuid=#{projectUuid,jdbcType=VARCHAR}) + task_uuid in (select uuid from ce_activity where main_component_uuid=#{projectUuid,jdbcType=VARCHAR}) delete from ce_task_input where - task_uuid in (select uuid from ce_activity where tmp_main_component_uuid=#{projectUuid,jdbcType=VARCHAR}) + task_uuid in (select uuid from ce_activity where main_component_uuid=#{projectUuid,jdbcType=VARCHAR}) - delete from ce_activity where tmp_main_component_uuid=#{projectUuid,jdbcType=VARCHAR} + delete from ce_activity where main_component_uuid=#{projectUuid,jdbcType=VARCHAR} delete from ce_scanner_context where - task_uuid in (select uuid from ce_queue where tmp_main_component_uuid=#{projectUuid,jdbcType=VARCHAR}) + task_uuid in (select uuid from ce_queue where main_component_uuid=#{projectUuid,jdbcType=VARCHAR}) delete from ce_task_characteristics where - task_uuid in (select uuid from ce_queue where tmp_main_component_uuid=#{projectUuid,jdbcType=VARCHAR}) + task_uuid in (select uuid from ce_queue where main_component_uuid=#{projectUuid,jdbcType=VARCHAR}) delete from ce_task_input where - task_uuid in (select uuid from ce_queue where tmp_main_component_uuid=#{projectUuid,jdbcType=VARCHAR}) + task_uuid in (select uuid from ce_queue where main_component_uuid=#{projectUuid,jdbcType=VARCHAR}) - delete from ce_queue where tmp_main_component_uuid=#{projectUuid,jdbcType=VARCHAR} + delete from ce_queue where main_component_uuid=#{projectUuid,jdbcType=VARCHAR} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java index ff8226a5235..c38abaec26e 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java @@ -22,15 +22,24 @@ package org.sonar.db.ce; import com.google.common.base.Function; import com.google.common.base.Strings; import com.google.common.collect.ImmutableSet; +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import org.assertj.core.api.AbstractListAssert; +import org.assertj.core.api.ObjectAssert; +import org.assertj.core.groups.Tuple; import org.junit.Rule; import org.junit.Test; +import org.junit.runner.RunWith; import org.sonar.api.utils.internal.TestSystem2; import org.sonar.core.util.CloseableIterator; +import org.sonar.core.util.UuidFactoryFast; import org.sonar.core.util.stream.MoreCollectors; import org.sonar.db.DbSession; import org.sonar.db.DbTester; @@ -40,13 +49,16 @@ import static java.util.Collections.singleton; import static java.util.Collections.singletonList; import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; import static org.sonar.db.Pagination.forPage; +import static org.sonar.db.ce.CeActivityDto.Status.CANCELED; import static org.sonar.db.ce.CeActivityDto.Status.FAILED; import static org.sonar.db.ce.CeActivityDto.Status.SUCCESS; import static org.sonar.db.ce.CeQueueDto.Status.PENDING; import static org.sonar.db.ce.CeQueueTesting.makeInProgress; import static org.sonar.db.ce.CeTaskTypes.REPORT; +@RunWith(DataProviderRunner.class) public class CeActivityDaoTest { private static final String MAINCOMPONENT_1 = randomAlphabetic(12); @@ -91,6 +103,197 @@ public class CeActivityDaoTest { assertThat(dto.isHasScannerContext()).isFalse(); } + @Test + @UseDataProvider("notCanceledStatus") + public void insert_resets_is_last_and_main_is_last_fields_based_on_component_and_main_component(CeActivityDto.Status status) { + String project1 = randomAlphabetic(5); + String branch11 = randomAlphabetic(6); + String project2 = randomAlphabetic(8); + String branch21 = randomAlphabetic(9); + String type = randomAlphabetic(10); + + String task1Project1 = insertAndCommit(newUuid(), type, project1, project1, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(task1Project1).containsOnly(tuple(true, true)); + + String task2Project1 = insertAndCommit(newUuid(), type, project1, project1, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(task1Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Project1).containsOnly(tuple(true, true)); + + String task1Branch11 = insertAndCommit(newUuid(), type, branch11, project1, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(task1Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Project1).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(task1Branch11).containsOnly(tuple(true, true)); + + String task2Branch11 = insertAndCommit(newUuid(), type, branch11, project1, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(task1Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Project1).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(task1Branch11).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Branch11).containsOnly(tuple(true, true)); + + String task1Project2 = insertAndCommit(newUuid(), type, project2, project2, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(task1Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Project1).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(task1Branch11).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Branch11).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(task1Project2).containsOnly(tuple(true, true)); + + String task2Project2 = insertAndCommit(newUuid(), type, project2, project2, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(task1Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Project1).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(task1Branch11).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Branch11).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(task1Project2).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Project2).containsOnly(tuple(true, true)); + + String task1Branch21 = insertAndCommit(newUuid(), type, branch21, project2, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(task1Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Project1).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(task1Branch11).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Branch11).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(task1Project2).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Project2).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(task1Branch21).containsOnly(tuple(true, true)); + + String task3project1 = insertAndCommit(newUuid(), type, project1, project1, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(task1Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task1Branch11).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Branch11).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(task1Project2).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task2Project2).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(task1Branch21).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(task3project1).containsOnly(tuple(true, true)); + } + + @Test + @UseDataProvider("notCanceledStatus") + public void insert_resets_is_last_and_main_is_last_fields_based_on_type(CeActivityDto.Status status) { + String type1 = randomAlphabetic(10); + String type2 = randomAlphabetic(11); + String project = randomAlphabetic(5); + String branch = randomAlphabetic(6); + + String type1Project1 = insertAndCommit(newUuid(), type1, project, project, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(type1Project1).containsOnly(tuple(true, true)); + + String type2Project1 = insertAndCommit(newUuid(), type2, project, project, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(type1Project1).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(type2Project1).containsOnly(tuple(true, true)); + + String type2Project2 = insertAndCommit(newUuid(), type2, project, project, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(type1Project1).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(type2Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(type2Project2).containsOnly(tuple(true, true)); + + String type1Branch1 = insertAndCommit(newUuid(), type1, branch, project, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(type1Project1).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(type2Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(type2Project2).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(type1Branch1).containsOnly(tuple(true, true)); + + String type2Branch1 = insertAndCommit(newUuid(), type2, branch, project, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(type1Project1).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(type2Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(type2Project2).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(type1Branch1).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(type2Branch1).containsOnly(tuple(true, true)); + + String type2Branch2 = insertAndCommit(newUuid(), type2, branch, project, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(type1Project1).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(type2Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(type2Project2).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(type1Branch1).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(type2Branch1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(type2Branch2).containsOnly(tuple(true, true)); + } + + @Test + @UseDataProvider("notCanceledStatus") + public void insert_resets_is_last_and_main_is_last_fields_based_on_component_or_not(CeActivityDto.Status status) { + String project = randomAlphabetic(5); + String type1 = randomAlphabetic(11); + String type2 = randomAlphabetic(11); + + String type1Project1 = insertAndCommit(newUuid(), type1, project, project, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(type1Project1).containsOnly(tuple(true, true)); + + String type1NoProject1 = insertAndCommit(newUuid(), type1, null, null, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(type1Project1).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(type1NoProject1).containsOnly(tuple(true, true)); + + String type1NoProject2 = insertAndCommit(newUuid(), type1, null, null, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(type1Project1).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(type1NoProject1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(type1NoProject2).containsOnly(tuple(true, true)); + + String type2NoProject1 = insertAndCommit(newUuid(), type2, null, null, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(type1Project1).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(type1NoProject1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(type1NoProject2).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(type2NoProject1).containsOnly(tuple(true, true)); + + String type2NoProject2 = insertAndCommit(newUuid(), type2, null, null, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(type1Project1).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(type1NoProject1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(type1NoProject2).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(type2NoProject1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(type2NoProject2).containsOnly(tuple(true, true)); + + String type1Project2 = insertAndCommit(newUuid(), type1, project, project, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(type1Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(type1NoProject1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(type1NoProject2).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(type2NoProject1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(type2NoProject2).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(type1Project2).containsOnly(tuple(true, true)); + } + + @Test + @UseDataProvider("notCanceledStatus") + public void insert_does_not_resets_is_last_and_main_is_last_fields_if_status_is_CANCELED(CeActivityDto.Status status) { + String project = randomAlphabetic(5); + String branch = randomAlphabetic(6); + String type = randomAlphabetic(10); + + String task1Project1 = insertAndCommit(newUuid(), type, project, project, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(task1Project1).containsOnly(tuple(true, true)); + + String task1Project2 = insertAndCommit(newUuid(), type, project, project, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(task1Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task1Project2).containsOnly(tuple(true, true)); + + String task1Project3 = insertAndCommit(newUuid(), type, project, project, CANCELED).getUuid(); + assertIsLastAndMainIsLastFieldsOf(task1Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task1Project2).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(task1Project3).containsOnly(tuple(false, false)); + + String task1Branch1 = insertAndCommit(newUuid(), type, branch, project, status).getUuid(); + assertIsLastAndMainIsLastFieldsOf(task1Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task1Project2).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(task1Project3).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task1Branch1).containsOnly(tuple(true, true)); + + String task1Branch2 = insertAndCommit(newUuid(), type, branch, project, CANCELED).getUuid(); + assertIsLastAndMainIsLastFieldsOf(task1Project1).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task1Project2).containsOnly(tuple(true, false)); + assertIsLastAndMainIsLastFieldsOf(task1Project3).containsOnly(tuple(false, false)); + assertIsLastAndMainIsLastFieldsOf(task1Branch1).containsOnly(tuple(true, true)); + assertIsLastAndMainIsLastFieldsOf(task1Branch2).containsOnly(tuple(false, false)); + } + + @DataProvider + public static Object[][] notCanceledStatus() { + return Arrays.stream(CeActivityDto.Status.values()) + .filter(t -> t != CANCELED) + .map(t -> new Object[] {t}) + .toArray(Object[][]::new); + } + + private AbstractListAssert, Tuple, ObjectAssert> assertIsLastAndMainIsLastFieldsOf(String taskUuid) { + return assertThat(db.select("select is_last as \"IS_LAST\", main_is_last as \"MAIN_IS_LAST\" from ce_activity where uuid='" + taskUuid + "'")) + .extracting(t -> (Boolean) t.get("IS_LAST"), t -> (Boolean) t.get("MAIN_IS_LAST")); + } + @Test public void test_insert_of_errorMessage_of_1_000_chars() { CeActivityDto dto = createActivityDto("TASK_1", REPORT, COMPONENT_1, MAINCOMPONENT_1, CeActivityDto.Status.FAILED) @@ -352,7 +555,13 @@ public class CeActivityDaoTest { return insert(uuid, type, mainComponentUuid, mainComponentUuid, status); } - private CeActivityDto insert(String uuid, String type, String componentUuid, @Nullable String mainComponentUuid, CeActivityDto.Status status) { + private CeActivityDto insertAndCommit(String uuid, String type, @Nullable String componentUuid, @Nullable String mainComponentUuid, CeActivityDto.Status status) { + CeActivityDto res = insert(uuid, type, componentUuid, mainComponentUuid, status); + db.commit(); + return res; + } + + private CeActivityDto insert(String uuid, String type, @Nullable String componentUuid, @Nullable String mainComponentUuid, CeActivityDto.Status status) { CeActivityDto dto = createActivityDto(uuid, type, componentUuid, mainComponentUuid, status); underTest.insert(db.getSession(), dto); return dto; @@ -418,4 +627,8 @@ public class CeActivityDaoTest { return input.getUuid(); } } + + private static String newUuid() { + return UuidFactoryFast.getInstance().create(); + } } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddLastKeyColumnsToCeActivity.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddLastKeyColumnsToCeActivity.java new file mode 100644 index 00000000000..515268559bd --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddLastKeyColumnsToCeActivity.java @@ -0,0 +1,119 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.v74; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.SupportsBlueGreen; +import org.sonar.server.platform.db.migration.def.BooleanColumnDef; +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.sql.CreateIndexBuilder; +import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder; +import org.sonar.server.platform.db.migration.sql.DropIndexBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +import static org.sonar.server.platform.db.migration.def.BooleanColumnDef.newBooleanColumnDefBuilder; +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE; +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; + +@SupportsBlueGreen +public class AddLastKeyColumnsToCeActivity extends DdlChange { + private static final String TABLE_NAME = "ce_activity"; + private static final int TASK_TYPE_COLUMN_SIZE = 15; + private static final BooleanColumnDef COLUMN_IS_LAST = newBooleanColumnDefBuilder() + .setColumnName("is_last") + .setIsNullable(true) + .build(); + private static final VarcharColumnDef COLUMN_IS_LAST_KEY = newVarcharColumnDefBuilder() + .setColumnName("is_last_key") + .setLimit(UUID_SIZE + TASK_TYPE_COLUMN_SIZE) + .setIsNullable(true) + .build(); + private static final BooleanColumnDef COLUMN_MAIN_IS_LAST = newBooleanColumnDefBuilder() + .setColumnName("main_is_last") + .setIsNullable(true) + .build(); + private static final VarcharColumnDef COLUMN_MAIN_IS_LAST_KEY = newVarcharColumnDefBuilder() + .setColumnName("main_is_last_key") + .setLimit(UUID_SIZE + TASK_TYPE_COLUMN_SIZE) + .setIsNullable(true) + .build(); + private static final VarcharColumnDef COLUMN_STATUS = newVarcharColumnDefBuilder() + .setColumnName("status") + .setLimit(15) + .setIsNullable(false) + .build(); + + public AddLastKeyColumnsToCeActivity(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + // drop existing column with wrong values + context.execute(new DropIndexBuilder(getDialect()) + .setTable(TABLE_NAME) + .setName("ce_activity_islastkey") + .build()); + context.execute(new DropIndexBuilder(getDialect()) + .setTable(TABLE_NAME) + .setName("ce_activity_islast_status") + .build()); + context.execute(new DropColumnsBuilder(getDialect(), TABLE_NAME, COLUMN_IS_LAST.getName(), COLUMN_IS_LAST_KEY.getName()) + .build()); + + + context.execute(new AddColumnsBuilder(getDialect(), TABLE_NAME) + .addColumn(COLUMN_IS_LAST) + .addColumn(COLUMN_IS_LAST_KEY) + .addColumn(COLUMN_MAIN_IS_LAST) + .addColumn(COLUMN_MAIN_IS_LAST_KEY) + .build()); + + // create indexes + context.execute(new CreateIndexBuilder(getDialect()) + .setTable(TABLE_NAME) + .setName(TABLE_NAME + "_islast_key") + .addColumn(COLUMN_IS_LAST_KEY) + .setUnique(false) + .build()); + context.execute(new CreateIndexBuilder(getDialect()) + .setTable(TABLE_NAME) + .setName(TABLE_NAME + "_islast") + .addColumn(COLUMN_IS_LAST) + .addColumn(COLUMN_STATUS) + .setUnique(false) + .build()); + context.execute(new CreateIndexBuilder(getDialect()) + .setTable(TABLE_NAME) + .setName(TABLE_NAME + "_main_islast_key") + .addColumn(COLUMN_MAIN_IS_LAST_KEY) + .setUnique(false) + .build()); + context.execute(new CreateIndexBuilder(getDialect()) + .setTable(TABLE_NAME) + .setName(TABLE_NAME + "_main_islast") + .addColumn(COLUMN_MAIN_IS_LAST) + .addColumn(COLUMN_STATUS) + .setUnique(false) + .build()); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddMainComponentUuidColumnsToCeActivity.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddMainComponentUuidColumnsToCeActivity.java new file mode 100644 index 00000000000..dc48dade091 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddMainComponentUuidColumnsToCeActivity.java @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.v74; + +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.SupportsBlueGreen; + +@SupportsBlueGreen +public class AddMainComponentUuidColumnsToCeActivity extends AddMainComponentUuidColumnsToCeTable { + + public AddMainComponentUuidColumnsToCeActivity(Database db) { + super(db, "ce_activity"); + } + +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddMainComponentUuidColumnsToCeQueue.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddMainComponentUuidColumnsToCeQueue.java new file mode 100644 index 00000000000..e8bedd32ac3 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddMainComponentUuidColumnsToCeQueue.java @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.v74; + +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.SupportsBlueGreen; + +@SupportsBlueGreen +public class AddMainComponentUuidColumnsToCeQueue extends AddMainComponentUuidColumnsToCeTable { + + public AddMainComponentUuidColumnsToCeQueue(Database db) { + super(db, "ce_queue"); + } + +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddMainComponentUuidColumnsToCeTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddMainComponentUuidColumnsToCeTable.java new file mode 100644 index 00000000000..e2e7b5b1b7a --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddMainComponentUuidColumnsToCeTable.java @@ -0,0 +1,81 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.v74; + +import java.sql.SQLException; +import org.sonar.db.Database; +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.sql.CreateIndexBuilder; +import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder; +import org.sonar.server.platform.db.migration.sql.DropIndexBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; + +public abstract class AddMainComponentUuidColumnsToCeTable extends DdlChange { + private static final VarcharColumnDef COLUMN_COMPONENT_UUID = newVarcharColumnDefBuilder() + .setColumnName("component_uuid") + .setLimit(VarcharColumnDef.UUID_SIZE) + .setIsNullable(true) + .build(); + private static final VarcharColumnDef COLUMN_MAIN_COMPONENT_UUID = newVarcharColumnDefBuilder() + .setColumnName("main_component_uuid") + .setLimit(VarcharColumnDef.UUID_SIZE) + .setIsNullable(true) + .build(); + private final String tableName; + + AddMainComponentUuidColumnsToCeTable(Database db, String tableName) { + super(db); + this.tableName = tableName; + } + + @Override + public void execute(Context context) throws SQLException { + // drop existing column with wrong values + context.execute(new DropIndexBuilder(getDialect()) + .setTable(tableName) + .setName(tableName + "_component_uuid") + .build()); + context.execute(new DropColumnsBuilder(getDialect(), tableName, COLUMN_COMPONENT_UUID.getName()) + .build()); + + // add new columns + context.execute(new AddColumnsBuilder(getDialect(), tableName) + .addColumn(COLUMN_COMPONENT_UUID) + .addColumn(COLUMN_MAIN_COMPONENT_UUID) + .build()); + + // create indexes + context.execute(new CreateIndexBuilder(getDialect()) + .setTable(tableName) + .setName(tableName + "_component") + .addColumn(COLUMN_COMPONENT_UUID) + .setUnique(false) + .build()); + context.execute(new CreateIndexBuilder(getDialect()) + .setTable(tableName) + .setName(tableName + "_main_component") + .addColumn(COLUMN_MAIN_COMPONENT_UUID) + .setUnique(false) + .build()); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java index 642e3ef57f3..85b37533ee7 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java @@ -39,6 +39,12 @@ public class DbVersion74 implements DbVersion { .add(2309, "Add CE_ACTIVITY.MAIN_LAST_KEY 1/6", AddTmpLastKeyColumnsToCeActivity.class) .add(2310, "Populate CE_ACTIVITY.MAIN_LAST_KEY 2/6", PopulateTmpLastKeyColumnsToCeActivity.class) .add(2311, "Populate CE_ACTIVITY.MAIN_LAST_KEY 3/6", MakeCeActivityLastKeyColumnsNullable.class) + .add(2312, "Add CE_QUEUE.MAIN_COMPONENT_UUID 3/5", AddMainComponentUuidColumnsToCeQueue.class) + .add(2313, "Add CE_ACTIVITY.MAIN_COMPONENT_UUID 3/5", AddMainComponentUuidColumnsToCeActivity.class) + .add(2314, "Add CE_ACTIVITY.MAIN_LAST_KEY 3/6", AddLastKeyColumnsToCeActivity.class) + .add(2315, "Populate CE_QUEUE.MAIN_COMPONENT_UUID 4/5", PopulateMainComponentUuidColumnsToCeQueue.class) + .add(2316, "Populate CE_ACTIVITY.MAIN_COMPONENT_UUID 4/5", PopulateMainComponentUuidColumnsToCeActivity.class) + .add(2317, "Populate CE_ACTIVITY.MAIN_LAST_KEY 4/6", PopulateLastKeyColumnsToCeActivity.class) ; } } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateLastKeyColumnsToCeActivity.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateLastKeyColumnsToCeActivity.java new file mode 100644 index 00000000000..8fc66f2f1f0 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateLastKeyColumnsToCeActivity.java @@ -0,0 +1,79 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.v74; + +import java.sql.SQLException; +import org.sonar.api.config.Configuration; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.SupportsBlueGreen; +import org.sonar.server.platform.db.migration.step.DataChange; +import org.sonar.server.platform.db.migration.step.MassUpdate; +import org.sonar.server.platform.db.migration.step.Select; +import org.sonar.server.platform.db.migration.step.SqlStatement; + +@SupportsBlueGreen +public class PopulateLastKeyColumnsToCeActivity extends DataChange { + private static final String TABLE_NAME = "ce_activity"; + + private final Configuration configuration; + + public PopulateLastKeyColumnsToCeActivity(Database db, Configuration configuration) { + super(db); + this.configuration = configuration; + } + + @Override + protected void execute(Context context) throws SQLException { + if (configuration.getBoolean("sonar.sonarcloud.enabled").orElse(false)) { + // data migration will be done in background so that interruption of service + // is reduced during upgrade + return; + } + + MassUpdate massUpdate = context.prepareMassUpdate(); + massUpdate.select("select" + + " ca.uuid, ca.tmp_is_last, ca.tmp_is_last_key, ca.tmp_main_is_last, ca.tmp_main_is_last_key" + + " from ce_activity ca" + + " where" + + " ca.is_last is null" + + " or ca.is_last_key is null" + + " or ca.main_is_last is null" + + " or ca.main_is_last_key is null"); + massUpdate.rowPluralName("rows of " + TABLE_NAME); + massUpdate.update("update " + TABLE_NAME + " set is_last=?, is_last_key=?, main_is_last=?, main_is_last_key=? where uuid=?"); + massUpdate.execute(PopulateLastKeyColumnsToCeActivity::handleUpdate); + } + + private static boolean handleUpdate(Select.Row row, SqlStatement update) throws SQLException { + String uuid = row.getString(1); + boolean isLast = row.getBoolean(2); + String isLastKey = row.getString(3); + boolean mainIsLast = row.getBoolean(2); + String mainIsLastKey = row.getString(3); + + update.setBoolean(1, isLast); + update.setString(2, isLastKey); + update.setBoolean(3, mainIsLast); + update.setString(4, mainIsLastKey); + update.setString(5, uuid); + + return true; + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateMainComponentUuidColumnsToCeActivity.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateMainComponentUuidColumnsToCeActivity.java new file mode 100644 index 00000000000..ae2b75fb1d9 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateMainComponentUuidColumnsToCeActivity.java @@ -0,0 +1,46 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.v74; + +import java.sql.SQLException; +import org.sonar.api.config.Configuration; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.SupportsBlueGreen; + +@SupportsBlueGreen +public class PopulateMainComponentUuidColumnsToCeActivity extends PopulateMainComponentUuidColumnsToCeTable { + private final Configuration configuration; + + public PopulateMainComponentUuidColumnsToCeActivity(Database db, Configuration configuration) { + super(db, "ce_activity"); + this.configuration = configuration; + } + + @Override + protected void execute(Context context) throws SQLException { + if (configuration.getBoolean("sonar.sonarcloud.enabled").orElse(false)) { + // data migration will be done in background so that interruption of service + // is reduced during upgrade + return; + } + + super.execute(context); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateMainComponentUuidColumnsToCeQueue.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateMainComponentUuidColumnsToCeQueue.java new file mode 100644 index 00000000000..2fae863074e --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateMainComponentUuidColumnsToCeQueue.java @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.v74; + +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.SupportsBlueGreen; + +@SupportsBlueGreen +public class PopulateMainComponentUuidColumnsToCeQueue extends PopulateMainComponentUuidColumnsToCeTable { + + public PopulateMainComponentUuidColumnsToCeQueue(Database db) { + super(db, "ce_queue"); + } + +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateMainComponentUuidColumnsToCeTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateMainComponentUuidColumnsToCeTable.java new file mode 100644 index 00000000000..b59af219fe5 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateMainComponentUuidColumnsToCeTable.java @@ -0,0 +1,62 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.v74; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.step.DataChange; +import org.sonar.server.platform.db.migration.step.MassUpdate; +import org.sonar.server.platform.db.migration.step.Select; +import org.sonar.server.platform.db.migration.step.SqlStatement; + +public abstract class PopulateMainComponentUuidColumnsToCeTable extends DataChange { + protected final String tableName; + + PopulateMainComponentUuidColumnsToCeTable(Database db, String tableName) { + super(db); + this.tableName = tableName; + } + + @Override + protected void execute(Context context) throws SQLException { + MassUpdate massUpdate = context.prepareMassUpdate(); + massUpdate.select("select" + + " c.uuid, c.tmp_component_uuid, c.tmp_main_component_uuid" + + " from " + tableName + " c" + + " where" + + " c.tmp_component_uuid is not null" + + " and (c.component_uuid is null or c.main_component_uuid is null)"); + massUpdate.rowPluralName("tasks with component"); + massUpdate.update("update " + tableName + " set component_uuid=?, main_component_uuid=? where uuid=?"); + massUpdate.execute(PopulateMainComponentUuidColumnsToCeTable::handleUpdate); + } + + private static boolean handleUpdate(Select.Row row, SqlStatement update) throws SQLException { + String uuid = row.getString(1); + String componentUuuid = row.getString(2); + String mainComponentUuuid = row.getString(3); + + update.setString(1, componentUuuid); + update.setString(2, mainComponentUuuid); + update.setString(3, uuid); + + return true; + } +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74Test.java index 7f5028ad332..5064842d84d 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74Test.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74Test.java @@ -35,6 +35,6 @@ public class DbVersion74Test { @Test public void verify_migration_count() { - verifyMigrationCount(underTest, 12); + verifyMigrationCount(underTest, 18); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDataAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDataAction.java index 0c4dde8885f..5a8cb42cf86 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDataAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDataAction.java @@ -27,9 +27,9 @@ import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.db.DbClient; -import org.sonar.server.platform.db.migration.version.v74.PopulateTmpColumnsToCeActivity; -import org.sonar.server.platform.db.migration.version.v74.PopulateTmpColumnsToCeQueue; -import org.sonar.server.platform.db.migration.version.v74.PopulateTmpLastKeyColumnsToCeActivity; +import org.sonar.server.platform.db.migration.version.v74.PopulateLastKeyColumnsToCeActivity; +import org.sonar.server.platform.db.migration.version.v74.PopulateMainComponentUuidColumnsToCeActivity; +import org.sonar.server.platform.db.migration.version.v74.PopulateMainComponentUuidColumnsToCeQueue; import org.sonar.server.user.UserSession; public class MigrateDataAction implements SystemWsAction { @@ -55,9 +55,9 @@ public class MigrateDataAction implements SystemWsAction { userSession.isSystemAdministrator(); Configuration emptyConfiguration = new MapSettings().asConfig(); - new PopulateTmpColumnsToCeQueue(dbClient.getDatabase()).execute(); - new PopulateTmpColumnsToCeActivity(dbClient.getDatabase(), emptyConfiguration).execute(); - new PopulateTmpLastKeyColumnsToCeActivity(dbClient.getDatabase(), emptyConfiguration).execute(); + new PopulateMainComponentUuidColumnsToCeQueue(dbClient.getDatabase()).execute(); + new PopulateMainComponentUuidColumnsToCeActivity(dbClient.getDatabase(), emptyConfiguration).execute(); + new PopulateLastKeyColumnsToCeActivity(dbClient.getDatabase(), emptyConfiguration).execute(); LOG.info("done"); response.noContent(); -- 2.39.5