import org.sonar.server.platform.db.migration.version.v75.DbVersion75;
import org.sonar.server.platform.db.migration.version.v76.DbVersion76;
import org.sonar.server.platform.db.migration.version.v77.DbVersion77;
+import org.sonar.server.platform.db.migration.version.v78.DbVersion78;
public class MigrationConfigurationModule extends Module {
@Override
DbVersion75.class,
DbVersion76.class,
DbVersion77.class,
+ DbVersion78.class,
// migration steps
MigrationStepRegistryImpl.class,
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.v78;
+
+import org.sonar.server.platform.db.migration.step.MigrationStepRegistry;
+import org.sonar.server.platform.db.migration.version.DbVersion;
+
+public class DbVersion78 implements DbVersion {
+
+ @Override
+ public void addSteps(MigrationStepRegistry registry) {
+ registry
+ .add(2700, "Drop overall subscriptions on notifications about new and resolved issues", DeleteOverallSubscriptionsOnNewAndResolvedIssuesNotifications.class);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.v78;
+
+import java.sql.SQLException;
+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;
+
+@SupportsBlueGreen
+public class DeleteOverallSubscriptionsOnNewAndResolvedIssuesNotifications extends DataChange {
+
+ public DeleteOverallSubscriptionsOnNewAndResolvedIssuesNotifications(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ MassUpdate massUpdate = context.prepareMassUpdate().rowPluralName("subscriptions");
+ massUpdate.select("select id from properties " +
+ "where resource_id is null " +
+ "and (prop_key like 'notification.NewFalsePositiveIssue.%' or prop_key like 'notification.NewIssues.%')");
+ massUpdate.update("delete from properties where id=?");
+ massUpdate.execute((row, update) -> {
+ long id = row.getLong(1);
+ update.setLong(1, id);
+ return true;
+ });
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.server.platform.db.migration.version.v78;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
assertThat(container.getPicoContainer().getComponentAdapters())
.hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER
// DbVersion classes
- + 18
+ + 19
// Others
+ 3);
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.v78;
+
+import org.junit.Test;
+import org.sonar.server.platform.db.migration.version.DbVersion;
+
+import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationCount;
+import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber;
+
+public class DbVersion78Test {
+ private DbVersion underTest = new DbVersion78();
+
+ @Test
+ public void migrationNumber_starts_at_2700() {
+ verifyMinimumMigrationNumber(underTest, 2700);
+ }
+
+ @Test
+ public void verify_migration_count() {
+ verifyMigrationCount(underTest, 1);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.v78;
+
+import java.sql.SQLException;
+import javax.annotation.Nullable;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DataChange;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.commons.lang.math.RandomUtils.nextInt;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DeleteOverallSubscriptionsOnNewAndResolvedIssuesNotificationsTest {
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(DeleteOverallSubscriptionsOnNewAndResolvedIssuesNotificationsTest.class, "schema.sql");
+
+ private DataChange underTest = new DeleteOverallSubscriptionsOnNewAndResolvedIssuesNotifications(db.database());
+
+ @Test
+ public void delete_overall_subscriptions() throws SQLException {
+ // properties that do not relate to subscriptions
+ insertProperty(1, "foo", null);
+ insertProperty(2, "bar", nextInt());
+
+ // global subscriptions to be deleted
+ insertProperty(3, "notification.NewFalsePositiveIssue.EmailNotificationChannel", null);
+ insertProperty(4, "notification.NewFalsePositiveIssue.OtherChannel", null);
+ insertProperty(5, "notification.NewIssues.EmailNotificationChannel", null);
+ insertProperty(6, "notification.NewIssues.OtherChannel", null);
+
+ // global subscriptions on other notifications, to be kept
+ insertProperty(7, "notification.ChangesOnMyIssue.EmailNotificationChannel", null);
+ insertProperty(8, "notification.NewAlerts.EmailNotificationChannel", null);
+ insertProperty(9, "notification.CeReportTaskFailure.EmailNotificationChannel", null);
+ insertProperty(10, "notification.SQ-MyNewIssues.EmailNotificationChannel", null);
+
+ // project subscriptions, to be kept
+ insertProperty(11, "notification.NewFalsePositiveIssue.EmailNotificationChannel", nextInt());
+ insertProperty(12, "notification.NewIssues.EmailNotificationChannel", nextInt());
+ insertProperty(13, "notification.ChangesOnMyIssue.EmailNotificationChannel", nextInt());
+ insertProperty(14, "notification.NewAlerts.EmailNotificationChannel", nextInt());
+ insertProperty(15, "notification.CeReportTaskFailure.EmailNotificationChannel", nextInt());
+ insertProperty(16, "notification.SQ-MyNewIssues.EmailNotificationChannel", nextInt());
+
+ underTest.execute();
+
+ assertProperties(1, 2, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+ }
+
+ private void assertProperties(Integer... expectedIds) {
+ assertThat(db.select("SELECT id FROM properties")
+ .stream()
+ .map(map -> ((Long) map.get("ID")).intValue())
+ .collect(toList()))
+ .containsExactlyInAnyOrder(expectedIds);
+ }
+
+ private void insertProperty(int id, String key, @Nullable Integer componentId) {
+ db.executeInsert(
+ "PROPERTIES",
+ "ID", id,
+ "PROP_KEY", key,
+ "USER_ID", nextInt(),
+ "RESOURCE_ID", componentId,
+ "IS_EMPTY", true,
+ "CREATED_AT", 123456);
+ }
+}
--- /dev/null
+CREATE TABLE "PROPERTIES" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "PROP_KEY" VARCHAR(512) NOT NULL,
+ "RESOURCE_ID" INTEGER,
+ "USER_ID" INTEGER,
+ "IS_EMPTY" BOOLEAN NOT NULL,
+ "TEXT_VALUE" VARCHAR(4000),
+ "CLOB_VALUE" CLOB,
+ "CREATED_AT" BIGINT
+);
+CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY");