aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-server
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2017-02-15 18:18:27 +0100
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>2017-02-17 13:31:49 +0100
commit9824b94f16109305b4847a611379029695823427 (patch)
tree85b339103ce4c56df78e3e26f21117da7fb04976 /server/sonar-server
parent0d3be9943570cf5bfb7fbb72fdfe5a6fcb2798c0 (diff)
downloadsonarqube-9824b94f16109305b4847a611379029695823427.tar.gz
sonarqube-9824b94f16109305b4847a611379029695823427.zip
split sonar-db into server/sonar-db-core and server/sonar-db-dao
Diffstat (limited to 'server/sonar-server')
-rw-r--r--server/sonar-server/pom.xml17
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryFactory.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/db/migration/AutoDbMigration.java110
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/db/migration/AutoDbMigrationTest.java145
4 files changed, 260 insertions, 16 deletions
diff --git a/server/sonar-server/pom.xml b/server/sonar-server/pom.xml
index ce99f0d7e93..69f66f0a1c7 100644
--- a/server/sonar-server/pom.xml
+++ b/server/sonar-server/pom.xml
@@ -61,7 +61,7 @@
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>sonar-db</artifactId>
+ <artifactId>sonar-db-dao</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
@@ -188,19 +188,8 @@
<!-- unit tests -->
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>sonar-db</artifactId>
- <version>${project.version}</version>
- <type>test-jar</type>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>sonar-testing-harness</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.dbunit</groupId>
- <artifactId>dbunit</artifactId>
+ <artifactId>sonar-db-testing</artifactId>
+ <type>pom</type>
<scope>test</scope>
</dependency>
<dependency>
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryFactory.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryFactory.java
index 0be862b3473..5431c1148c9 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryFactory.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryFactory.java
@@ -31,12 +31,12 @@ import javax.annotation.Nullable;
import org.sonar.api.measures.Metric.Level;
import org.sonar.core.util.stream.Collectors;
import org.sonar.server.measure.index.ProjectMeasuresQuery;
-import org.sonar.server.measure.index.ProjectMeasuresQuery.MetricCriterion;
-import org.sonar.server.measure.index.ProjectMeasuresQuery.Operator;
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Locale.ENGLISH;
import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
+import static org.sonar.server.measure.index.ProjectMeasuresQuery.MetricCriterion;
+import static org.sonar.server.measure.index.ProjectMeasuresQuery.Operator;
class ProjectMeasuresQueryFactory {
private static final Splitter CRITERIA_SPLITTER = Splitter.on(Pattern.compile("and", Pattern.CASE_INSENSITIVE));
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/db/migration/AutoDbMigration.java b/server/sonar-server/src/main/java/org/sonar/server/platform/db/migration/AutoDbMigration.java
new file mode 100644
index 00000000000..40f297bfeea
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/db/migration/AutoDbMigration.java
@@ -0,0 +1,110 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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;
+
+import com.google.common.annotations.VisibleForTesting;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import org.apache.commons.dbutils.DbUtils;
+import org.apache.ibatis.session.SqlSession;
+import org.picocontainer.Startable;
+import org.sonar.api.platform.ServerUpgradeStatus;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.db.DbClient;
+import org.sonar.db.DdlUtils;
+import org.sonar.db.dialect.Dialect;
+import org.sonar.db.dialect.H2;
+import org.sonar.server.platform.db.migration.engine.MigrationEngine;
+
+/**
+ * FIXME fix this class to remove use of DdlUtils.createSchema
+ */
+public class AutoDbMigration implements Startable {
+ private final ServerUpgradeStatus serverUpgradeStatus;
+ private final DbClient dbClient;
+ private final MigrationEngine migrationEngine;
+
+ public AutoDbMigration(ServerUpgradeStatus serverUpgradeStatus, DbClient dbClient, MigrationEngine migrationEngine) {
+ this.serverUpgradeStatus = serverUpgradeStatus;
+ this.dbClient = dbClient;
+ this.migrationEngine = migrationEngine;
+ }
+
+ @Override
+ public void start() {
+ if (!serverUpgradeStatus.isFreshInstall()) {
+ return;
+ }
+
+ Loggers.get(getClass()).info("Automatically perform DB migration on fresh install");
+ Dialect dialect = dbClient.getDatabase().getDialect();
+ if (H2.ID.equals(dialect.getId())) {
+ installH2();
+ } else {
+ migrationEngine.execute();
+ }
+ }
+
+ @VisibleForTesting
+ void installH2() {
+ Connection connection = null;
+ try (SqlSession session = dbClient.openSession(false)) {
+ connection = session.getConnection();
+ createH2Schema(connection, dbClient.getDatabase().getDialect().getId());
+ } finally {
+ DbUtils.closeQuietly(connection);
+ }
+ }
+
+ @VisibleForTesting
+ protected void createH2Schema(Connection connection, String dialectId) {
+ DdlUtils.createSchema(connection, dialectId, false);
+ hackFixForProjectMeasureTreeQueries(connection);
+ }
+
+ /**
+ * see SONAR-8586
+ */
+ private static void hackFixForProjectMeasureTreeQueries(Connection connection) {
+ int metricId = 1;
+ try (PreparedStatement preparedStatement = connection.prepareStatement("insert into PROJECT_MEASURES (METRIC_ID,COMPONENT_UUID,ANALYSIS_UUID) values (?,?,?);")) {
+ for (int i = 1; i < 1000; i++) {
+ preparedStatement.setInt(1, metricId);
+ preparedStatement.setString(2, "foo_" + i);
+ preparedStatement.setString(3, "bar_" + i);
+ preparedStatement.addBatch();
+ if (i % 250 == 0) {
+ preparedStatement.executeBatch();
+ connection.commit();
+ }
+ }
+ preparedStatement.executeBatch();
+ connection.commit();
+ } catch (SQLException e) {
+ throw new RuntimeException("Failed to insert fake rows into table PROJECT_MEASURES", e);
+ }
+ }
+
+ @Override
+ public void stop() {
+ // nothing to do
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/db/migration/AutoDbMigrationTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/db/migration/AutoDbMigrationTest.java
new file mode 100644
index 00000000000..b8e24b0cf32
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/db/migration/AutoDbMigrationTest.java
@@ -0,0 +1,145 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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;
+
+import java.sql.Connection;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mockito;
+import org.sonar.api.platform.ServerUpgradeStatus;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.dialect.Dialect;
+import org.sonar.db.dialect.H2;
+import org.sonar.db.dialect.MsSql;
+import org.sonar.db.dialect.MySql;
+import org.sonar.db.dialect.Oracle;
+import org.sonar.db.dialect.PostgreSql;
+import org.sonar.server.platform.db.migration.engine.MigrationEngine;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+public class AutoDbMigrationTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+ @Rule
+ public LogTester logTester = new LogTester();
+
+ private DbClient dbClient = mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS);
+ private ServerUpgradeStatus serverUpgradeStatus = mock(ServerUpgradeStatus.class);
+ private MigrationEngine migrationEngine = mock(MigrationEngine.class);
+ private AutoDbMigration underTest = new AutoDbMigration(serverUpgradeStatus, dbClient, migrationEngine);
+
+ private AutoDbMigration noRealH2Creation = spy(new AutoDbMigration(serverUpgradeStatus, dbClient, migrationEngine) {
+ @Override
+ protected void createH2Schema(Connection connection, String dialectId) {
+ // do nothing
+ }
+ });
+
+ @Test
+ public void start_creates_schema_on_h2_if_fresh_install() {
+ mockDialect(new H2());
+ mockDbClientOpenSession();
+ mockFreshInstall(true);
+
+ noRealH2Creation.start();
+
+ verify(noRealH2Creation).installH2();
+ verifyInfoLog();
+ }
+
+ @Test
+ public void start_runs_MigrationEngine_on_mysql_if_fresh_install() {
+ start_runs_MigrationEngine_for_dialect_if_fresh_install(new MySql());
+ }
+
+ @Test
+ public void start_runs_MigrationEngine_on_postgre_if_fresh_install() {
+ start_runs_MigrationEngine_for_dialect_if_fresh_install(new PostgreSql());
+ }
+
+ @Test
+ public void start_runs_MigrationEngine_on_Oracle_if_fresh_install() {
+ start_runs_MigrationEngine_for_dialect_if_fresh_install(new Oracle());
+ }
+
+ @Test
+ public void start_runs_MigrationEngine_on_MsSQL_if_fresh_install() {
+ start_runs_MigrationEngine_for_dialect_if_fresh_install(new MsSql());
+ }
+
+ private void start_runs_MigrationEngine_for_dialect_if_fresh_install(Dialect dialect) {
+ mockDialect(dialect);
+ mockFreshInstall(true);
+
+ underTest.start();
+
+ verify(migrationEngine).execute();
+ verifyInfoLog();
+ }
+
+ @Test
+ public void start_does_nothing_if_not_fresh_install() {
+ mockFreshInstall(false);
+
+ noRealH2Creation.start();
+
+ verify(noRealH2Creation).start();
+ verifyNoMoreInteractions(noRealH2Creation);
+ verifyZeroInteractions(migrationEngine);
+ assertThat(logTester.logs()).isEmpty();
+ }
+
+ @Test
+ public void stop_has_no_effect() {
+ underTest.stop();
+ }
+
+ private void mockFreshInstall(boolean value) {
+ when(serverUpgradeStatus.isFreshInstall()).thenReturn(value);
+ }
+
+ private void mockDialect(Dialect dialect) {
+ when(dbClient.getDatabase().getDialect()).thenReturn(dialect);
+ }
+
+ private void mockDbClientOpenSession() {
+ Connection connection = mock(Connection.class);
+ DbSession session = mock(DbSession.class);
+ when(session.getConnection()).thenReturn(connection);
+ when(dbClient.openSession(false)).thenReturn(session);
+ }
+
+ private void verifyInfoLog() {
+ assertThat(logTester.logs()).hasSize(1);
+ assertThat(logTester.logs(LoggerLevel.INFO)).containsExactly("Automatically perform DB migration on fresh install");
+ }
+
+}