diff options
30 files changed, 56 insertions, 1062 deletions
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DbVersionModule.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DbVersionModule.java index 4fdb281ddbb..0de137980aa 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DbVersionModule.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DbVersionModule.java @@ -20,6 +20,7 @@ package org.sonar.server.platform.db.migration.version; import org.sonar.core.platform.Module; +import org.sonar.server.platform.db.migration.version.v56.DbVersion56; import org.sonar.server.platform.db.migration.version.v561.DbVersion561; import org.sonar.server.platform.db.migration.version.v60.DbVersion60; import org.sonar.server.platform.db.migration.version.v61.DbVersion61; @@ -30,6 +31,7 @@ public class DbVersionModule extends Module { @Override protected void configureModule() { add( + DbVersion56.class, DbVersion561.class, DbVersion60.class, DbVersion61.class, diff --git a/sonar-db/src/main/java/org/sonar/db/version/v56/CreateInitialSchema.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchema.java index 91007e90792..d037512bbf0 100644 --- a/sonar-db/src/main/java/org/sonar/db/version/v56/CreateInitialSchema.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchema.java @@ -17,7 +17,7 @@ * 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.v56; +package org.sonar.server.platform.db.migration.version.v56; import java.sql.SQLException; import org.sonar.db.Database; @@ -26,10 +26,10 @@ import org.sonar.db.version.BooleanColumnDef; import org.sonar.db.version.ColumnDef; import org.sonar.db.version.CreateIndexBuilder; import org.sonar.db.version.CreateTableBuilder; -import org.sonar.db.version.DdlChange; import org.sonar.db.version.IntegerColumnDef; import org.sonar.db.version.TinyIntColumnDef; import org.sonar.db.version.VarcharColumnDef; +import org.sonar.server.platform.db.migration.step.DdlChange; import static org.sonar.db.version.BigIntegerColumnDef.newBigIntegerColumnDefBuilder; import static org.sonar.db.version.BlobColumnDef.newBlobColumnDefBuilder; diff --git a/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/DbVersion56.java index 6e7ec450d6e..c8295486b0d 100644 --- a/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/DbVersion56.java @@ -17,18 +17,16 @@ * 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; +package org.sonar.server.platform.db.migration.version.v56; -import org.sonar.core.platform.Module; -import org.sonar.db.version.v56.CreateInitialSchema; -import org.sonar.db.version.v56.PopulateInitialSchema; +import org.sonar.server.platform.db.migration.step.MigrationStepRegistry; +import org.sonar.server.platform.db.migration.version.DbVersion; -public class MigrationStepModule extends Module { +public class DbVersion56 implements DbVersion { @Override - protected void configureModule() { - add( - // 5.6 - CreateInitialSchema.class, - PopulateInitialSchema.class); + public void addSteps(MigrationStepRegistry registry) { + registry + .add(1, "Create initial schema", CreateInitialSchema.class) + .add(2, "Populate initial schema", PopulateInitialSchema.class); } } diff --git a/sonar-db/src/main/java/org/sonar/db/version/v56/PopulateInitialSchema.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchema.java index 491db800cbb..ef48be58073 100644 --- a/sonar-db/src/main/java/org/sonar/db/version/v56/PopulateInitialSchema.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchema.java @@ -17,15 +17,15 @@ * 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.v56; +package org.sonar.server.platform.db.migration.version.v56; import java.sql.SQLException; import java.util.Date; import org.sonar.api.utils.System2; import org.sonar.db.Database; -import org.sonar.db.version.BaseDataChange; +import org.sonar.server.platform.db.migration.step.DataChange; -public class PopulateInitialSchema extends BaseDataChange { +public class PopulateInitialSchema extends DataChange { private static final String ADMINS_GROUP = "sonar-administrators"; private static final String USERS_GROUP = "sonar-users"; diff --git a/sonar-db/src/main/java/org/sonar/db/version/v56/package-info.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/package-info.java index c3a55a0eb13..832de3c3198 100644 --- a/sonar-db/src/main/java/org/sonar/db/version/v56/package-info.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/package-info.java @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @ParametersAreNonnullByDefault -package org.sonar.db.version.v56; +package org.sonar.server.platform.db.migration.version.v56; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DbVersionModuleTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DbVersionModuleTest.java index 6f9226ab604..8a2b5a42cc9 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DbVersionModuleTest.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DbVersionModuleTest.java @@ -36,7 +36,7 @@ public class DbVersionModuleTest { underTest.configure(container); assertThat(container.getPicoContainer().getComponentAdapters()) - .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 5); + .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 6); } } diff --git a/sonar-db/src/test/java/org/sonar/db/version/v56/CreateInitialSchemaTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchemaTest.java index d92d451c1e8..61a39f3dae5 100644 --- a/sonar-db/src/test/java/org/sonar/db/version/v56/CreateInitialSchemaTest.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchemaTest.java @@ -17,7 +17,7 @@ * 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.v56; +package org.sonar.server.platform.db.migration.version.v56; import java.sql.Connection; import java.sql.ResultSet; diff --git a/sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/DbVersion56Test.java index 60bf767ed9c..d62347556e6 100644 --- a/sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/DbVersion56Test.java @@ -17,18 +17,31 @@ * 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; +package org.sonar.server.platform.db.migration.version.v56; import org.junit.Test; -import org.sonar.core.platform.ComponentContainer; import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationCount; +import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber; + +public class DbVersion56Test { + private DbVersion56 underTest = new DbVersion56(); -public class MigrationStepModuleTest { @Test - public void verify_count_of_added_MigrationStep_types() { - ComponentContainer container = new ComponentContainer(); - new MigrationStepModule().configure(container); - assertThat(container.size()).isEqualTo(4); + public void verify_no_support_component() { + assertThat(underTest.getSupportComponents()).isEmpty(); } + + @Test + public void migrationNumber_starts_at_1153() { + verifyMinimumMigrationNumber(underTest, 1); + } + + @Test + public void verify_migration_count() { + verifyMigrationCount(underTest, 2); + } + + } diff --git a/sonar-db/src/test/java/org/sonar/db/version/v56/PopulateInitialSchemaTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchemaTest.java index 3f3699edcc8..5d167c53e49 100644 --- a/sonar-db/src/test/java/org/sonar/db/version/v56/PopulateInitialSchemaTest.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchemaTest.java @@ -17,7 +17,7 @@ * 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.v56; +package org.sonar.server.platform.db.migration.version.v56; import java.sql.SQLException; import java.util.List; diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v56/CreateInitialSchemaTest/empty.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchemaTest/empty.sql index e69de29bb2d..e69de29bb2d 100644 --- a/sonar-db/src/test/resources/org/sonar/db/version/v56/CreateInitialSchemaTest/empty.sql +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchemaTest/empty.sql diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v56/PopulateInitialSchemaTest/v56.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchemaTest/v56.sql index d0c61c969ac..d0c61c969ac 100644 --- a/sonar-db/src/test/resources/org/sonar/db/version/v56/PopulateInitialSchemaTest/v56.sql +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchemaTest/v56.sql diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/db/migrations/DatabaseMigrator.java b/server/sonar-server/src/main/java/org/sonar/server/platform/db/migrations/DatabaseMigrator.java index 1435468e39a..1746941c190 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/db/migrations/DatabaseMigrator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/db/migrations/DatabaseMigrator.java @@ -29,7 +29,6 @@ import org.sonar.api.server.ServerSide; import org.sonar.api.utils.log.Loggers; import org.sonar.db.DbClient; import org.sonar.db.DdlUtils; -import org.sonar.db.version.MigrationStep; import org.sonar.server.plugins.ServerPluginRepository; /** @@ -42,16 +41,13 @@ import org.sonar.server.plugins.ServerPluginRepository; public class DatabaseMigrator implements Startable { private final DbClient dbClient; - private final MigrationStep[] migrations; private final ServerUpgradeStatus serverUpgradeStatus; /** * ServerPluginRepository is used to ensure H2 schema creation is done only after copy of bundle plugins have been done */ - public DatabaseMigrator(DbClient dbClient, MigrationStep[] migrations, ServerUpgradeStatus serverUpgradeStatus, - ServerPluginRepository unused) { + public DatabaseMigrator(DbClient dbClient, ServerUpgradeStatus serverUpgradeStatus, ServerPluginRepository unused) { this.dbClient = dbClient; - this.migrations = migrations; this.serverUpgradeStatus = serverUpgradeStatus; } @@ -89,28 +85,6 @@ public class DatabaseMigrator implements Startable { return false; } - public void executeMigration(String className) { - MigrationStep migration = getMigration(className); - try { - migration.execute(); - - } catch (Exception e) { - // duplication between log and exception because webapp does not correctly log initial stacktrace - String msg = "Fail to execute database migration: " + className; - Loggers.get(getClass()).error(msg, e); - throw new IllegalStateException(msg, e); - } - } - - private MigrationStep getMigration(String className) { - for (MigrationStep migration : migrations) { - if (migration.getClass().getName().equals(className)) { - return migration; - } - } - throw new IllegalArgumentException("Database migration not found: " + className); - } - @VisibleForTesting protected void createSchema(Connection connection, String dialectId) { DdlUtils.createSchema(connection, dialectId, false); diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel2.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel2.java index 9e9f2e95479..65b92653ff3 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel2.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel2.java @@ -25,7 +25,6 @@ import org.sonar.core.i18n.RuleI18nManager; import org.sonar.core.platform.PluginClassloaderFactory; import org.sonar.core.platform.PluginLoader; import org.sonar.db.charset.DatabaseCharsetChecker; -import org.sonar.db.version.MigrationStepModule; import org.sonar.server.platform.DefaultServerUpgradeStatus; import org.sonar.server.platform.StartupMetadataProvider; import org.sonar.server.platform.db.CheckDatabaseCharsetAtStartup; @@ -75,9 +74,7 @@ public class PlatformLevel2 extends PlatformLevel { add(DatabaseMigrationStateImpl.class, DatabaseMigrationExecutorServiceImpl.class); // Ruby DB Migration - add( - DatabaseMigrator.class, - MigrationStepModule.class); + add(DatabaseMigrator.class); addIfStartupLeader( DatabaseCharsetChecker.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java index aa5f0f6f694..9aa211f5fbc 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java @@ -55,13 +55,12 @@ import org.sonar.server.authentication.IdentityProviderRepository; import org.sonar.server.component.ComponentCleanerService; import org.sonar.server.platform.PersistentSettings; import org.sonar.server.platform.Platform; -import org.sonar.server.platform.db.migrations.DatabaseMigrator; import org.sonar.server.platform.db.migration.DatabaseMigrationState; import org.sonar.server.platform.ws.UpgradesAction; import org.sonar.server.user.NewUserNotifier; import static com.google.common.collect.Lists.newArrayList; -import static org.sonar.server.platform.db.migration.DatabaseMigrationState.*; +import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status; public final class JRubyFacade { @@ -153,9 +152,8 @@ public final class JRubyFacade { return get(Database.class); } - // Only used by Java migration - public DatabaseMigrator databaseMigrator() { - return get(DatabaseMigrator.class); + public boolean isDbUptodate() { + return getContainer().getComponentByType(DatabaseVersion.class).getStatus() == DatabaseVersion.Status.UP_TO_DATE; } /* PROFILES CONSOLE : RULES AND METRIC THRESHOLDS */ diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/db/migrations/DatabaseMigratorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/db/migrations/DatabaseMigratorTest.java index 6fca4c37125..a3bac3ac496 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/db/migrations/DatabaseMigratorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/db/migrations/DatabaseMigratorTest.java @@ -31,7 +31,6 @@ import org.sonar.db.DbSession; import org.sonar.db.dialect.Dialect; import org.sonar.db.dialect.H2; import org.sonar.db.dialect.MySql; -import org.sonar.db.version.MigrationStep; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.anyBoolean; @@ -45,14 +44,13 @@ public class DatabaseMigratorTest { @Rule public ExpectedException thrown = ExpectedException.none(); - DbClient dbClient = mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS); - MigrationStep[] migrations = new MigrationStep[] {new FakeMigrationStep()}; - ServerUpgradeStatus serverUpgradeStatus = mock(ServerUpgradeStatus.class); - DatabaseMigrator migrator; + private DbClient dbClient = mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS); + private ServerUpgradeStatus serverUpgradeStatus = mock(ServerUpgradeStatus.class); + private DatabaseMigrator migrator; @Before public void setUp() { - migrator = new DatabaseMigrator(dbClient, migrations, serverUpgradeStatus, null); + migrator = new DatabaseMigrator(dbClient, serverUpgradeStatus, null); } @Test @@ -64,21 +62,6 @@ public class DatabaseMigratorTest { } @Test - public void fail_if_execute_unknown_migration() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("Database migration not found: org.xxx.UnknownMigration"); - - migrator.executeMigration("org.xxx.UnknownMigration"); - } - - @Test - public void execute_migration() { - assertThat(FakeMigrationStep.executed).isFalse(); - migrator.executeMigration(FakeMigrationStep.class.getName()); - assertThat(FakeMigrationStep.executed).isTrue(); - } - - @Test public void should_create_schema_on_h2() { Dialect supportedDialect = new H2(); when(dbClient.getDatabase().getDialect()).thenReturn(supportedDialect); @@ -88,7 +71,7 @@ public class DatabaseMigratorTest { when(dbClient.openSession(false)).thenReturn(session); when(serverUpgradeStatus.isFreshInstall()).thenReturn(true); - DatabaseMigrator databaseMigrator = new DatabaseMigrator(dbClient, migrations, serverUpgradeStatus, null) { + DatabaseMigrator databaseMigrator = new DatabaseMigrator(dbClient, serverUpgradeStatus, null) { @Override protected void createSchema(Connection connection, String dialectId) { } @@ -97,12 +80,4 @@ public class DatabaseMigratorTest { assertThat(databaseMigrator.createDatabase()).isTrue(); } - public static class FakeMigrationStep implements MigrationStep { - static boolean executed = false; - - @Override - public void execute() { - executed = true; - } - } } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/AddAnalysisUuidColumnToDuplicationsIndex.java b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/AddAnalysisUuidColumnToDuplicationsIndex.java index 04f86a0ed14..557449e68c2 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/AddAnalysisUuidColumnToDuplicationsIndex.java +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/AddAnalysisUuidColumnToDuplicationsIndex.java @@ -22,7 +22,6 @@ package org.sonar.db.version.v60; import java.sql.SQLException; import org.sonar.db.Database; import org.sonar.db.version.AddColumnsBuilder; -import org.sonar.db.version.DdlChange; import static org.sonar.db.version.VarcharColumnDef.UUID_VARCHAR_SIZE; import static org.sonar.db.version.VarcharColumnDef.newVarcharColumnDefBuilder; @@ -42,4 +41,4 @@ public class AddAnalysisUuidColumnToDuplicationsIndex extends DdlChange { .build()); } -}
\ No newline at end of file +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/AddComponentUuidColumnToDuplicationsIndex.java b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/AddComponentUuidColumnToDuplicationsIndex.java index a25cf2cc376..8612d57b378 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/AddComponentUuidColumnToDuplicationsIndex.java +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/AddComponentUuidColumnToDuplicationsIndex.java @@ -22,7 +22,6 @@ package org.sonar.db.version.v60; import java.sql.SQLException; import org.sonar.db.Database; import org.sonar.db.version.AddColumnsBuilder; -import org.sonar.db.version.DdlChange; import static org.sonar.db.version.VarcharColumnDef.UUID_VARCHAR_SIZE; import static org.sonar.db.version.VarcharColumnDef.newVarcharColumnDefBuilder; @@ -43,4 +42,4 @@ public class AddComponentUuidAndAnalysisUuidColumnToDuplicationsIndex extends Dd .build()); } -}
\ No newline at end of file +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/DeleteOrphanDuplicationsIndexRowsWithoutComponent.java b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/DeleteOrphanDuplicationsIndexRowsWithoutComponent.java index 763dd89a98a..0a05c5194b3 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/DeleteOrphanDuplicationsIndexRowsWithoutComponent.java +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/DeleteOrphanDuplicationsIndexRowsWithoutComponent.java @@ -21,7 +21,6 @@ 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; public class DeleteOrphanDuplicationsIndexRowsWithoutComponent extends BaseDataChange { @@ -42,4 +41,4 @@ public class DeleteOrphanDuplicationsIndexRowsWithoutComponent extends BaseDataC }); } -}
\ No newline at end of file +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/MakeComponentUuidNotNullOnDuplicationsIndex.java b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/MakeComponentUuidNotNullOnDuplicationsIndex.java index 6233d86fb40..8ced13cac4d 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/MakeComponentUuidNotNullOnDuplicationsIndex.java +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/MakeComponentUuidNotNullOnDuplicationsIndex.java @@ -22,7 +22,6 @@ package org.sonar.db.version.v60; import java.sql.SQLException; import org.sonar.db.Database; import org.sonar.db.version.AlterColumnsBuilder; -import org.sonar.db.version.DdlChange; import static org.sonar.db.version.VarcharColumnDef.UUID_VARCHAR_SIZE; import static org.sonar.db.version.VarcharColumnDef.newVarcharColumnDefBuilder; @@ -42,4 +41,4 @@ public class MakeComponentUuidNotNullOnDuplicationsIndex extends DdlChange { .build()); } -}
\ No newline at end of file +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v2/AddComponentUuidAndAnalysisUuidColumnToDuplicationsIndex.java b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v2/AddComponentUuidAndAnalysisUuidColumnToDuplicationsIndex.java index 8e9280fa5ec..8cc16f323a9 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v2/AddComponentUuidAndAnalysisUuidColumnToDuplicationsIndex.java +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v2/AddComponentUuidAndAnalysisUuidColumnToDuplicationsIndex.java @@ -22,7 +22,6 @@ package org.sonar.db.version.v60; import java.sql.SQLException; import org.sonar.db.Database; import org.sonar.db.version.AddColumnsBuilder; -import org.sonar.db.version.DdlChange; import static org.sonar.db.version.VarcharColumnDef.UUID_VARCHAR_SIZE; import static org.sonar.db.version.VarcharColumnDef.newVarcharColumnDefBuilder; @@ -42,4 +41,4 @@ public class AddComponentUuidColumnToDuplicationsIndex extends DdlChange { .build()); } -}
\ No newline at end of file +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v2/MakeComponentUuidAndAnalysisUuidNotNullOnDuplicationsIndex.java b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v2/MakeComponentUuidAndAnalysisUuidNotNullOnDuplicationsIndex.java index e365b126bfd..9e522216532 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v2/MakeComponentUuidAndAnalysisUuidNotNullOnDuplicationsIndex.java +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v2/MakeComponentUuidAndAnalysisUuidNotNullOnDuplicationsIndex.java @@ -22,7 +22,6 @@ package org.sonar.db.version.v60; import java.sql.SQLException; import org.sonar.db.Database; import org.sonar.db.version.AlterColumnsBuilder; -import org.sonar.db.version.DdlChange; import static org.sonar.db.version.VarcharColumnDef.UUID_VARCHAR_SIZE; import static org.sonar.db.version.VarcharColumnDef.newVarcharColumnDefBuilder; @@ -43,4 +42,4 @@ public class MakeComponentUuidAndAnalysisUuidNotNullOnDuplicationsIndex extends .build()); } -}
\ No newline at end of file +} diff --git a/server/sonar-web/src/main/webapp/WEB-INF/config/environment.rb b/server/sonar-web/src/main/webapp/WEB-INF/config/environment.rb index 3c375e4607b..00f28b34ec3 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/config/environment.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/config/environment.rb @@ -100,164 +100,9 @@ Rails::Initializer.run do |config| # Prevent appearance of ANSI style escape sequences in logs config.active_record.colorize_logging = false - # Use SQL instead of Active Record's schema dumper when creating the test database. - # This is necessary if your schema can't be completely dumped by the schema dumper, - # like if you have constraints or database-specific column types - # config.active_record.schema_format = :sql - - # Activate observers that should always be running - # Please note that observers generated using script/generate observer need to have an _observer suffix - # config.active_record.observers = :cacher, :garbage_collector, :forum_observer end -class ActiveRecord::Migration - def self.dialect - ActiveRecord::Base.configurations[ENV['RAILS_ENV']]['dialect'] - end - - def self.column_exists?(table_name, column_name) - columns(table_name).any?{ |c| c.name == column_name.to_s } - end - - def self.add_index(table_name, column_name, options = {}) - # ActiveRecord can generate index names longer than 30 characters, but that's - # not supported by Oracle, the "Enterprise" database. - # For this reason we force to set name of indexes. - raise ArgumentError, 'Missing index name' unless options[:name] - - unless index_exists?(table_name, column_name, :name => options[:name]) - super(table_name, column_name, options) - end - end - - def self.remove_column(table_name, column_name) - if column_exists?(table_name, column_name) - super(table_name, column_name) - end - end - - def self.add_column(table_name, column_name, type, options = {}) - unless column_exists?(table_name, column_name) - super(table_name, column_name, type, options) - end - end - - def self.add_varchar_index(table_name, column_name, options = {}) - if dialect()=='mysql' && !options[:length] - # Index of varchar column is limited to 767 bytes on mysql (<= 255 UTF-8 characters) - # See http://jira.sonarsource.com/browse/SONAR-4137 and - # http://dev.mysql.com/doc/refman/5.6/en/innodb-restrictions.html - options[:length]=255 - end - add_index table_name, column_name, options - end - - def self.execute_java_migration(classname) - Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration(classname) - end - - def self.alter_to_big_primary_key(tablename) - case dialect() - when "postgre" - execute "ALTER TABLE #{tablename} ALTER COLUMN id TYPE bigint" - when "mysql" - execute "ALTER TABLE #{tablename} CHANGE id id BIGINT AUTO_INCREMENT" - when "h2" - # not needed? - when "oracle" - # do nothing, oracle integer are big enough - when "sqlserver" - constraint=select_one "select name from sysobjects where parent_obj = (select id from sysobjects where name = '#{tablename}')" - execute "ALTER TABLE #{tablename} DROP CONSTRAINT #{constraint["name"]}" - execute "ALTER TABLE #{tablename} ALTER COLUMN id bigint" - execute "ALTER TABLE #{tablename} ADD PRIMARY KEY(id)" - end - end - - def self.alter_to_big_integer(tablename, columnname, indexname=nil) - case dialect() - when "sqlserver" - execute "DROP INDEX #{indexname} on #{tablename}" if indexname - change_column(tablename, columnname, :big_integer, :null => true) - execute "CREATE INDEX #{indexname} on #{tablename}(#{columnname})" if indexname - else - change_column(tablename, columnname, :big_integer, :null => true) - end - end - - def self.add_primary_key(tablename, columnname) - if dialect()=="mysql" - execute "ALTER TABLE `#{tablename}` ADD PRIMARY KEY (`#{columnname}`)" - else - execute "ALTER TABLE #{tablename} ADD CONSTRAINT pk_#{tablename} PRIMARY KEY (#{columnname})" - end - end - - # SONAR-4178 - def self.create_table(table_name, options = {}) - # Oracle constraint (see names of triggers and indices) - raise ArgumentError, "Table name is too long: #{table_name}" if table_name.to_s.length>25 - - super(table_name, options) - create_id_trigger(table_name) if dialect()=='oracle' && options[:id] != false - end - - def drop_table(table_name, options = {}) - super(table_name, options) - drop_id_trigger(table_name) if dialect()=='oracle' - end - - def self.rename_table(old_table_name, new_table_name, options = {}) - drop_id_trigger(old_table_name) if dialect()=='oracle' && options[:id] != false - super(old_table_name, new_table_name) - create_id_trigger(new_table_name) if dialect()=='oracle' && options[:id] != false - end - - def self.create_id_trigger(table) - execute_ddl("create trigger for table #{table}", - - %{CREATE OR REPLACE TRIGGER #{table}_idt - BEFORE INSERT ON #{table} - FOR EACH ROW - BEGIN - IF :new.id IS null THEN - SELECT #{table}_seq.nextval INTO :new.id FROM dual; - END IF; - END;}) - end - - def self.drop_id_trigger(table) - drop_trigger("#{table}_idt") - end - - def self.drop_trigger(trigger_name) - execute_ddl("drop trigger #{trigger_name}", "DROP TRIGGER #{trigger_name}") - end - - def self.write(text="") - # See migration.rb, the method write directly calls "puts" - Java::OrgSlf4j::LoggerFactory::getLogger('DbMigration').info(text) if verbose - end - - def self.drop_index_quietly(table, index) - begin - remove_index table, :name => index - rescue - #ignore - end - end - - - private - - def self.execute_ddl(message, ddl) - say_with_time(message) do - ActiveRecord::Base.connection.execute(ddl) - end - end -end - # patch for SONAR-1182. GWT does not support ISO8601 dates that end with 'Z' # http://google-web-toolkit.googlecode.com/svn/javadoc/1.6/com/google/gwt/i18n/client/DateTimeFormat.html module ActiveSupport diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/001_create_initial_schema.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/001_create_initial_schema.rb deleted file mode 100644 index 049022bd018..00000000000 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/001_create_initial_schema.rb +++ /dev/null @@ -1,24 +0,0 @@ - # - # SonarQube, open source software quality management tool. - # Copyright (C) 2008-2016 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. - # -class CreateInitialSchema < ActiveRecord::Migration - def self.up - execute_java_migration('org.sonar.db.version.v56.CreateInitialSchema') - end -end diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/002_populate_initial_schema.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/002_populate_initial_schema.rb deleted file mode 100644 index 3687c57fe3d..00000000000 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/002_populate_initial_schema.rb +++ /dev/null @@ -1,24 +0,0 @@ - # - # SonarQube, open source software quality management tool. - # Copyright (C) 2008-2016 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. - # -class PopulateInitialSchema < ActiveRecord::Migration - def self.up - execute_java_migration('org.sonar.db.version.v56.PopulateInitialSchema') - end -end diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/README.txt b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/README.txt deleted file mode 100644 index 3cd43b6e984..00000000000 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/README.txt +++ /dev/null @@ -1,55 +0,0 @@ -HOW TO ADD A MIGRATION - -* Jump some versions when adding the first Ruby on Rails migration of a new sonar version. For example if sonar 2.10 is 193, then sonar 2.11 should start at 200. -* Complete the DDL files for H2 : - + sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl - + sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql : - - add "INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('<THE MIGRATION ID>')" -* Update the migration id defined in org.sonar.db.version.DatabaseVersion -* If a table is added or removed, then edit org.sonar.db.version.DatabaseVersion#TABLES -* Changes in bulk must be handled using Java migrations based on org.sonar.db.version.MassUpdate : - + Create the class for the Java migration in package org.sonar.db.version.vXYZ, where XYZ is the version of SQ without dots - + Add the class to org.sonar.db.version.MigrationStepModule - + Create a Ruby migration which calls execute_java_migration('org.sonar.db.version.vXYZ.MyMigration') - + Simple, "one to one" migrations that only need to be split by 1000 can rely on class org.sonar.db.version.BaseDataChange - - -RECOMMENDATIONS - -* Prefer to add nullable columns to avoid problems during migration, EXCEPT for booleans. For booleans: - - * columns must be NON-nullable but default value (false) must NOT be set in database. It allows to fully define the model programmatically. - * column names must be chosen so that the default value is actually false. - * E.g.: rule_failures.switched_off - -* Always create an index with a name : add_index "action_plans", "project_id", :name => "action_plans_project_id" - Note that this name is limited to 30 characters because of Oracle constraint. - -* Silently ignore failures when adding an index that has already been created by users. It can occur when the index - is not created in the same migration script than the table. - - begin - add_index "action_plans", "project_id", :name => "action_plans_project_id" - rescue - # ignore - end - -* Use faux models when touching rows (SELECT/INSERT/UPDATE/DELETE). See http://guides.rubyonrails.org/migrations.html#using-models-in-your-migrations - for more details. Note that associations must not be used. - IMPORTANT : do not use faux models for user models (User, Group, UserRole, GroupRole) because of required associations and password encryption. - - - class MyMigration < ActiveRecord::Migration - # This is the faux model. It only maps columns. No functional methods. - class Metric < ActiveRecord::Base - end - - def self.up - # it’s a good idea to call reset_column_information to refresh the ActiveRecord cache for the model prior to - # updating data in the database - Metric.reset_column_information - Metric.find(:all) do |m| - m.save - end - end - end diff --git a/server/sonar-web/src/main/webapp/WEB-INF/lib/database_version.rb b/server/sonar-web/src/main/webapp/WEB-INF/lib/database_version.rb index 52f032d0441..9656163835a 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/lib/database_version.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/lib/database_version.rb @@ -53,7 +53,7 @@ class DatabaseVersion def self.uptodate? unless $uptodate - $uptodate = (current_version>=target_version) + $uptodate = Java::OrgSonarServerUi::JRubyFacade.getInstance().isDbUptodate() end $uptodate end @@ -63,7 +63,6 @@ class DatabaseVersion end def self.upgrade_and_start - ActiveRecord::Migrator.migrate(migrations_path) Java::OrgSonarServerPlatform::Platform.getInstance().upgradeDb() Java::OrgSonarServerPlatform::Platform.getInstance().doStart() load_java_web_services diff --git a/sonar-db/src/main/java/org/sonar/db/version/BaseDataChange.java b/sonar-db/src/main/java/org/sonar/db/version/BaseDataChange.java deleted file mode 100644 index ae82b4d2f89..00000000000 --- a/sonar-db/src/main/java/org/sonar/db/version/BaseDataChange.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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; - -import java.sql.Connection; -import java.sql.SQLException; -import org.apache.commons.dbutils.DbUtils; -import org.sonar.db.Database; - -public abstract class BaseDataChange implements DataChange, MigrationStep { - - private final Database db; - - public BaseDataChange(Database db) { - this.db = db; - } - - @Override - public final void execute() throws SQLException { - Connection readConnection = null; - Connection writeConnection = null; - try { - readConnection = openConnection(); - - writeConnection = db.getDataSource().getConnection(); - writeConnection.setAutoCommit(false); - Context context = new Context(db, readConnection, writeConnection); - execute(context); - - } finally { - DbUtils.closeQuietly(readConnection); - DbUtils.closeQuietly(writeConnection); - } - } - - /** - * Do not forget to close it ! - */ - protected Connection openConnection() throws SQLException { - Connection connection = db.getDataSource().getConnection(); - connection.setAutoCommit(false); - if (connection.getMetaData().supportsTransactionIsolationLevel(Connection.TRANSACTION_READ_UNCOMMITTED)) { - connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED); - } - return connection; - } - -} diff --git a/sonar-db/src/main/java/org/sonar/db/version/DdlChange.java b/sonar-db/src/main/java/org/sonar/db/version/DdlChange.java deleted file mode 100644 index ffab3bb9fc5..00000000000 --- a/sonar-db/src/main/java/org/sonar/db/version/DdlChange.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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; - -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.List; -import java.util.regex.Pattern; -import org.apache.commons.dbutils.DbUtils; -import org.sonar.db.Database; -import org.sonar.db.dialect.Dialect; - -import static java.lang.String.format; -import static java.util.Arrays.asList; - -public abstract class DdlChange implements MigrationStep { - - private final Database db; - - public DdlChange(Database db) { - this.db = db; - } - - @Override - public final void execute() throws SQLException { - Connection writeConnection = null; - try { - writeConnection = db.getDataSource().getConnection(); - writeConnection.setAutoCommit(false); - Context context = new Context(writeConnection); - execute(context); - - } finally { - DbUtils.closeQuietly(writeConnection); - } - } - - public abstract void execute(Context context) throws SQLException; - - protected Database getDatabase() { - return db; - } - - protected Dialect getDialect() { - return db.getDialect(); - } - - public static class Context { - private static final int ERROR_HANDLING_THRESHOLD = 10; - // the tricky regexp is required to match "NULL" but not "NOT NULL" - private final Pattern nullPattern = Pattern.compile("\\h?(?<!NOT )NULL"); - private final Pattern notNullPattern = Pattern.compile("\\h?NOT NULL"); - private final Connection writeConnection; - - public Context(Connection writeConnection) { - this.writeConnection = writeConnection; - } - - public void execute(String sql) throws SQLException { - execute(sql, sql, 0); - } - - public void execute(String original, String sql, int errorCount) throws SQLException { - try (Statement stmt = writeConnection.createStatement()) { - stmt.execute(sql); - writeConnection.commit(); - } catch (SQLException e) { - if (errorCount < ERROR_HANDLING_THRESHOLD) { - String message = e.getMessage(); - if (message.contains("ORA-01451")) { - String newSql = nullPattern.matcher(sql).replaceFirst(""); - execute(original, newSql, errorCount + 1); - return; - } else if (message.contains("ORA-01442")) { - String newSql = notNullPattern.matcher(sql).replaceFirst(""); - execute(original, newSql, errorCount + 1); - return; - } - } - throw new IllegalStateException(messageForIseOf(original, sql, errorCount), e); - } catch (Exception e) { - throw new IllegalStateException(messageForIseOf(original, sql, errorCount), e); - } - } - - private static String messageForIseOf(String original, String sql, int errorCount) { - if (!original.equals(sql) || errorCount > 0) { - return format("Fail to execute %s %n (caught %s error, original was %s)", sql, errorCount, original); - } else { - return format("Fail to execute %s", sql); - } - } - - public void execute(String... sqls) throws SQLException { - execute(asList(sqls)); - } - - public void execute(List<String> sqls) throws SQLException { - for (String sql : sqls) { - execute(sql); - } - } - } -} diff --git a/sonar-db/src/main/java/org/sonar/db/version/MigrationStep.java b/sonar-db/src/main/java/org/sonar/db/version/MigrationStep.java deleted file mode 100644 index 6a50bc05795..00000000000 --- a/sonar-db/src/main/java/org/sonar/db/version/MigrationStep.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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; - -import java.sql.SQLException; - -/** - * Java alternative of ActiveRecord::Migration. Do not forget to declare implementation classes in {@link MigrationStepModule} - * @since 3.7 - */ -public interface MigrationStep { - - void execute() throws SQLException; - -} diff --git a/sonar-db/src/test/java/org/sonar/db/version/BaseDataChangeTest.java b/sonar-db/src/test/java/org/sonar/db/version/BaseDataChangeTest.java deleted file mode 100644 index 329f54955e2..00000000000 --- a/sonar-db/src/test/java/org/sonar/db/version/BaseDataChangeTest.java +++ /dev/null @@ -1,479 +0,0 @@ -/* - * 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; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.api.utils.System2; -import org.sonar.db.BatchSession; -import org.sonar.db.DbTester; -import org.sonar.db.version.Select.Row; -import org.sonar.db.version.Select.RowReader; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; - - -public class BaseDataChangeTest { - - @Rule - public DbTester db = DbTester.createForSchema(System2.INSTANCE, BaseDataChangeTest.class, "schema.sql"); - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Before - public void setUp() { - db.executeUpdateSql("truncate table persons"); - } - - @Test - public void query() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - final AtomicBoolean executed = new AtomicBoolean(false); - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - assertThat(context.prepareSelect("select id from persons order by id desc").list(Select.LONG_READER)) - .containsExactly(3L, 2L, 1L); - assertThat(context.prepareSelect("select id from persons where id=?").setLong(1, 2L).get(Select.LONG_READER)) - .isEqualTo(2L); - assertThat(context.prepareSelect("select id from persons where id=?").setLong(1, 12345L).get(Select.LONG_READER)) - .isNull(); - executed.set(true); - } - }.execute(); - assertThat(executed.get()).isTrue(); - } - - @Test - public void read_column_types() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - final List<Object[]> persons = new ArrayList<>(); - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - persons.addAll(context - .prepareSelect("select id,login,age,enabled,updated_at,coeff from persons where id=2") - .list(new UserReader())); - } - }.execute(); - assertThat(persons).hasSize(1); - assertThat(persons.get(0)[0]).isEqualTo(2L); - assertThat(persons.get(0)[1]).isEqualTo("emmerik"); - assertThat(persons.get(0)[2]).isEqualTo(14); - assertThat(persons.get(0)[3]).isEqualTo(true); - assertThat(persons.get(0)[4]).isNotNull(); - assertThat(persons.get(0)[5]).isEqualTo(5.2); - } - - @Test - public void parameterized_query() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - final List<Long> ids = new ArrayList<>(); - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - ids.addAll(context.prepareSelect("select id from persons where id>=?").setLong(1, 2L).list(Select.LONG_READER)); - } - }.execute(); - assertThat(ids).containsOnly(2L, 3L); - } - - @Test - public void display_current_row_details_if_error_during_get() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - thrown.expect(IllegalStateException.class); - thrown.expectMessage("Error during processing of row: [id=2]"); - - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - context.prepareSelect("select id from persons where id>=?").setLong(1, 2L).get(new RowReader<Long>() { - @Override - public Long read(Row row) throws SQLException { - throw new IllegalStateException("Unexpected error"); - } - }); - } - }.execute(); - - } - - @Test - public void display_current_row_details_if_error_during_list() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - thrown.expect(IllegalStateException.class); - thrown.expectMessage("Error during processing of row: [id=2]"); - - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - context.prepareSelect("select id from persons where id>=?").setLong(1, 2L).list(new RowReader<Long>() { - @Override - public Long read(Row row) throws SQLException { - throw new IllegalStateException("Unexpected error"); - } - }); - } - }.execute(); - - } - - @Test - public void bad_parameterized_query() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - final List<Long> ids = new ArrayList<>(); - BaseDataChange change = new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - // parameter value is not set - ids.addAll(context.prepareSelect("select id from persons where id>=?").list(Select.LONG_READER)); - } - }; - - thrown.expect(SQLException.class); - - change.execute(); - } - - @Test - public void scroll() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - final List<Long> ids = new ArrayList<>(); - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - context.prepareSelect("select id from persons order by id desc").scroll(new Select.RowHandler() { - @Override - public void handle(Select.Row row) throws SQLException { - ids.add(row.getNullableLong(1)); - } - }); - } - }.execute(); - assertThat(ids).containsExactly(3L, 2L, 1L); - } - - @Test - public void insert() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - context.prepareUpsert("insert into persons(id,login,age,enabled,coeff) values (?,?,?,?,?)") - .setLong(1, 10L) - .setString(2, "kurt") - .setInt(3, 27) - .setBoolean(4, true) - .setDouble(5, 2.2) - .execute().commit().close(); - } - }.execute(); - - db.assertDbUnit(getClass(), "insert-result.xml", "persons"); - } - - @Test - public void batch_insert() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - Upsert upsert = context.prepareUpsert("insert into persons(id,login,age,enabled,coeff) values (?,?,?,?,?)"); - upsert - .setLong(1, 10L) - .setString(2, "kurt") - .setInt(3, 27) - .setBoolean(4, true) - .setDouble(5, 2.2) - .addBatch(); - upsert - .setLong(1, 11L) - .setString(2, "courtney") - .setInt(3, 25) - .setBoolean(4, false) - .setDouble(5, 2.3) - .addBatch(); - upsert.execute().commit().close(); - } - }.execute(); - - db.assertDbUnit(getClass(), "batch-insert-result.xml", "persons"); - } - - @Test - public void update_null() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - Upsert upsert = context.prepareUpsert("update persons set login=?,age=?,enabled=?, updated_at=?, coeff=? where id=?"); - upsert - .setString(1, null) - .setInt(2, null) - .setBoolean(3, null) - .setDate(4, null) - .setDouble(5, null) - .setLong(6, 2L) - .execute() - .commit() - .close(); - } - }.execute(); - - db.assertDbUnit(getClass(), "update-null-result.xml", "persons"); - } - - @Test - public void mass_batch_insert() throws Exception { - db.executeUpdateSql("truncate table persons"); - - final int count = BatchSession.MAX_BATCH_SIZE + 10; - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - Upsert upsert = context.prepareUpsert("insert into persons(id,login,age,enabled,coeff) values (?,?,?,?,?)"); - for (int i = 0; i < count; i++) { - upsert - .setLong(1, 10L + i) - .setString(2, "login" + i) - .setInt(3, 10 + i) - .setBoolean(4, true) - .setDouble(4, i + 0.5) - .addBatch(); - } - upsert.execute().commit().close(); - - } - }.execute(); - - assertThat(db.countRowsOfTable("persons")).isEqualTo(count); - } - - @Test - public void scroll_and_update() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - final Upsert upsert = context.prepareUpsert("update persons set login=?, age=? where id=?"); - context.prepareSelect("select id from persons").scroll(new Select.RowHandler() { - @Override - public void handle(Select.Row row) throws SQLException { - long id = row.getNullableLong(1); - upsert.setString(1, "login" + id).setInt(2, 10 + (int) id).setLong(3, id); - upsert.execute(); - } - }); - upsert.commit().close(); - } - }.execute(); - - db.assertDbUnit(getClass(), "scroll-and-update-result.xml", "persons"); - } - - @Test - public void display_current_row_details_if_error_during_scroll() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - thrown.expect(IllegalStateException.class); - thrown.expectMessage("Error during processing of row: [id=1]"); - - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - final Upsert upsert = context.prepareUpsert("update persons set login=?, age=? where id=?"); - context.prepareSelect("select id from persons").scroll(new Select.RowHandler() { - @Override - public void handle(Select.Row row) throws SQLException { - throw new IllegalStateException("Unexpected error"); - } - }); - upsert.commit().close(); - } - }.execute(); - } - - @Test - public void mass_update() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - MassUpdate massUpdate = context.prepareMassUpdate(); - massUpdate.select("select id from persons where id>=?").setLong(1, 2L); - massUpdate.update("update persons set login=?, age=? where id=?"); - massUpdate.execute(new MassUpdate.Handler() { - @Override - public boolean handle(Select.Row row, SqlStatement update) throws SQLException { - long id = row.getNullableLong(1); - update - .setString(1, "login" + id) - .setInt(2, 10 + (int) id) - .setLong(3, id); - return true; - } - }); - } - }.execute(); - - db.assertDbUnit(getClass(), "mass-update-result.xml", "persons"); - } - - @Test - public void display_current_row_details_if_error_during_mass_update() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - thrown.expect(IllegalStateException.class); - thrown.expectMessage("Error during processing of row: [id=2]"); - - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - MassUpdate massUpdate = context.prepareMassUpdate(); - massUpdate.select("select id from persons where id>=?").setLong(1, 2L); - massUpdate.update("update persons set login=?, age=? where id=?"); - massUpdate.execute(new MassUpdate.Handler() { - @Override - public boolean handle(Select.Row row, SqlStatement update) throws SQLException { - throw new IllegalStateException("Unexpected error"); - } - }); - } - }.execute(); - } - - @Test - public void mass_update_nothing() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - MassUpdate massUpdate = context.prepareMassUpdate(); - massUpdate.select("select id from persons where id>=?").setLong(1, 2L); - massUpdate.update("update persons set login=?, age=? where id=?"); - massUpdate.execute(new MassUpdate.Handler() { - @Override - public boolean handle(Select.Row row, SqlStatement update) throws SQLException { - return false; - } - }); - } - }.execute(); - - db.assertDbUnit(getClass(), "persons.xml", "persons"); - } - - @Test - public void bad_mass_update() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - BaseDataChange change = new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - MassUpdate massUpdate = context.prepareMassUpdate(); - massUpdate.select("select id from persons where id>=?").setLong(1, 2L); - // update is not set - massUpdate.execute(new MassUpdate.Handler() { - @Override - public boolean handle(Select.Row row, SqlStatement update) throws SQLException { - return false; - } - }); - } - }; - try { - change.execute(); - fail(); - } catch (IllegalStateException e) { - assertThat(e).hasMessage("SELECT or UPDATE requests are not defined"); - } - } - - @Test - public void read_not_null_fields() throws Exception { - db.prepareDbUnit(getClass(), "persons.xml"); - - final List<Object[]> persons = new ArrayList<>(); - new BaseDataChange(db.database()) { - @Override - public void execute(Context context) throws SQLException { - persons.addAll(context - .prepareSelect("select id,login,age,enabled,updated_at,coeff from persons where id=2") - .list(new Select.RowReader<Object[]>() { - @Override - public Object[] read(Select.Row row) throws SQLException { - return new Object[] { - // id, login, age, enabled - row.getLong(1), - row.getString(2), - row.getInt(3), - row.getBoolean(4), - row.getDate(5), - row.getDouble(6), - }; - } - })); - } - }.execute(); - assertThat(persons).hasSize(1); - assertThat(persons.get(0)[0]).isEqualTo(2L); - assertThat(persons.get(0)[1]).isEqualTo("emmerik"); - assertThat(persons.get(0)[2]).isEqualTo(14); - assertThat(persons.get(0)[3]).isEqualTo(true); - assertThat(persons.get(0)[4]).isNotNull(); - assertThat(persons.get(0)[5]).isEqualTo(5.2); - } - - static class UserReader implements Select.RowReader<Object[]> { - @Override - public Object[] read(Select.Row row) throws SQLException { - return new Object[] { - // id, login, age, enabled - row.getNullableLong(1), - row.getNullableString(2), - row.getNullableInt(3), - row.getNullableBoolean(4), - row.getNullableDate(5), - row.getNullableDouble(6), - }; - } - } -} |