import java.util.Collection;
import java.util.List;
import java.util.Optional;
+import org.sonar.core.util.UuidFactory;
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
public class MeasureDao implements Dao {
+ private final UuidFactory uuidFactory;
+
+ public MeasureDao(UuidFactory uuidFactory) {
+ this.uuidFactory = uuidFactory;
+ }
+
public Optional<MeasureDto> selectLastMeasure(DbSession dbSession, String componentUuid, String metricKey) {
return Optional.ofNullable(mapper(dbSession).selectLastMeasure(componentUuid, metricKey));
}
}
public void insert(DbSession session, MeasureDto measureDto) {
+ measureDto.setUuid(uuidFactory.create());
mapper(session).insert(measureDto);
}
public void insert(DbSession session, Collection<MeasureDto> items) {
for (MeasureDto item : items) {
+ item.setUuid(uuidFactory.create());
insert(session, item);
}
}
public class MeasureDto {
private static final int MAX_TEXT_VALUE_LENGTH = 4000;
+ private String uuid;
private Double value;
private String textValue;
private byte[] dataValue;
private String analysisUuid;
private int metricId;
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
@CheckForNull
public Double getValue() {
return value;
<mapper namespace="org.sonar.db.measure.MeasureMapper">
<sql id="measureColumns">
+ pm.uuid as uuid,
pm.metric_id as metricId,
pm.component_uuid as componentUuid,
pm.analysis_uuid as analysisUuid,
<insert id="insert" parameterType="Measure" useGeneratedKeys="false">
insert into project_measures (
+ uuid,
value,
metric_id,
component_uuid,
variation_value_1,
measure_data)
VALUES (
+ #{uuid, jdbcType=VARCHAR},
#{value, jdbcType=DOUBLE},
#{metricId, jdbcType=INTEGER},
#{componentUuid, jdbcType=VARCHAR},
CREATE INDEX "PROJECT_UUID" ON "PROJECT_MAPPINGS"("PROJECT_UUID");
CREATE TABLE "PROJECT_MEASURES"(
- "ID" BIGINT NOT NULL AUTO_INCREMENT (1,1),
"VALUE" DOUBLE,
"METRIC_ID" INTEGER NOT NULL,
"ANALYSIS_UUID" VARCHAR(50) NOT NULL,
"VARIATION_VALUE_3" DOUBLE,
"VARIATION_VALUE_4" DOUBLE,
"VARIATION_VALUE_5" DOUBLE,
- "MEASURE_DATA" BLOB
+ "MEASURE_DATA" BLOB,
+ "UUID" VARCHAR(40) NOT NULL
);
-ALTER TABLE "PROJECT_MEASURES" ADD CONSTRAINT "PK_PROJECT_MEASURES" PRIMARY KEY("ID");
+ALTER TABLE "PROJECT_MEASURES" ADD CONSTRAINT "PK_PROJECT_MEASURES" PRIMARY KEY("UUID");
CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES"("ANALYSIS_UUID", "METRIC_ID");
CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES"("COMPONENT_UUID");
private void verifyMeasure(String componentUuid, String metricKey, String analysisUuid, String value) {
Optional<MeasureDto> measure = underTest.selectMeasure(db.getSession(), analysisUuid, componentUuid, metricKey);
assertThat(measure.map(MeasureDto::getData)).contains(value);
+ assertThat(measure.map(MeasureDto::getUuid)).isNotEmpty();
}
private void verifyMeasure(String componentUuid, String metricKey, String value) {
Optional<MeasureDto> measure = underTest.selectLastMeasure(db.getSession(), componentUuid, metricKey);
assertThat(measure.map(MeasureDto::getData)).contains(value);
+ assertThat(measure.map(MeasureDto::getUuid)).isNotEmpty();
}
private void verifyNoMeasure(String componentUuid, String metricKey, String analysisUuid) {
import org.sonar.server.platform.db.migration.version.v83.notifications.DropPrimaryKeyOnIdColumnOfNotificationTable;
import org.sonar.server.platform.db.migration.version.v83.notifications.MakeNotificationUuidAndCreatedAtColumnsNotNullable;
import org.sonar.server.platform.db.migration.version.v83.notifications.PopulateNotificationUuidAndCreatedAt;
+import org.sonar.server.platform.db.migration.version.v83.projectmeasures.AddPrimaryKeyOnUuidColumnOfProjectMeasuresTable;
+import org.sonar.server.platform.db.migration.version.v83.projectmeasures.AddUuidColumnToProjectMeasures;
+import org.sonar.server.platform.db.migration.version.v83.projectmeasures.DropIdColumnOfProjectMeasuresTable;
+import org.sonar.server.platform.db.migration.version.v83.projectmeasures.DropPrimaryKeyOnIdColumnOfProjectMeasuresTable;
+import org.sonar.server.platform.db.migration.version.v83.projectmeasures.MakeProjectMeasuresUuidColumnNotNullable;
+import org.sonar.server.platform.db.migration.version.v83.projectmeasures.PopulateProjectMeasureUuid;
import org.sonar.server.platform.db.migration.version.v83.snapshots.issues.AddPrimaryKeyOnUuidColumnOfSnapshotsTable;
import org.sonar.server.platform.db.migration.version.v83.snapshots.issues.DropIdColumnOfSnapshotsTable;
import org.sonar.server.platform.db.migration.version.v83.snapshots.issues.DropPrimaryKeyOnIdColumnOfSnapshotsTable;
.add(3431, "Drop primary key on 'ID' column of 'ACTIVE_RULE_PARAMS' table", DropPrimaryKeyOnIdColumnOfActiveRuleParametersTable.class)
.add(3432, "Add primary key on 'UUID' column of 'ACTIVE_RULE_PARAMS' table", AddPrimaryKeyOnUuidColumnOfActiveRuleParametersTable.class)
.add(3433, "Drop column 'ID' of 'ACTIVE_RULE_PARAMS' table", DropIdColumnOfActiveRuleParametersTable.class)
+
+ // Migration on PROJECT_MEASURES table
+ .add(3434, "Add 'uuid' columns for 'PROJECT_MEASURES'", AddUuidColumnToProjectMeasures.class)
+ .add(3435, "Populate 'uuid' column for 'PROJECT_MEASURES'", PopulateProjectMeasureUuid.class)
+ .add(3436, "Make 'uuid' column not nullable for 'PROJECT_MEASURES'", MakeProjectMeasuresUuidColumnNotNullable.class)
+ .add(3437, "Drop primary key on 'ID' column of 'PROJECT_MEASURES' table", DropPrimaryKeyOnIdColumnOfProjectMeasuresTable.class)
+ .add(3438, "Add primary key on 'UUID' column of 'PROJECT_MEASURES' table", AddPrimaryKeyOnUuidColumnOfProjectMeasuresTable.class)
+ .add(3439, "Drop column 'ID' of 'PROJECT_MEASURES' table", DropIdColumnOfProjectMeasuresTable.class)
;
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.v83.projectmeasures;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+import org.sonar.server.platform.db.migration.version.v83.util.AddPrimaryKeyBuilder;
+
+public class AddPrimaryKeyOnUuidColumnOfProjectMeasuresTable extends DdlChange {
+
+ public AddPrimaryKeyOnUuidColumnOfProjectMeasuresTable(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new AddPrimaryKeyBuilder("project_measures", "uuid").build());
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.v83.projectmeasures;
+
+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.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class AddUuidColumnToProjectMeasures extends DdlChange {
+ private static final String TABLE = "project_measures";
+
+ private static final VarcharColumnDef uuidColumnDefinition = newVarcharColumnDefBuilder()
+ .setColumnName("uuid")
+ .setIsNullable(true)
+ .setDefaultValue(null)
+ .setLimit(VarcharColumnDef.UUID_SIZE)
+ .build();
+
+ public AddUuidColumnToProjectMeasures(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new AddColumnsBuilder(getDialect(), TABLE)
+ .addColumn(uuidColumnDefinition)
+ .build());
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.v83.projectmeasures;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class DropIdColumnOfProjectMeasuresTable extends DdlChange {
+
+ public DropIdColumnOfProjectMeasuresTable(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new DropColumnsBuilder(getDialect(), "project_measures", "id").build());
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.v83.projectmeasures;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+import org.sonar.server.platform.db.migration.version.v83.util.DropPrimaryKeySqlGenerator;
+
+public class DropPrimaryKeyOnIdColumnOfProjectMeasuresTable extends DdlChange {
+
+ private final DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator;
+
+ public DropPrimaryKeyOnIdColumnOfProjectMeasuresTable(Database db, DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator) {
+ super(db);
+ this.dropPrimaryKeySqlGenerator = dropPrimaryKeySqlGenerator;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(dropPrimaryKeySqlGenerator.generate("project_measures", "project_measures", "id"));
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.v83.projectmeasures;
+
+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.AlterColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class MakeProjectMeasuresUuidColumnNotNullable extends DdlChange {
+ private static final String TABLE = "project_measures";
+
+ private static final VarcharColumnDef uuidColumnDefinition = newVarcharColumnDefBuilder()
+ .setColumnName("uuid")
+ .setIsNullable(false)
+ .setDefaultValue(null)
+ .setLimit(VarcharColumnDef.UUID_SIZE)
+ .build();
+
+ public MakeProjectMeasuresUuidColumnNotNullable(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new AlterColumnsBuilder(getDialect(), TABLE)
+ .updateColumn(uuidColumnDefinition)
+ .build());
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.v83.projectmeasures;
+
+import java.sql.SQLException;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.MassUpdate;
+
+public class PopulateProjectMeasureUuid extends DataChange {
+
+ private final UuidFactory uuidFactory;
+
+ public PopulateProjectMeasureUuid(Database db, UuidFactory uuidFactory) {
+ super(db);
+ this.uuidFactory = uuidFactory;
+ }
+
+ @Override
+ protected void execute(Context context) throws SQLException {
+ MassUpdate massUpdate = context.prepareMassUpdate();
+
+ massUpdate.select("select id from project_measures where uuid is null");
+ massUpdate.update("update project_measures set uuid = ? where id = ?");
+
+ massUpdate.execute((row, update) -> {
+ update.setString(1, uuidFactory.create());
+ update.setLong(2, row.getLong(1));
+ return true;
+ });
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.v83.projectmeasures;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.MigrationStep;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class AddPrimaryKeyOnUuidColumnOfProjectMeasureTableTest {
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(AddPrimaryKeyOnUuidColumnOfProjectMeasureTableTest.class, "schema.sql");
+
+ private MigrationStep underTest = new AddPrimaryKeyOnUuidColumnOfProjectMeasuresTable(db.database());
+
+ @Test
+ public void execute() throws SQLException {
+ underTest.execute();
+
+ db.assertPrimaryKey("project_measures", "pk_project_measures", "uuid");
+ }
+
+ @Test
+ public void migration_is_not_re_entrant() throws SQLException {
+ underTest.execute();
+
+ assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.v83.projectmeasures;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class AddUuidToProjectMeasuresTest {
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(AddUuidToProjectMeasuresTest.class, "schema.sql");
+
+ private UuidFactory uuidFactory = UuidFactoryFast.getInstance();
+
+ private DdlChange underTest = new AddUuidColumnToProjectMeasures(db.database());
+
+ @Before
+ public void setup() {
+ insertProjectMeasure(1L);
+ insertProjectMeasure(2L);
+ insertProjectMeasure(3L);
+ }
+
+ @Test
+ public void add_uuid_column_to_project_measures() throws SQLException {
+ underTest.execute();
+
+ db.assertColumnDefinition("project_measures", "uuid", Types.VARCHAR, 40, true);
+
+ assertThat(db.countSql("select count(id) from project_measures"))
+ .isEqualTo(3);
+ }
+
+ private void insertProjectMeasure(Long id) {
+ db.executeInsert("project_measures",
+ "id", id,
+ "metric_id", id + 100,
+ "analysis_uuid", uuidFactory.create(),
+ "component_uuid", uuidFactory.create());
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.v83.projectmeasures;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.MigrationStep;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class DropIdColumnOfProjectMeasuresTableTest {
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(DropIdColumnOfProjectMeasuresTableTest.class, "schema.sql");
+
+ private MigrationStep underTest = new DropIdColumnOfProjectMeasuresTable(db.database());
+
+ @Test
+ public void execute() throws SQLException {
+ underTest.execute();
+
+ db.assertColumnDoesNotExist("project_measures", "id");
+ }
+
+ @Test
+ public void migration_is_not_re_entrant() throws SQLException {
+ underTest.execute();
+
+ assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.v83.projectmeasures;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.MigrationStep;
+import org.sonar.server.platform.db.migration.version.v83.util.DropPrimaryKeySqlGenerator;
+import org.sonar.server.platform.db.migration.version.v83.util.GetConstraintHelper;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class DropPrimaryKeyOnIdColumnOfProjectMeasuresTableTest {
+
+ private static final String TABLE_NAME = "project_measures";
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(DropPrimaryKeyOnIdColumnOfProjectMeasuresTableTest.class, "schema.sql");
+
+ private DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator = new DropPrimaryKeySqlGenerator(db.database(), new GetConstraintHelper(db.database()));
+
+ private MigrationStep underTest = new DropPrimaryKeyOnIdColumnOfProjectMeasuresTable(db.database(), dropPrimaryKeySqlGenerator);
+
+ @Test
+ public void execute() throws SQLException {
+ underTest.execute();
+
+ db.assertNoPrimaryKey(TABLE_NAME);
+ }
+
+ @Test
+ public void migration_is_not_re_entrant() throws SQLException {
+ underTest.execute();
+
+ assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.v83.projectmeasures;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.MigrationStep;
+
+import static java.sql.Types.VARCHAR;
+
+public class MakeProjectMeasuresUuidColumnNotNullableTest {
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(MakeProjectMeasuresUuidColumnNotNullableTest.class, "schema.sql");
+
+ private MigrationStep underTest = new MakeProjectMeasuresUuidColumnNotNullable(db.database());
+
+ @Test
+ public void uuid_column_is_not_null() throws SQLException {
+ underTest.execute();
+
+ db.assertColumnDefinition("project_measures", "uuid", VARCHAR, null, false);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.v83.projectmeasures;
+
+import java.sql.SQLException;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DataChange;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PopulateProjectMeasuresUuidTest {
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(PopulateProjectMeasuresUuidTest.class, "schema.sql");
+
+ private UuidFactory uuidFactory = UuidFactoryFast.getInstance();
+ private DataChange underTest = new PopulateProjectMeasureUuid(db.database(), uuidFactory);
+
+ @Test
+ public void populate_uuids() throws SQLException {
+ insertProjectMeasure(1L);
+ insertProjectMeasure(2L);
+ insertProjectMeasure(3L);
+
+ underTest.execute();
+
+ verifyUuidsAreNotNull();
+ }
+
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ insertProjectMeasure(1L);
+ insertProjectMeasure(2L);
+ insertProjectMeasure(3L);
+
+ underTest.execute();
+ // re-entrant
+ underTest.execute();
+
+ verifyUuidsAreNotNull();
+ }
+
+ private void verifyUuidsAreNotNull() {
+ assertThat(db.select("select uuid from project_measures")
+ .stream()
+ .map(row -> row.get("UUID"))
+ .filter(Objects::isNull)
+ .collect(Collectors.toList())).isEmpty();
+ }
+
+ private void insertProjectMeasure(Long id) {
+ db.executeInsert("project_measures",
+ "id", id,
+ "metric_id", id + 100,
+ "analysis_uuid", uuidFactory.create(),
+ "component_uuid", uuidFactory.create());
+ }
+
+}
--- /dev/null
+CREATE TABLE "PROJECT_MEASURES"(
+ "ID" BIGINT NOT NULL AUTO_INCREMENT (1,1),
+ "UUID" VARCHAR(40) NOT NULL,
+ "VALUE" DOUBLE,
+ "METRIC_ID" INTEGER NOT NULL,
+ "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "PERSON_ID" INTEGER,
+ "VARIATION_VALUE_1" DOUBLE,
+ "VARIATION_VALUE_2" DOUBLE,
+ "VARIATION_VALUE_3" DOUBLE,
+ "VARIATION_VALUE_4" DOUBLE,
+ "VARIATION_VALUE_5" DOUBLE,
+ "MEASURE_DATA" BLOB
+);
+CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES"("ANALYSIS_UUID", "METRIC_ID");
+CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES"("COMPONENT_UUID");
--- /dev/null
+CREATE TABLE "PROJECT_MEASURES"(
+ "ID" BIGINT NOT NULL AUTO_INCREMENT (1,1),
+ "VALUE" DOUBLE,
+ "METRIC_ID" INTEGER NOT NULL,
+ "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "PERSON_ID" INTEGER,
+ "VARIATION_VALUE_1" DOUBLE,
+ "VARIATION_VALUE_2" DOUBLE,
+ "VARIATION_VALUE_3" DOUBLE,
+ "VARIATION_VALUE_4" DOUBLE,
+ "VARIATION_VALUE_5" DOUBLE,
+ "MEASURE_DATA" BLOB
+);
+ALTER TABLE "PROJECT_MEASURES" ADD CONSTRAINT "PK_PROJECT_MEASURES" PRIMARY KEY("ID");
+CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES"("ANALYSIS_UUID", "METRIC_ID");
+CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES"("COMPONENT_UUID");
--- /dev/null
+CREATE TABLE "PROJECT_MEASURES"(
+ "ID" BIGINT NOT NULL AUTO_INCREMENT (1,1),
+ "UUID" VARCHAR(40) NOT NULL,
+ "VALUE" DOUBLE,
+ "METRIC_ID" INTEGER NOT NULL,
+ "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "PERSON_ID" INTEGER,
+ "VARIATION_VALUE_1" DOUBLE,
+ "VARIATION_VALUE_2" DOUBLE,
+ "VARIATION_VALUE_3" DOUBLE,
+ "VARIATION_VALUE_4" DOUBLE,
+ "VARIATION_VALUE_5" DOUBLE,
+ "MEASURE_DATA" BLOB
+);
+ALTER TABLE "PROJECT_MEASURES" ADD CONSTRAINT "PK_PROJECT_MEASURES" PRIMARY KEY("UUID");
+CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES"("ANALYSIS_UUID", "METRIC_ID");
+CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES"("COMPONENT_UUID");
--- /dev/null
+CREATE TABLE "PROJECT_MEASURES"(
+ "ID" BIGINT NOT NULL AUTO_INCREMENT (1,1),
+ "UUID" VARCHAR(40) NOT NULL,
+ "VALUE" DOUBLE,
+ "METRIC_ID" INTEGER NOT NULL,
+ "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "PERSON_ID" INTEGER,
+ "VARIATION_VALUE_1" DOUBLE,
+ "VARIATION_VALUE_2" DOUBLE,
+ "VARIATION_VALUE_3" DOUBLE,
+ "VARIATION_VALUE_4" DOUBLE,
+ "VARIATION_VALUE_5" DOUBLE,
+ "MEASURE_DATA" BLOB
+);
+ALTER TABLE "PROJECT_MEASURES" ADD CONSTRAINT "PK_PROJECT_MEASURES" PRIMARY KEY("ID");
+CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES"("ANALYSIS_UUID", "METRIC_ID");
+CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES"("COMPONENT_UUID");
--- /dev/null
+CREATE TABLE "PROJECT_MEASURES"(
+ "ID" BIGINT NOT NULL AUTO_INCREMENT (1,1),
+ "UUID" VARCHAR(40),
+ "VALUE" DOUBLE,
+ "METRIC_ID" INTEGER NOT NULL,
+ "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "PERSON_ID" INTEGER,
+ "VARIATION_VALUE_1" DOUBLE,
+ "VARIATION_VALUE_2" DOUBLE,
+ "VARIATION_VALUE_3" DOUBLE,
+ "VARIATION_VALUE_4" DOUBLE,
+ "VARIATION_VALUE_5" DOUBLE,
+ "MEASURE_DATA" BLOB
+);
+ALTER TABLE "PROJECT_MEASURES" ADD CONSTRAINT "PK_PROJECT_MEASURES" PRIMARY KEY("ID");
+CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES"("ANALYSIS_UUID", "METRIC_ID");
+CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES"("COMPONENT_UUID");
--- /dev/null
+CREATE TABLE "PROJECT_MEASURES"(
+ "ID" BIGINT NOT NULL AUTO_INCREMENT (1,1),
+ "UUID" VARCHAR(40),
+ "VALUE" DOUBLE,
+ "METRIC_ID" INTEGER NOT NULL,
+ "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "PERSON_ID" INTEGER,
+ "VARIATION_VALUE_1" DOUBLE,
+ "VARIATION_VALUE_2" DOUBLE,
+ "VARIATION_VALUE_3" DOUBLE,
+ "VARIATION_VALUE_4" DOUBLE,
+ "VARIATION_VALUE_5" DOUBLE,
+ "MEASURE_DATA" BLOB
+);
+ALTER TABLE "PROJECT_MEASURES" ADD CONSTRAINT "PK_PROJECT_MEASURES" PRIMARY KEY("ID");
+CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES"("ANALYSIS_UUID", "METRIC_ID");
+CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES"("COMPONENT_UUID");