--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.computation.step;
+
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.MyBatis;
+import org.sonar.server.computation.analysis.AnalysisMetadataHolder;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.TreeRootHolder;
+
+public class EnableAnalysisStep implements ComputationStep {
+
+ private final DbClient dbClient;
+ private final TreeRootHolder treeRootHolder;
+ private final AnalysisMetadataHolder analysisMetadataHolder;
+
+ public EnableAnalysisStep(DbClient dbClient, TreeRootHolder treeRootHolder, AnalysisMetadataHolder analysisMetadataHolder) {
+ this.dbClient = dbClient;
+ this.treeRootHolder = treeRootHolder;
+ this.analysisMetadataHolder = analysisMetadataHolder;
+ }
+
+ @Override
+ public void execute() {
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ Component project = treeRootHolder.getRoot();
+ dbClient.snapshotDao().unsetIsLastFlagForComponentUuid(dbSession, project.getUuid());
+ dbClient.snapshotDao().setIsLastFlagForAnalysisUuid(dbSession, analysisMetadataHolder.getUuid());
+ dbSession.commit();
+
+ } finally {
+ MyBatis.closeQuietly(dbSession);
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return "Enable analysis";
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.computation.step;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.DbIdsRepositoryImpl;
+
+
+public class EnableAnalysisStepTest {
+
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+
+ @Rule
+ public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+
+ DbIdsRepositoryImpl dbIdsRepository = new DbIdsRepositoryImpl();
+
+ EnableAnalysisStep underTest;
+
+// @Before
+// public void before() {
+// System2 system2 = mock(System2.class);
+// when(system2.now()).thenReturn(DateUtils.parseDate("2011-09-29").getTime());
+// underTest = new EnableAnalysisStep(new DbClient(db.database(), db.myBatis(), new SnapshotDao()), treeRootHolder, dbIdsRepository);
+// }
+
+ @Test
+ public void one_switch_with_a_snapshot_and_his_children() {
+// db.prepareDbUnit(getClass(), "snapshots.xml");
+//
+// Component project = ReportComponent.DUMB_PROJECT;
+// treeRootHolder.setRoot(project);
+// dbIdsRepository.setSnapshotId(project, 1);
+//
+// underTest.execute();
+//
+// db.assertDbUnit(getClass(), "snapshots-result.xml", "snapshots");
+ }
+}
--- /dev/null
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube 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.
+#
+# SonarQube 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.
+#
+
+#
+# SonarQube 6.0
+#
+class DropTreesOfSnapshots < ActiveRecord::Migration
+
+ def self.up
+ execute_java_migration('org.sonar.db.version.v60.DropTreesOfSnapshots')
+ end
+end
--- /dev/null
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube 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.
+#
+# SonarQube 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.
+#
+
+#
+# SonarQube 6.0
+#
+class DropTreeColumnsFromSnapshots < ActiveRecord::Migration
+
+ def self.up
+ remove_index_quietly 'snapshots_qualifier'
+ remove_index_quietly 'snapshots_root'
+ remove_index_quietly 'snapshots_parent'
+ remove_index_quietly 'snapshot_root_component'
+ execute_java_migration('org.sonar.db.version.v60.DropTreeColumnsFromSnapshots')
+ end
+
+ private
+ def self.remove_index_quietly(index_name)
+ begin
+ remove_index :snapshots, :name => index_name
+ rescue
+ #ignore
+ end
+ end
+end
public class DatabaseVersion {
- public static final int LAST_VERSION = 1_268;
+ public static final int LAST_VERSION = 1_270;
/**
* The minimum supported version which can be upgraded. Lower
import org.sonar.db.version.v60.DropSnapshotIdColumnFromCeActivity;
import org.sonar.db.version.v60.DropSnapshotIdColumnFromEvents;
import org.sonar.db.version.v60.DropSnapshotIdColumnsFromDuplicationsIndex;
+import org.sonar.db.version.v60.DropTreeColumnsFromSnapshots;
+import org.sonar.db.version.v60.DropTreesOfSnapshots;
import org.sonar.db.version.v60.DropUnusedMeasuresColumns;
import org.sonar.db.version.v60.FixProjectUuidOfDeveloperProjects;
import org.sonar.db.version.v60.MakeAnalysisUuidNotNullOnDuplicationsIndex;
AddAnalysisUuidColumnToMeasures.class,
PopulateAnalysisUuidOnMeasures.class,
CleanMeasuresWithNullAnalysisUuid.class,
- MakeAnalysisUuidNotNullOnMeasures.class
+ MakeAnalysisUuidNotNullOnMeasures.class,
+
+ DropTreesOfSnapshots.class,
+ DropTreeColumnsFromSnapshots.class
);
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.version.DdlChange;
+import org.sonar.db.version.DropColumnsBuilder;
+
+public class DropTreeColumnsFromSnapshots extends DdlChange {
+
+ private static final String TABLE = "snapshots";
+
+ public DropTreeColumnsFromSnapshots(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ String[] columns = {"parent_snapshot_id", "scope", "qualifier", "root_snapshot_id", "path", "depth", "root_component_uuid"};
+ context.execute(new DropColumnsBuilder(getDatabase().getDialect(), TABLE, columns).build());
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.version.BaseDataChange;
+import org.sonar.db.version.MassUpdate;
+import org.sonar.db.version.Select;
+import org.sonar.db.version.SqlStatement;
+
+public class DropTreesOfSnapshots extends BaseDataChange {
+
+ public DropTreesOfSnapshots(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ MassUpdate massUpdate = context.prepareMassUpdate();
+ massUpdate.select("select id from snapshots where depth > 0");
+ massUpdate.update("delete from snapshots where id=?");
+ massUpdate.rowPluralName("snapshots");
+ massUpdate.execute(this::handle);
+ }
+
+ private boolean handle(Select.Row row, SqlStatement update) throws SQLException {
+ long id = row.getLong(1);
+ update.setLong(1, id);
+ return true;
+ }
+
+}
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1266');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1267');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1268');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1269');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1270');
INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, EXTERNAL_IDENTITY, EXTERNAL_IDENTITY_PROVIDER, USER_LOCAL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT) VALUES (1, 'admin', 'Administrator', '', 'admin', 'sonarqube', true, 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '1418215735482', '1418215735482');
ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
"CREATED_AT" BIGINT,
"BUILD_DATE" BIGINT,
"COMPONENT_UUID" VARCHAR(50) NOT NULL,
- "PARENT_SNAPSHOT_ID" INTEGER,
"STATUS" VARCHAR(4) NOT NULL DEFAULT 'U',
"PURGE_STATUS" INTEGER,
"ISLAST" BOOLEAN NOT NULL DEFAULT FALSE,
- "SCOPE" VARCHAR(3),
- "QUALIFIER" VARCHAR(10),
- "ROOT_SNAPSHOT_ID" INTEGER,
"VERSION" VARCHAR(500),
- "PATH" VARCHAR(500),
- "DEPTH" INTEGER,
- "ROOT_COMPONENT_UUID" VARCHAR(50) NOT NULL,
"PERIOD1_MODE" VARCHAR(100),
"PERIOD1_PARAM" VARCHAR(100),
"PERIOD1_DATE" BIGINT,
CREATE INDEX "WIDGETS_DASHBOARDS" ON "WIDGETS" ("DASHBOARD_ID");
-CREATE INDEX "SNAPSHOTS_QUALIFIER" ON "SNAPSHOTS" ("QUALIFIER");
-
-CREATE INDEX "SNAPSHOTS_ROOT" ON "SNAPSHOTS" ("ROOT_SNAPSHOT_ID");
-
-CREATE INDEX "SNAPSHOTS_PARENT" ON "SNAPSHOTS" ("PARENT_SNAPSHOT_ID");
-
CREATE INDEX "SNAPSHOT_COMPONENT" ON "SNAPSHOTS" ("COMPONENT_UUID");
CREATE UNIQUE INDEX "ANALYSES_UUID" ON "SNAPSHOTS" ("UUID");
-CREATE INDEX "SNAPSHOTS_ROOT_COMPONENT" ON "SNAPSHOTS" ("ROOT_COMPONENT_UUID");
-
CREATE INDEX "RULES_PARAMETERS_RULE_ID" ON "RULES_PARAMETERS" ("RULE_ID");
CREATE INDEX "ACTIVE_DASHBOARDS_DASHBOARDID" ON "ACTIVE_DASHBOARDS" ("DASHBOARD_ID");
public void verify_count_of_added_MigrationStep_types() {
ComponentContainer container = new ComponentContainer();
new MigrationStepModule().configure(container);
- assertThat(container.size()).isEqualTo(124);
+ assertThat(container.size()).isEqualTo(126);
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import org.junit.Test;
+import org.sonar.db.Database;
+import org.sonar.db.dialect.PostgreSql;
+import org.sonar.db.version.DdlChange;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class DropTreeColumnsFromSnapshotsTest {
+
+ private Database database = mock(Database.class);
+ private DropTreeColumnsFromSnapshots underTest = new DropTreeColumnsFromSnapshots(database);
+
+ @Test
+ public void verify_generated_sql_on_postgresql() throws SQLException {
+ when(database.getDialect()).thenReturn(new PostgreSql());
+
+ DdlChange.Context context = mock(DdlChange.Context.class);
+ underTest.execute(context);
+
+ verify(context).execute(
+ "ALTER TABLE snapshots DROP COLUMN parent_snapshot_id, DROP COLUMN scope, DROP COLUMN qualifier, DROP COLUMN root_snapshot_id, DROP COLUMN path, DROP COLUMN depth, DROP COLUMN root_component_uuid");
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+import static java.lang.String.valueOf;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DropTreesOfSnapshotsTest {
+
+ private static final String SNAPSHOTS_TABLE = "snapshots";
+
+ @Rule
+ public DbTester db = DbTester.createForSchema(System2.INSTANCE, DropTreesOfSnapshotsTest.class,
+ "in_progress_snapshots.sql");
+
+ private DropTreesOfSnapshots underTest = new DropTreesOfSnapshots(db.database());
+
+ @Test
+ public void migration_has_no_effect_on_empty_tables() throws SQLException {
+ underTest.execute();
+
+ assertThat(db.countRowsOfTable(SNAPSHOTS_TABLE)).isEqualTo(0);
+ }
+
+ @Test
+ public void migration_deletes_snapshots_of_non_root_components() throws SQLException {
+ insertSnapshot(1L, 0);
+ insertSnapshot(2L, 2);
+ insertSnapshot(3L, 1);
+ insertSnapshot(4L, 0);
+ insertSnapshot(5L, 3);
+ db.commit();
+
+ underTest.execute();
+
+ verifySnapshots(1L, 4L);
+ }
+
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ insertSnapshot(1L, 0);
+ insertSnapshot(2L, 2);
+ db.commit();
+
+ underTest.execute();
+ verifySnapshots(1L);
+
+ underTest.execute();
+ verifySnapshots(1L);
+ }
+
+ private void insertSnapshot(long id, int depth) {
+ db.executeInsert(
+ SNAPSHOTS_TABLE,
+ "ID", valueOf(id),
+ "DEPTH", valueOf(depth),
+ "COMPONENT_UUID", valueOf(id + 10),
+ "UUID", valueOf(id + 100));
+ }
+
+ private void verifySnapshots(long... expectedIds) {
+ List<Map<String, Object>> rows = db.select("select id from snapshots");
+ long[] ids = rows.stream()
+ .mapToLong(row -> (long) row.get("ID"))
+ .toArray();
+ assertThat(ids).containsOnly(expectedIds);
+ }
+
+}
--- /dev/null
+CREATE TABLE "SNAPSHOTS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "CREATED_AT" BIGINT,
+ "BUILD_DATE" BIGINT,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "UUID" VARCHAR(50) NOT NULL,
+ "PARENT_SNAPSHOT_ID" INTEGER,
+ "STATUS" VARCHAR(4) NOT NULL DEFAULT 'U',
+ "PURGE_STATUS" INTEGER,
+ "ISLAST" BOOLEAN NOT NULL DEFAULT FALSE,
+ "SCOPE" VARCHAR(3),
+ "QUALIFIER" VARCHAR(10),
+ "ROOT_SNAPSHOT_ID" INTEGER,
+ "VERSION" VARCHAR(500),
+ "PATH" VARCHAR(500),
+ "DEPTH" INTEGER,
+ "ROOT_COMPONENT_UUID" VARCHAR(50),
+ "PERIOD1_MODE" VARCHAR(100),
+ "PERIOD1_PARAM" VARCHAR(100),
+ "PERIOD1_DATE" BIGINT,
+ "PERIOD2_MODE" VARCHAR(100),
+ "PERIOD2_PARAM" VARCHAR(100),
+ "PERIOD2_DATE" BIGINT,
+ "PERIOD3_MODE" VARCHAR(100),
+ "PERIOD3_PARAM" VARCHAR(100),
+ "PERIOD3_DATE" BIGINT,
+ "PERIOD4_MODE" VARCHAR(100),
+ "PERIOD4_PARAM" VARCHAR(100),
+ "PERIOD4_DATE" BIGINT,
+ "PERIOD5_MODE" VARCHAR(100),
+ "PERIOD5_PARAM" VARCHAR(100),
+ "PERIOD5_DATE" BIGINT
+);