aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2016-12-13 12:20:34 +0100
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>2016-12-14 12:11:53 +0100
commit610a9a839737166711a29cbb1fdb7911474c5b40 (patch)
treef9cb60518fd3c4aaf5d8a1d6233a55c0ace06000 /server
parente2cff9277df4ccaae9098a13d36c52ef70b259fc (diff)
downloadsonarqube-610a9a839737166711a29cbb1fdb7911474c5b40.tar.gz
sonarqube-610a9a839737166711a29cbb1fdb7911474c5b40.zip
SONAR-8445 move SQ 5.6 create schema migrations out of Ruby
and start some cleaning of migration related code in Ruby
Diffstat (limited to 'server')
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DbVersionModule.java2
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchema.java924
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/DbVersion56.java32
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchema.java121
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/package-info.java24
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DbVersionModuleTest.java2
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchemaTest.java100
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/DbVersion56Test.java47
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchemaTest.java131
-rw-r--r--server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchemaTest/empty.sql0
-rw-r--r--server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchemaTest/v56.sql47
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/db/migrations/DatabaseMigrator.java28
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel2.java5
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java8
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/db/migrations/DatabaseMigratorTest.java35
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/AddAnalysisUuidColumnToDuplicationsIndex.java3
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/AddComponentUuidColumnToDuplicationsIndex.java3
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/DeleteOrphanDuplicationsIndexRowsWithoutComponent.java3
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v1/MakeComponentUuidNotNullOnDuplicationsIndex.java3
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v2/AddComponentUuidAndAnalysisUuidColumnToDuplicationsIndex.java3
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStepTest/v2/MakeComponentUuidAndAnalysisUuidNotNullOnDuplicationsIndex.java3
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/config/environment.rb155
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/db/migrate/001_create_initial_schema.rb24
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/db/migrate/002_populate_initial_schema.rb24
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/db/migrate/README.txt55
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/lib/database_version.rb3
26 files changed, 1446 insertions, 339 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/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchema.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchema.java
new file mode 100644
index 00000000000..d037512bbf0
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchema.java
@@ -0,0 +1,924 @@
+/*
+ * 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.platform.db.migration.version.v56;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.version.BigIntegerColumnDef;
+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.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;
+import static org.sonar.db.version.BooleanColumnDef.newBooleanColumnDefBuilder;
+import static org.sonar.db.version.ClobColumnDef.newClobColumnDefBuilder;
+import static org.sonar.db.version.CreateTableBuilder.ColumnFlag.AUTO_INCREMENT;
+import static org.sonar.db.version.DecimalColumnDef.newDecimalColumnDefBuilder;
+import static org.sonar.db.version.IntegerColumnDef.newIntegerColumnDefBuilder;
+import static org.sonar.db.version.TimestampColumnDef.newTimestampColumnDefBuilder;
+
+public class CreateInitialSchema extends DdlChange {
+
+ public CreateInitialSchema(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ createActiveDashboards(context);
+ createActiveRuleParameters(context);
+ createActiveRules(context);
+ createActivities(context);
+ createAuthors(context);
+ createCeActivity(context);
+ createCeQueue(context);
+ createDashboards(context);
+ createDuplicationsIndex(context);
+ createEvents(context);
+ createFileSources(context);
+ createGroupRoles(context);
+ createGroups(context);
+ createGroupsUsers(context);
+ createIssueChanges(context);
+ createIssueFilterFavourites(context);
+ createIssueFilters(context);
+ createIssues(context);
+ createLoadedTemplates(context);
+ createManualMeasures(context);
+ createMeasureFilterFavourites(context);
+ createMeasureFilters(context);
+ createMetrics(context);
+ createNotifications(context);
+ createPermissionTemplates(context);
+ createPermTemplatesGroups(context);
+ createPermTemplatesUsers(context);
+ createProjectLinks(context);
+ createProjectMeasures(context);
+ createProjectQprofiles(context);
+ createProjects(context);
+ createProperties(context);
+ createQualityGateConditions(context);
+ createQualityGates(context);
+ createResourceIndex(context);
+ createRules(context);
+ createRulesParameters(context);
+ createRulesProfiles(context);
+ createSnapshots(context);
+ createUserRoles(context);
+ createUserTokens(context);
+ createUsers(context);
+ createWidgetProperties(context);
+ createWidgets(context);
+ }
+
+ private void createUserTokens(Context context) throws SQLException {
+ VarcharColumnDef loginCol = newLenientVarcharBuilder("login").setLimit(255).setIsNullable(false).build();
+ VarcharColumnDef nameCol = newLenientVarcharBuilder("name").setLimit(100).setIsNullable(false).build();
+ VarcharColumnDef tokenHashCol = newLenientVarcharBuilder("token_hash").setLimit(255).setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("user_tokens")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(loginCol)
+ .addColumn(nameCol)
+ .addColumn(tokenHashCol)
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").setIsNullable(false).build())
+ .build());
+ addIndex(context, "user_tokens", "user_tokens_login_name", true, loginCol, nameCol);
+ addIndex(context, "user_tokens", "user_tokens_token_hash", true, tokenHashCol);
+ }
+
+ private void createCeActivity(Context context) throws SQLException {
+ VarcharColumnDef uuidCol = newLenientVarcharBuilder("uuid").setLimit(40).setIsNullable(false).build();
+ VarcharColumnDef isLastKeyCol = newLenientVarcharBuilder("is_last_key").setLimit(55).setIsNullable(false).build();
+ BooleanColumnDef isLastCol = newBooleanColumnDefBuilder().setColumnName("is_last").setIsNullable(false).build();
+ VarcharColumnDef statusCol = newLenientVarcharBuilder("status").setLimit(15).setIsNullable(false).build();
+ VarcharColumnDef componentUuidCol = newLenientVarcharBuilder("component_uuid").setLimit(40).build();
+ context.execute(
+ newTableBuilder("ce_activity")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(uuidCol)
+ .addColumn(newLenientVarcharBuilder("task_type").setLimit(15).setIsNullable(false).build())
+ .addColumn(componentUuidCol)
+ .addColumn(statusCol)
+ .addColumn(isLastCol)
+ .addColumn(isLastKeyCol)
+ .addColumn(newLenientVarcharBuilder("submitter_login").setLimit(255).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("submitted_at").setIsNullable(false).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("started_at").build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("executed_at").build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").setIsNullable(false).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("updated_at").setIsNullable(false).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("execution_time_ms").build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("snapshot_id").build())
+ .build());
+ addIndex(context, "ce_activity", "ce_activity_component_uuid", false, componentUuidCol);
+ addIndex(context, "ce_activity", "ce_activity_islast_status", false, isLastCol, statusCol);
+ addIndex(context, "ce_activity", "ce_activity_islastkey", false, isLastKeyCol);
+ addIndex(context, "ce_activity", "ce_activity_uuid", true, uuidCol);
+ }
+
+ private void createCeQueue(Context context) throws SQLException {
+ VarcharColumnDef uuidCol = newLenientVarcharBuilder("uuid").setLimit(40).setIsNullable(false).build();
+ VarcharColumnDef componentUuidCol = newLenientVarcharBuilder("component_uuid").setLimit(40).build();
+ context.execute(
+ newTableBuilder("ce_queue")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(uuidCol)
+ .addColumn(newLenientVarcharBuilder("task_type").setLimit(15).setIsNullable(false).build())
+ .addColumn(componentUuidCol)
+ .addColumn(newLenientVarcharBuilder("status").setLimit(15).build())
+ .addColumn(newLenientVarcharBuilder("submitter_login").setLimit(255).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("started_at").build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").setIsNullable(false).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("updated_at").setIsNullable(false).build())
+ .build());
+ addIndex(context, "ce_queue", "ce_queue_component_uuid", false, componentUuidCol);
+ addIndex(context, "ce_queue", "ce_queue_uuid", true, uuidCol);
+ }
+
+ private void createFileSources(Context context) throws SQLException {
+ VarcharColumnDef projectUuidCol = newLenientVarcharBuilder("project_uuid").setLimit(50).setIsNullable(false).build();
+ BigIntegerColumnDef updatedAtCol = newBigIntegerColumnDefBuilder().setColumnName("updated_at").setIsNullable(false).build();
+ VarcharColumnDef dataTypeCol = newLenientVarcharBuilder("data_type").setLimit(20).build();
+ VarcharColumnDef fileUuidCol = newLenientVarcharBuilder("file_uuid").setLimit(50).setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("file_sources")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(projectUuidCol)
+ .addColumn(fileUuidCol)
+ .addColumn(newClobColumnDefBuilder().setColumnName("line_hashes").build())
+ .addColumn(newLenientVarcharBuilder("data_hash").setLimit(50).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").setIsNullable(false).build())
+ .addColumn(updatedAtCol)
+ .addColumn(newLenientVarcharBuilder("src_hash").setLimit(50).build())
+ .addColumn(newBlobColumnDefBuilder().setColumnName("binary_data").build())
+ .addColumn(dataTypeCol)
+ .addColumn(newLenientVarcharBuilder("revision").setLimit(100).build())
+ .build());
+ addIndex(context, "file_sources", "file_sources_project_uuid", false, projectUuidCol);
+ addIndex(context, "file_sources", "file_sources_updated_at", false, updatedAtCol);
+ addIndex(context, "file_sources", "file_sources_uuid_type", true, fileUuidCol, dataTypeCol);
+ }
+
+ private void createActivities(Context context) throws SQLException {
+ VarcharColumnDef keeCol = newLenientVarcharBuilder("log_key").setLimit(255).build();
+ context.execute(
+ newTableBuilder("activities")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(newLenientVarcharBuilder("user_login").setLimit(255).build())
+ .addColumn(newClobColumnDefBuilder().setColumnName("data_field").build())
+ .addColumn(newLenientVarcharBuilder("log_type").setLimit(50).build())
+ .addColumn(newLenientVarcharBuilder("log_action").setLimit(50).build())
+ .addColumn(newLenientVarcharBuilder("log_message").setLimit(4000).build())
+ .addColumn(keeCol)
+ .build());
+
+ addIndex(context, "activities", "activities_log_key", true, keeCol);
+ }
+
+ private void createPermTemplatesGroups(Context context) throws SQLException {
+ context.execute(
+ newTableBuilder("perm_templates_groups")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("group_id").build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("template_id").setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("permission_reference").setLimit(64).setIsNullable(false).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("updated_at").build())
+ .build());
+ }
+
+ private void createPermTemplatesUsers(Context context) throws SQLException {
+ context.execute(
+ newTableBuilder("perm_templates_users")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("user_id").setIsNullable(false).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("template_id").setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("permission_reference").setLimit(64).setIsNullable(false).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("updated_at").build())
+ .build());
+ }
+
+ private void createPermissionTemplates(Context context) throws SQLException {
+ context.execute(
+ newTableBuilder("permission_templates")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newLenientVarcharBuilder("name").setLimit(100).setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("kee").setLimit(100).setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("description").setLimit(4000).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("updated_at").build())
+ .addColumn(newLenientVarcharBuilder("key_pattern").setLimit(500).build())
+ .build());
+ }
+
+ private void createIssueFilterFavourites(Context context) throws SQLException {
+ VarcharColumnDef loginCol = newLenientVarcharBuilder("user_login").setLimit(255).setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("issue_filter_favourites")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(loginCol)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("issue_filter_id").setIsNullable(false).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").build())
+ .build());
+ addIndex(context, "issue_filter_favourites", "issue_filter_favs_user", false, loginCol);
+ }
+
+ private void createIssueFilters(Context context) throws SQLException {
+ VarcharColumnDef nameCol = newLenientVarcharBuilder("name").setLimit(100).setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("issue_filters")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(nameCol)
+ .addColumn(newLenientVarcharBuilder("user_login").setLimit(255).build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("shared").setIsNullable(false).setDefaultValue(false).build())
+ .addColumn(newLenientVarcharBuilder("description").setLimit(4000).build())
+ .addColumn(newClobColumnDefBuilder().setColumnName("data").build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("updated_at").build())
+ .build());
+ addIndex(context, "issue_filters", "issue_filters_name", false, nameCol);
+ }
+
+ private void createIssueChanges(Context context) throws SQLException {
+ VarcharColumnDef issueKeyCol = newLenientVarcharBuilder("issue_key").setLimit(50).setIsNullable(false).build();
+ VarcharColumnDef keeCol = newLenientVarcharBuilder("kee").setLimit(50).build();
+ context.execute(
+ newTableBuilder("issue_changes")
+ .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(keeCol)
+ .addColumn(issueKeyCol)
+ .addColumn(newLenientVarcharBuilder("user_login").setLimit(255).build())
+ .addColumn(newLenientVarcharBuilder("change_type").setLimit(20).build())
+ .addColumn(newClobColumnDefBuilder().setColumnName("change_data").build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("updated_at").build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("issue_change_creation_date").build())
+ .build());
+ addIndex(context, "issue_changes", "issue_changes_issue_key", false, issueKeyCol);
+ addIndex(context, "issue_changes", "issue_changes_kee", false, keeCol);
+ }
+
+ private void createIssues(Context context) throws SQLException {
+ VarcharColumnDef assigneeCol = newLenientVarcharBuilder("assignee").setLimit(255).build();
+ VarcharColumnDef componentUuidCol = newLenientVarcharBuilder("component_uuid").setLimit(50).build();
+ BigIntegerColumnDef issueCreationDateCol = newBigIntegerColumnDefBuilder().setColumnName("issue_creation_date").build();
+ VarcharColumnDef keeCol = newLenientVarcharBuilder("kee").setLimit(50).setIsNullable(false).build();
+ VarcharColumnDef projectUuidCol = newLenientVarcharBuilder("project_uuid").setLimit(50).build();
+ VarcharColumnDef resolutionCol = newLenientVarcharBuilder("resolution").setLimit(20).build();
+ IntegerColumnDef ruleIdCol = newIntegerColumnDefBuilder().setColumnName("rule_id").build();
+ BigIntegerColumnDef updatedAtCol = newBigIntegerColumnDefBuilder().setColumnName("updated_at").build();
+ context.execute(
+ newTableBuilder("issues")
+ .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(keeCol)
+ .addColumn(ruleIdCol)
+ .addColumn(newLenientVarcharBuilder("severity").setLimit(10).build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("manual_severity").setIsNullable(false).build())
+ // unit has been fixed in SonarQube 5.6 (see migration 1151, SONAR-7493)
+ .addColumn(newLenientVarcharBuilder("message").setIgnoreOracleUnit(false).setLimit(4000).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("line").build())
+ .addColumn(newDecimalColumnDefBuilder().setColumnName("gap").setPrecision(30).setScale(20).build())
+ .addColumn(newLenientVarcharBuilder("status").setLimit(20).build())
+ .addColumn(resolutionCol)
+ .addColumn(newLenientVarcharBuilder("checksum").setLimit(1000).build())
+ .addColumn(newLenientVarcharBuilder("reporter").setLimit(255).build())
+ .addColumn(assigneeCol)
+ .addColumn(newLenientVarcharBuilder("author_login").setLimit(255).build())
+ .addColumn(newLenientVarcharBuilder("action_plan_key").setLimit(50).build())
+ .addColumn(newLenientVarcharBuilder("issue_attributes").setLimit(4000).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("effort").build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(updatedAtCol)
+ .addColumn(issueCreationDateCol)
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("issue_update_date").build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("issue_close_date").build())
+ .addColumn(newLenientVarcharBuilder("tags").setLimit(4000).build())
+ .addColumn(componentUuidCol)
+ .addColumn(projectUuidCol)
+ .addColumn(newBlobColumnDefBuilder().setColumnName("locations").build())
+ .addColumn(new TinyIntColumnDef.Builder().setColumnName("issue_type").build())
+ .build());
+ addIndex(context, "issues", "issues_assignee", false, assigneeCol);
+ addIndex(context, "issues", "issues_component_uuid", false, componentUuidCol);
+ addIndex(context, "issues", "issues_creation_date", false, issueCreationDateCol);
+ addIndex(context, "issues", "issues_kee", true, keeCol);
+ addIndex(context, "issues", "issues_project_uuid", false, projectUuidCol);
+ addIndex(context, "issues", "issues_resolution", false, resolutionCol);
+ addIndex(context, "issues", "issues_rule_id", false, ruleIdCol);
+ addIndex(context, "issues", "issues_updated_at", false, updatedAtCol);
+ }
+
+ private void createMeasureFilterFavourites(Context context) throws SQLException {
+ IntegerColumnDef userIdCol = newIntegerColumnDefBuilder().setColumnName("user_id").setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("measure_filter_favourites")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(userIdCol)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("measure_filter_id").setIsNullable(false).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").build())
+ .build());
+ addIndex(context, "measure_filter_favourites", "measure_filter_favs_userid", false, userIdCol);
+ }
+
+ private void createMeasureFilters(Context context) throws SQLException {
+ VarcharColumnDef nameCol = newLenientVarcharBuilder("name").setLimit(100).setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("measure_filters")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(nameCol)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("user_id").build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("shared").setDefaultValue(false).setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("description").setLimit(4000).build())
+ .addColumn(newClobColumnDefBuilder().setColumnName("data").build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("updated_at").build())
+ .build());
+ addIndex(context, "measure_filters", "measure_filters_name", false, nameCol);
+ }
+
+ private void createAuthors(Context context) throws SQLException {
+ VarcharColumnDef loginCol = newLenientVarcharBuilder("login").setLimit(255).build();
+ context.execute(
+ newTableBuilder("authors")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("person_id").setIsNullable(false).build())
+ .addColumn(loginCol)
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("updated_at").build())
+ .build());
+ addIndex(context, "authors", "uniq_author_logins", true, loginCol);
+ }
+
+ private void createResourceIndex(Context context) throws SQLException {
+ VarcharColumnDef keeCol = newLenientVarcharBuilder("kee").setLimit(400).setIsNullable(false).build();
+ IntegerColumnDef resourceIdCol = newIntegerColumnDefBuilder().setColumnName("resource_id").setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("resource_index")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(keeCol)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("position").setIsNullable(false).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("name_size").setIsNullable(false).build())
+ .addColumn(resourceIdCol)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("root_project_id").setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("qualifier").setLimit(10).setIsNullable(false).build())
+ .build());
+ addIndex(context, "resource_index", "resource_index_key", false, keeCol);
+ addIndex(context, "resource_index", "resource_index_rid", false, resourceIdCol);
+ }
+
+ private void createLoadedTemplates(Context context) throws SQLException {
+ context.execute(
+ newTableBuilder("loaded_templates")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newLenientVarcharBuilder("kee").setLimit(200).build())
+ .addColumn(newLenientVarcharBuilder("template_type").setLimit(15).build())
+ .build());
+ }
+
+ private void createMetrics(Context context) throws SQLException {
+ VarcharColumnDef nameCol = newLenientVarcharBuilder("name").setLimit(64).setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("metrics")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(nameCol)
+ .addColumn(newLenientVarcharBuilder("description").setLimit(255).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("direction").setIsNullable(false).setDefaultValue(0).build())
+ .addColumn(newLenientVarcharBuilder("domain").setLimit(64).build())
+ .addColumn(newLenientVarcharBuilder("short_name").setLimit(64).build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("qualitative").setDefaultValue(false).setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("val_type").setLimit(8).build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("user_managed").setDefaultValue(false).build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("enabled").setDefaultValue(true).build())
+ .addColumn(newDecimalColumnDefBuilder().setColumnName("worst_value").setPrecision(38).setScale(20).build())
+ .addColumn(newDecimalColumnDefBuilder().setColumnName("best_value").setPrecision(38).setScale(20).build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("optimized_best_value").build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("hidden").build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("delete_historical_data").build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("decimal_scale").build())
+ .build());
+ addIndex(context, "metrics", "metrics_unique_name", true, nameCol);
+ }
+
+ private void createDashboards(Context context) throws SQLException {
+ context.execute(
+ newTableBuilder("dashboards")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("user_id").build())
+ .addColumn(newLenientVarcharBuilder("name").setLimit(256).build())
+ .addColumn(newLenientVarcharBuilder("description").setLimit(1000).build())
+ .addColumn(newLenientVarcharBuilder("column_layout").setLimit(20).build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("shared").build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("updated_at").build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("is_global").build())
+ .build());
+ }
+
+ private void createUsers(Context context) throws SQLException {
+ VarcharColumnDef loginCol = newLenientVarcharBuilder("login").setLimit(255).build();
+ BigIntegerColumnDef updatedAtCol = newBigIntegerColumnDefBuilder().setColumnName("updated_at").build();
+ context.execute(
+ newTableBuilder("users")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(loginCol)
+ .addColumn(newLenientVarcharBuilder("name").setLimit(200).build())
+ .addColumn(newLenientVarcharBuilder("email").setLimit(100).build())
+ .addColumn(newLenientVarcharBuilder("crypted_password").setLimit(40).build())
+ .addColumn(newLenientVarcharBuilder("salt").setLimit(40).build())
+ .addColumn(newLenientVarcharBuilder("remember_token").setLimit(500).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("remember_token_expires_at").build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("active").setDefaultValue(true).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(updatedAtCol)
+ .addColumn(newLenientVarcharBuilder("scm_accounts").setLimit(4000).build())
+ .addColumn(newLenientVarcharBuilder("external_identity").setLimit(255).build())
+ .addColumn(newLenientVarcharBuilder("external_identity_provider").setLimit(100).build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("user_local").build())
+ .build());
+ addIndex(context, "users", "users_login", true, loginCol);
+ addIndex(context, "users", "users_updated_at", false, updatedAtCol);
+ }
+
+ private void createActiveRuleParameters(Context context) throws SQLException {
+ context.execute(
+ newTableBuilder("active_rule_parameters")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("active_rule_id").setIsNullable(false).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("rules_parameter_id").setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("value").setLimit(4000).build())
+ .addColumn(newLenientVarcharBuilder("rules_parameter_key").setLimit(128).build())
+ .build());
+ }
+
+ private void createActiveRules(Context context) throws SQLException {
+ IntegerColumnDef profileIdCol = newIntegerColumnDefBuilder().setColumnName("profile_id").setIsNullable(false).build();
+ IntegerColumnDef ruleIdCol = newIntegerColumnDefBuilder().setColumnName("rule_id").setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("active_rules")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(profileIdCol)
+ .addColumn(ruleIdCol)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("failure_level").setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("inheritance").setLimit(10).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("updated_at").build())
+ .build());
+ addIndex(context, "active_rules", "uniq_profile_rule_ids", true, profileIdCol, ruleIdCol);
+ }
+
+ private void createUserRoles(Context context) throws SQLException {
+ IntegerColumnDef userIdCol = newIntegerColumnDefBuilder().setColumnName("user_id").build();
+ IntegerColumnDef resourceIdCol = newIntegerColumnDefBuilder().setColumnName("resource_id").build();
+ context.execute(
+ newTableBuilder("user_roles")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(userIdCol)
+ .addColumn(resourceIdCol)
+ .addColumn(newLenientVarcharBuilder("role").setLimit(64).setIsNullable(false).build())
+ .build());
+ addIndex(context, "user_roles", "user_roles_resource", false, resourceIdCol);
+ addIndex(context, "user_roles", "user_roles_user", false, userIdCol);
+ }
+
+ private void createActiveDashboards(Context context) throws SQLException {
+ IntegerColumnDef dashboardIdCol = newIntegerColumnDefBuilder().setColumnName("dashboard_id").setIsNullable(false).build();
+ IntegerColumnDef userIdCol = newIntegerColumnDefBuilder().setColumnName("user_id").build();
+ context.execute(
+ newTableBuilder("active_dashboards")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(dashboardIdCol)
+ .addColumn(userIdCol)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("order_index").build())
+ .build());
+ addIndex(context, "active_dashboards", "active_dashboards_dashboardid", false, dashboardIdCol);
+ addIndex(context, "active_dashboards", "active_dashboards_userid", false, userIdCol);
+ }
+
+ private void createNotifications(Context context) throws SQLException {
+ context.execute(
+ newTableBuilder("notifications")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newBlobColumnDefBuilder().setColumnName("data").build())
+ .build());
+ }
+
+ private void createSnapshots(Context context) throws SQLException {
+ IntegerColumnDef projectIdCol = newIntegerColumnDefBuilder().setColumnName("project_id").setIsNullable(false).build();
+ IntegerColumnDef rootProjectIdCol = newIntegerColumnDefBuilder().setColumnName("root_project_id").setIsNullable(true).build();
+ IntegerColumnDef parentSnapshotIdCol = newIntegerColumnDefBuilder().setColumnName("parent_snapshot_id").setIsNullable(true).build();
+ VarcharColumnDef qualifierCol = newLenientVarcharBuilder("qualifier").setLimit(10).setIsNullable(true).build();
+ IntegerColumnDef rootSnapshotIdCol = newIntegerColumnDefBuilder().setColumnName("root_snapshot_id").setIsNullable(true).build();
+ context.execute(
+ newTableBuilder("snapshots")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(projectIdCol)
+ .addColumn(parentSnapshotIdCol)
+ .addColumn(newLenientVarcharBuilder("status").setLimit(4).setIsNullable(false).setDefaultValue("U").build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("islast").setIsNullable(false).setDefaultValue(false).build())
+ .addColumn(newLenientVarcharBuilder("scope").setLimit(3).setIsNullable(true).build())
+ .addColumn(qualifierCol)
+ .addColumn(rootSnapshotIdCol)
+ .addColumn(newLenientVarcharBuilder("version").setLimit(500).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("path").setLimit(500).setIsNullable(true).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("depth").setIsNullable(true).build())
+ .addColumn(rootProjectIdCol)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("purge_status").setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("period1_mode").setLimit(100).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("period1_param").setLimit(100).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("period2_mode").setLimit(100).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("period2_param").setLimit(100).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("period3_mode").setLimit(100).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("period3_param").setLimit(100).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("period4_mode").setLimit(100).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("period4_param").setLimit(100).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("period5_mode").setLimit(100).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("period5_param").setLimit(100).setIsNullable(true).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").setIsNullable(true).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("build_date").setIsNullable(true).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("period1_date").setIsNullable(true).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("period2_date").setIsNullable(true).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("period3_date").setIsNullable(true).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("period4_date").setIsNullable(true).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("period5_date").setIsNullable(true).build())
+ .build());
+ addIndex(context, "snapshots", "snapshot_project_id", false, projectIdCol);
+ addIndex(context, "snapshots", "snapshots_parent", false, parentSnapshotIdCol);
+ addIndex(context, "snapshots", "snapshots_qualifier", false, qualifierCol);
+ addIndex(context, "snapshots", "snapshots_root", false, rootSnapshotIdCol);
+ addIndex(context, "snapshots", "snapshots_root_project_id", false, rootProjectIdCol);
+ }
+
+ private void createGroups(Context context) throws SQLException {
+ context.execute(
+ newTableBuilder("groups")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newLenientVarcharBuilder("name").setLimit(500).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("description").setLimit(200).setIsNullable(true).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").setIsNullable(true).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("updated_at").setIsNullable(true).build())
+ .build());
+ }
+
+ private void createWidgets(Context context) throws SQLException {
+ IntegerColumnDef dashboardId = newIntegerColumnDefBuilder().setColumnName("dashboard_id").setIsNullable(false).build();
+ VarcharColumnDef widgetKey = newLenientVarcharBuilder("widget_key").setLimit(256).setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("widgets")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(dashboardId)
+ .addColumn(widgetKey)
+ .addColumn(newLenientVarcharBuilder("name").setLimit(256).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("description").setLimit(1000).setIsNullable(true).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("column_index").setIsNullable(true).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("row_index").setIsNullable(true).build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("configured").setIsNullable(true).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").setIsNullable(true).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("updated_at").setIsNullable(true).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("resource_id").setIsNullable(true).build())
+ .build());
+ addIndex(context, "widgets", "widgets_dashboards", false, dashboardId);
+ addIndex(context, "widgets", "widgets_widgetkey", false, widgetKey);
+ }
+
+ private void createProjectQprofiles(Context context) throws SQLException {
+ VarcharColumnDef projectUuid = newLenientVarcharBuilder("project_uuid").setLimit(50).setIsNullable(false).build();
+ VarcharColumnDef profileKey = newLenientVarcharBuilder("profile_key").setLimit(50).setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("project_qprofiles")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(projectUuid)
+ .addColumn(profileKey)
+ .build());
+ addIndex(context, "project_qprofiles", "uniq_project_qprofiles", true, projectUuid, profileKey);
+ }
+
+ private void createRulesProfiles(Context context) throws SQLException {
+ VarcharColumnDef keeCol = newLenientVarcharBuilder("kee").setLimit(255).setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("rules_profiles")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newLenientVarcharBuilder("name").setLimit(100).setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("language").setLimit(20).setIsNullable(true).build())
+ .addColumn(keeCol)
+ .addColumn(newLenientVarcharBuilder("parent_kee").setLimit(255).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("rules_updated_at").setLimit(100).setIsNullable(true).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").setIsNullable(true).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("updated_at").setIsNullable(true).build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("is_default").setIsNullable(false).build())
+ .build());
+ addIndex(context, "rules_profiles", "uniq_qprof_key", true, keeCol);
+ }
+
+ private void createRulesParameters(Context context) throws SQLException {
+ IntegerColumnDef ruleIdCol = newIntegerColumnDefBuilder().setColumnName("rule_id").setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("rules_parameters")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(ruleIdCol)
+ .addColumn(newLenientVarcharBuilder("name").setLimit(128).setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("description").setLimit(4000).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("param_type").setLimit(512).setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("default_value").setLimit(4000).setIsNullable(true).build())
+ .build());
+ addIndex(context, "rules_parameters", "rules_parameters_rule_id", false, ruleIdCol);
+ }
+
+ private void createGroupsUsers(Context context) throws SQLException {
+ BigIntegerColumnDef userIdCol = newBigIntegerColumnDefBuilder().setColumnName("user_id").setIsNullable(true).build();
+ BigIntegerColumnDef groupIdCol = newBigIntegerColumnDefBuilder().setColumnName("group_id").setIsNullable(true).build();
+ context.execute(
+ newTableBuilder("groups_users")
+ .addColumn(userIdCol)
+ .addColumn(groupIdCol)
+ .build());
+ addIndex(context, "groups_users", "index_groups_users_on_user_id", false, userIdCol);
+ addIndex(context, "groups_users", "index_groups_users_on_group_id", false, groupIdCol);
+ addIndex(context, "groups_users", "groups_users_unique", true, groupIdCol, userIdCol);
+ }
+
+ private void createProjectMeasures(Context context) throws SQLException {
+ IntegerColumnDef personIdCol = newIntegerColumnDefBuilder().setColumnName("person_id").build();
+ IntegerColumnDef metricIdCol = newIntegerColumnDefBuilder().setColumnName("metric_id").setIsNullable(false).build();
+ IntegerColumnDef snapshotIdCol = newIntegerColumnDefBuilder().setColumnName("snapshot_id").setIsNullable(true).build();
+ context.execute(
+ newTableBuilder("project_measures")
+ .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newDecimalColumnDefBuilder().setColumnName("value").setPrecision(38).setScale(20).build())
+ .addColumn(metricIdCol)
+ .addColumn(snapshotIdCol)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("rule_id").setIsNullable(true).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("rules_category_id").setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("text_value").setLimit(4000).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("tendency").build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("measure_date").build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("project_id").build())
+ .addColumn(newLenientVarcharBuilder("alert_status").setLimit(5).build())
+ .addColumn(newLenientVarcharBuilder("alert_text").setLimit(4000).build())
+ .addColumn(newLenientVarcharBuilder("url").setLimit(2000).build())
+ .addColumn(newLenientVarcharBuilder("description").setLimit(4000).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("rule_priority").build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("characteristic_id").build())
+ .addColumn(personIdCol)
+ .addColumn(newDecimalColumnDefBuilder().setColumnName("variation_value_1").setPrecision(38).setScale(20).build())
+ .addColumn(newDecimalColumnDefBuilder().setColumnName("variation_value_2").setPrecision(38).setScale(20).build())
+ .addColumn(newDecimalColumnDefBuilder().setColumnName("variation_value_3").setPrecision(38).setScale(20).build())
+ .addColumn(newDecimalColumnDefBuilder().setColumnName("variation_value_4").setPrecision(38).setScale(20).build())
+ .addColumn(newDecimalColumnDefBuilder().setColumnName("variation_value_5").setPrecision(38).setScale(20).build())
+ .addColumn(newBlobColumnDefBuilder().setColumnName("measure_data").build())
+ .build());
+ addIndex(context, "project_measures", "measures_sid_metric", false, snapshotIdCol, metricIdCol);
+ addIndex(context, "project_measures", "measures_person", false, personIdCol);
+ }
+
+ private void createManualMeasures(Context context) throws SQLException {
+ VarcharColumnDef componentUuidCol = newLenientVarcharBuilder("component_uuid").setLimit(50).build();
+ context.execute(
+ newTableBuilder("manual_measures")
+ .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("metric_id").setIsNullable(false).build())
+ .addColumn(newDecimalColumnDefBuilder().setColumnName("value").setPrecision(38).setScale(20).build())
+ .addColumn(newLenientVarcharBuilder("text_value").setLimit(4000).build())
+ .addColumn(newLenientVarcharBuilder("user_login").setLimit(255).build())
+ .addColumn(newLenientVarcharBuilder("description").setLimit(4000).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("updated_at").build())
+ .addColumn(componentUuidCol)
+ .build());
+ addIndex(context, "manual_measures", "manual_measures_component_uuid", false, componentUuidCol);
+ }
+
+ private void createProjects(Context context) throws SQLException {
+ VarcharColumnDef keeCol = newLenientVarcharBuilder("kee").setLimit(400).build();
+ VarcharColumnDef moduleUuidCol = newLenientVarcharBuilder("module_uuid").setLimit(50).build();
+ VarcharColumnDef projectUuidCol = newLenientVarcharBuilder("project_uuid").setLimit(50).build();
+ VarcharColumnDef qualifierCol = newLenientVarcharBuilder("qualifier").setLimit(10).build();
+ IntegerColumnDef rootIdCol = newIntegerColumnDefBuilder().setColumnName("root_id").build();
+ VarcharColumnDef uuidCol = newLenientVarcharBuilder("uuid").setLimit(50).build();
+ context.execute(
+ newTableBuilder("projects")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newLenientVarcharBuilder("name").setLimit(2000).build())
+ .addColumn(newLenientVarcharBuilder("description").setLimit(2000).build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("enabled").setDefaultValue(true).setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("scope").setLimit(3).build())
+ .addColumn(qualifierCol)
+ .addColumn(keeCol)
+ .addColumn(rootIdCol)
+ .addColumn(newLenientVarcharBuilder("language").setLimit(20).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("copy_resource_id").build())
+ .addColumn(newLenientVarcharBuilder("long_name").setLimit(2000).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("person_id").build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").build())
+ .addColumn(newLenientVarcharBuilder("path").setLimit(2000).build())
+ .addColumn(newLenientVarcharBuilder("deprecated_kee").setLimit(400).build())
+ .addColumn(uuidCol)
+ .addColumn(projectUuidCol)
+ .addColumn(moduleUuidCol)
+ .addColumn(newLenientVarcharBuilder("module_uuid_path").setLimit(4000).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("authorization_updated_at").build())
+ .build());
+ addIndex(context, "projects", "projects_kee", true, keeCol);
+ addIndex(context, "projects", "projects_module_uuid", false, moduleUuidCol);
+ addIndex(context, "projects", "projects_project_uuid", false, projectUuidCol);
+ addIndex(context, "projects", "projects_qualifier", false, qualifierCol);
+ addIndex(context, "projects", "projects_root_id", false, rootIdCol);
+ addIndex(context, "projects", "projects_uuid", true, uuidCol);
+ }
+
+ private void createGroupRoles(Context context) throws SQLException {
+ IntegerColumnDef groupIdCol = newIntegerColumnDefBuilder().setColumnName("group_id").setIsNullable(true).build();
+ IntegerColumnDef resourceIdCol = newIntegerColumnDefBuilder().setColumnName("resource_id").setIsNullable(true).build();
+ VarcharColumnDef roleCol = newLenientVarcharBuilder("role").setLimit(64).setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("group_roles")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(groupIdCol)
+ .addColumn(resourceIdCol)
+ .addColumn(roleCol)
+ .build());
+ addIndex(context, "group_roles", "group_roles_resource", false, resourceIdCol);
+ addIndex(context, "group_roles", "uniq_group_roles", true, groupIdCol, resourceIdCol, roleCol);
+ }
+
+ private void createRules(Context context) throws SQLException {
+ VarcharColumnDef pluginRuleKeyCol = newLenientVarcharBuilder("plugin_rule_key").setLimit(200).setIsNullable(false).build();
+ VarcharColumnDef pluginNameCol = newLenientVarcharBuilder("plugin_name").setLimit(255).setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("rules")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newLenientVarcharBuilder("name").setLimit(200).setIsNullable(true).build())
+ .addColumn(pluginRuleKeyCol)
+ .addColumn(newLenientVarcharBuilder("plugin_config_key").setLimit(200).setIsNullable(true).build())
+ .addColumn(pluginNameCol)
+ .addColumn(newClobColumnDefBuilder().setColumnName("description").setIsNullable(true).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("priority").setIsNullable(true).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("template_id").setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("status").setLimit(40).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("language").setLimit(20).setIsNullable(true).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("note_created_at").setIsNullable(true).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("note_updated_at").setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("note_user_login").setLimit(255).setIsNullable(true).build())
+ .addColumn(newClobColumnDefBuilder().setColumnName("note_data").setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("remediation_function").setLimit(200).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("def_remediation_function").setLimit(20).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("remediation_gap_mult").setLimit(20).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("def_remediation_gap_mult").setLimit(20).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("remediation_base_effort").setLimit(20).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("def_remediation_base_effort").setLimit(20).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("gap_description").setLimit(4000).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("tags").setLimit(4000).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("system_tags").setLimit(4000).setIsNullable(true).build())
+ .addColumn(newBooleanColumnDefBuilder().setColumnName("is_template").setIsNullable(false).setDefaultValue(false).build())
+ .addColumn(newLenientVarcharBuilder("description_format").setLimit(20).setIsNullable(true).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").setIsNullable(true).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("updated_at").setIsNullable(true).build())
+ .addColumn(new TinyIntColumnDef.Builder().setColumnName("rule_type").setIsNullable(true).build())
+ .build());
+ addIndex(context, "rules", "rules_repo_key", true, pluginRuleKeyCol, pluginNameCol);
+ }
+
+ private void createWidgetProperties(Context context) throws SQLException {
+ IntegerColumnDef widgetIdCol = newIntegerColumnDefBuilder().setColumnName("widget_id").setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("widget_properties")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(widgetIdCol)
+ .addColumn(newLenientVarcharBuilder("kee").setLimit(100).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("text_value").setLimit(4000).setIsNullable(true).build())
+ .build());
+ addIndex(context, "widget_properties", "widget_properties_widgets", false, widgetIdCol);
+ }
+
+ private void createEvents(Context context) throws SQLException {
+ VarcharColumnDef componentUuid = newLenientVarcharBuilder("component_uuid").setLimit(50).setIsNullable(true).build();
+ IntegerColumnDef snapshotId = newIntegerColumnDefBuilder().setColumnName("snapshot_id").setIsNullable(true).build();
+ context.execute(
+ newTableBuilder("events")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newLenientVarcharBuilder("name").setLimit(400).setIsNullable(true).build())
+ .addColumn(snapshotId)
+ .addColumn(newLenientVarcharBuilder("category").setLimit(50).build())
+ .addColumn(newLenientVarcharBuilder("description").setLimit(4000).build())
+ .addColumn(newLenientVarcharBuilder("event_data").setLimit(4000).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("event_date").setIsNullable(false).build())
+ .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").setIsNullable(false).build())
+ .addColumn(componentUuid)
+ .build());
+ addIndex(context, "events", "events_component_uuid", false, componentUuid);
+ addIndex(context, "events", "events_snapshot_id", false, snapshotId);
+ }
+
+ private void createQualityGates(Context context) throws SQLException {
+ VarcharColumnDef nameCol = newLenientVarcharBuilder("name").setLimit(100).setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("quality_gates")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(nameCol)
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").setIsNullable(true).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("updated_at").setIsNullable(true).build())
+ .build());
+ addIndex(context, "quality_gates", "uniq_quality_gates", true, nameCol);
+ }
+
+ private void createQualityGateConditions(Context context) throws SQLException {
+ context.execute(
+ newTableBuilder("quality_gate_conditions")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("qgate_id").setIsNullable(true).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("metric_id").setIsNullable(true).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("period").setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("operator").setLimit(3).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("value_error").setLimit(64).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("value_warning").setLimit(64).setIsNullable(true).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("created_at").setIsNullable(true).build())
+ .addColumn(newTimestampColumnDefBuilder().setColumnName("updated_at").setIsNullable(true).build())
+ .build());
+ }
+
+ private void createProperties(Context context) throws SQLException {
+ VarcharColumnDef propKey = newLenientVarcharBuilder("prop_key").setLimit(512).setIsNullable(true).build();
+ context.execute(
+ newTableBuilder("properties")
+ // do not define as primary key on purpose -> already set in org.sonar.db.version.v61.CreateTableProperties2
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build())
+ .addColumn(propKey)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("resource_id").setIsNullable(true).build())
+ .addColumn(newClobColumnDefBuilder().setColumnName("text_value").setIsNullable(true).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("user_id").setIsNullable(true).build())
+ .build());
+ addIndex(context, "properties", "properties_key", false, propKey);
+ }
+
+ private void createProjectLinks(Context context) throws SQLException {
+ context.execute(
+ newTableBuilder("project_links")
+ .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newLenientVarcharBuilder("link_type").setLimit(20).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("name").setLimit(128).setIsNullable(true).build())
+ .addColumn(newLenientVarcharBuilder("href").setLimit(2048).setIsNullable(false).build())
+ .addColumn(newLenientVarcharBuilder("component_uuid").setLimit(2048).setIsNullable(true).build())
+ .build());
+ }
+
+ private void createDuplicationsIndex(Context context) throws SQLException {
+ VarcharColumnDef hashCol = newLenientVarcharBuilder("hash").setLimit(50).setIsNullable(false).build();
+ IntegerColumnDef snapshotIdCol = newIntegerColumnDefBuilder().setColumnName("snapshot_id").setIsNullable(false).build();
+ context.execute(
+ newTableBuilder("duplications_index")
+ .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("project_snapshot_id").setIsNullable(false).build())
+ .addColumn(snapshotIdCol)
+ .addColumn(hashCol)
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("index_in_file").setIsNullable(false).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("start_line").setIsNullable(false).build())
+ .addColumn(newIntegerColumnDefBuilder().setColumnName("end_line").setIsNullable(false).build())
+ .build());
+ addIndex(context, "duplications_index", "duplications_index_hash", false, hashCol);
+ addIndex(context, "duplications_index", "duplications_index_sid", false, snapshotIdCol);
+ }
+
+ private void addIndex(Context context, String table, String index, boolean unique, ColumnDef... columns) throws SQLException {
+ CreateIndexBuilder builder = new CreateIndexBuilder(getDialect())
+ .setTable(table)
+ .setName(index)
+ .setUnique(unique);
+ for (ColumnDef column : columns) {
+ builder.addColumn(column);
+ }
+ context.execute(builder.build());
+ }
+
+ private static VarcharColumnDef.Builder newLenientVarcharBuilder(String column) {
+ return new VarcharColumnDef.Builder().setColumnName(column).setIgnoreOracleUnit(true);
+ }
+
+ private CreateTableBuilder newTableBuilder(String tableName) {
+ return new CreateTableBuilder(getDialect(), tableName);
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/DbVersion56.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/DbVersion56.java
new file mode 100644
index 00000000000..c8295486b0d
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/DbVersion56.java
@@ -0,0 +1,32 @@
+/*
+ * 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.platform.db.migration.version.v56;
+
+import org.sonar.server.platform.db.migration.step.MigrationStepRegistry;
+import org.sonar.server.platform.db.migration.version.DbVersion;
+
+public class DbVersion56 implements DbVersion {
+ @Override
+ public void addSteps(MigrationStepRegistry registry) {
+ registry
+ .add(1, "Create initial schema", CreateInitialSchema.class)
+ .add(2, "Populate initial schema", PopulateInitialSchema.class);
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchema.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchema.java
new file mode 100644
index 00000000000..ef48be58073
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchema.java
@@ -0,0 +1,121 @@
+/*
+ * 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.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.server.platform.db.migration.step.DataChange;
+
+public class PopulateInitialSchema extends DataChange {
+
+ private static final String ADMINS_GROUP = "sonar-administrators";
+ private static final String USERS_GROUP = "sonar-users";
+ private static final String ADMIN_USER = "admin";
+
+ private final System2 system2;
+
+ public PopulateInitialSchema(Database db, System2 system2) {
+ super(db);
+ this.system2 = system2;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ insertGroups(context);
+ insertGroupRoles(context);
+ insertAdminUser(context);
+ insertGroupMemberships(context);
+
+ }
+
+ private void insertGroups(Context context) throws SQLException {
+ truncateTable(context, "groups");
+
+ Date now = new Date(system2.now());
+ context.prepareUpsert("insert into groups (name, description, created_at, updated_at) values (?, ?, ?, ?)")
+ .setString(1, ADMINS_GROUP)
+ .setString(2, "System administrators")
+ .setDate(3, now)
+ .setDate(4, now)
+ .addBatch()
+ .setString(1, USERS_GROUP)
+ .setString(2, "Any new users created will automatically join this group")
+ .setDate(3, now)
+ .setDate(4, now)
+ .addBatch()
+ .execute()
+ .commit();
+ }
+
+ private static void insertGroupRoles(Context context) throws SQLException {
+ truncateTable(context, "group_roles");
+
+ // admin group
+ context.prepareUpsert("insert into group_roles (group_id, resource_id, role) values ((select id from groups where name='" + ADMINS_GROUP + "'), null, ?)")
+ .setString(1, "admin").addBatch()
+ .setString(1, "profileadmin").addBatch()
+ .setString(1, "gateadmin").addBatch()
+ .setString(1, "shareDashboard").addBatch()
+ .setString(1, "provisioning").addBatch()
+ .execute()
+ .commit();
+
+ // anyone
+ context.prepareUpsert("insert into group_roles (group_id, resource_id, role) values (null, null, ?)")
+ .setString(1, "scan").addBatch()
+ .setString(1, "provisioning").addBatch()
+ .execute()
+ .commit();
+ }
+
+ private void insertAdminUser(Context context) throws SQLException {
+ truncateTable(context, "users");
+
+ long now = system2.now();
+ context.prepareUpsert("insert into users " +
+ "(login, name, email, external_identity, external_identity_provider, user_local, crypted_password, salt, " +
+ "created_at, updated_at, remember_token, remember_token_expires_at) " +
+ "values ('" + ADMIN_USER + "', 'Administrator', '', 'admin', 'sonarqube', ?, " +
+ "'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', ?, ?, null, null)")
+ .setBoolean(1, true)
+ .setLong(2, now)
+ .setLong(3, now)
+ .execute()
+ .commit();
+ }
+
+ private static void insertGroupMemberships(Context context) throws SQLException {
+ truncateTable(context, "groups_users");
+
+ context.prepareUpsert("insert into groups_users (user_id, group_id) values " +
+ "((select id from users where login='" + ADMIN_USER + "'), (select id from groups where name=?))")
+ .setString(1, ADMINS_GROUP).addBatch()
+ .setString(1, USERS_GROUP).addBatch()
+ .execute()
+ .commit();
+ }
+
+ private static void truncateTable(Context context, String table) throws SQLException {
+ context.prepareUpsert("truncate table " + table).execute().commit();
+ }
+
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/package-info.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/package-info.java
new file mode 100644
index 00000000000..832de3c3198
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v56/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+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/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchemaTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchemaTest.java
new file mode 100644
index 00000000000..61a39f3dae5
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchemaTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.platform.db.migration.version.v56;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CreateInitialSchemaTest {
+
+ @Rule
+ public final DbTester dbTester = DbTester.createForSchema(System2.INSTANCE, CreateInitialSchemaTest.class, "empty.sql");
+
+ private CreateInitialSchema underTest = new CreateInitialSchema(dbTester.database());
+
+ @Test
+ public void creates_tables_on_empty_db() throws Exception {
+ underTest.execute();
+
+ List<String> tables = new ArrayList<>();
+ try (Connection connection = dbTester.openConnection();
+ ResultSet rs = connection.getMetaData().getTables(null, null, null, new String[] {"TABLE"})) {
+
+ while (rs.next()) {
+ tables.add(rs.getString("TABLE_NAME").toLowerCase(Locale.ENGLISH));
+ }
+ }
+ assertThat(tables).containsOnly(
+ "active_dashboards",
+ "active_rules",
+ "active_rule_parameters",
+ "activities",
+ "authors",
+ "ce_activity",
+ "ce_queue",
+ "dashboards",
+ "duplications_index",
+ "events",
+ "file_sources",
+ "groups",
+ "groups_users",
+ "group_roles",
+ "issues",
+ "issue_changes",
+ "issue_filters",
+ "issue_filter_favourites",
+ "loaded_templates",
+ "manual_measures",
+ "measure_filters",
+ "measure_filter_favourites",
+ "metrics",
+ "notifications",
+ "permission_templates",
+ "perm_templates_groups",
+ "perm_templates_users",
+ "projects",
+ "project_links",
+ "project_measures",
+ "project_qprofiles",
+ "properties",
+ "quality_gates",
+ "quality_gate_conditions",
+ "resource_index",
+ "rules",
+ "rules_parameters",
+ "rules_profiles",
+ "snapshots",
+ "users",
+ "user_roles",
+ "user_tokens",
+ "widgets",
+ "widget_properties");
+ }
+
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/DbVersion56Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/DbVersion56Test.java
new file mode 100644
index 00000000000..d62347556e6
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/DbVersion56Test.java
@@ -0,0 +1,47 @@
+/*
+ * 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.platform.db.migration.version.v56;
+
+import org.junit.Test;
+
+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();
+
+ @Test
+ 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/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchemaTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchemaTest.java
new file mode 100644
index 00000000000..5d167c53e49
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchemaTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.platform.db.migration.version.v56;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.stream.Collectors;
+import org.sonar.db.DbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class PopulateInitialSchemaTest {
+
+ private static final long NOW = 1_500L;
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private System2 system2 = mock(System2.class);
+
+ @Rule
+ public DbTester db = DbTester.createForSchema(System2.INSTANCE, PopulateInitialSchemaTest.class, "v56.sql");
+
+ private PopulateInitialSchema underTest = new PopulateInitialSchema(db.database(), system2);
+
+ @Test
+ public void migration_inserts_users_and_groups() throws SQLException {
+ when(system2.now()).thenReturn(NOW);
+
+ underTest.execute();
+
+ verifyGroup("sonar-administrators", "System administrators");
+ verifyGroup("sonar-users", "Any new users created will automatically join this group");
+ verifyRolesOfAdminsGroup();
+ verifyRolesOfUsersGroup();
+ verifyRolesOfAnyone();
+ verifyAdminUser();
+ verifyMembershipOfAdminUser();
+ }
+
+ private void verifyRolesOfAdminsGroup() {
+ List<String> roles = selectRoles("sonar-administrators");
+ assertThat(roles).containsOnly("admin", "profileadmin", "gateadmin", "shareDashboard", "provisioning");
+ }
+
+ private void verifyRolesOfUsersGroup() {
+ assertThat(selectRoles("sonar-users")).isEmpty();
+ }
+
+ private void verifyRolesOfAnyone() {
+ List<Map<String, Object>> rows = db.select("select gr.role as \"role\" " +
+ "from group_roles gr where gr.group_id is null");
+ List<String> roles = rows.stream()
+ .map(row -> (String) row.get("role"))
+ .collect(Collectors.toArrayList());
+ assertThat(roles).containsOnly("provisioning", "scan");
+ }
+
+ private List<String> selectRoles(String groupName) {
+ List<Map<String, Object>> rows = db.select("select gr.role as \"role\" " +
+ "from group_roles gr " +
+ "inner join groups g on gr.group_id = g.id " +
+ "where g.name='" + groupName + "'");
+ return rows.stream()
+ .map(row -> (String) row.get("role"))
+ .collect(Collectors.toArrayList());
+ }
+
+ private void verifyGroup(String expectedName, String expectedDescription) {
+ Map<String, Object> cols = db.selectFirst("select name as \"name\", description as \"description\", " +
+ "created_at as \"created_at\", updated_at as \"updated_at\" " +
+ "from groups where name='" + expectedName + "'");
+ assertThat(cols.get("name")).isEqualTo(expectedName);
+ assertThat(cols.get("description")).isEqualTo(expectedDescription);
+ assertThat(cols.get("created_at")).isNotNull();
+ }
+
+ private void verifyMembershipOfAdminUser() {
+ List<Map<String, Object>> rows = db.select("select g.name as \"groupName\" from groups g " +
+ "inner join groups_users gu on gu.group_id = g.id " +
+ "inner join users u on gu.user_id = u.id " +
+ "where u.login='admin'");
+ List<String> groupNames = rows.stream()
+ .map(row -> (String) row.get("groupName"))
+ .collect(Collectors.toArrayList());
+ assertThat(groupNames).containsOnly("sonar-administrators", "sonar-users");
+ }
+
+ private void verifyAdminUser() {
+ Map<String, Object> cols = db.selectFirst("select login as \"login\", name as \"name\", email as \"email\", " +
+ "external_identity as \"external_identity\", external_identity_provider as \"external_identity_provider\", " +
+ "user_local as \"user_local\", crypted_password as \"crypted_password\", salt as \"salt\", created_at as \"created_at\", " +
+ "updated_at as \"updated_at\", remember_token as \"remember_token\", remember_token_expires_at as \"remember_token_expires_at\" " +
+ "from users where login='admin'");
+ assertThat(cols.get("login")).isEqualTo("admin");
+ assertThat(cols.get("name")).isEqualTo("Administrator");
+ assertThat(cols.get("email")).isEqualTo("");
+ assertThat(cols.get("user_local")).isEqualTo(true);
+ assertThat(cols.get("crypted_password")).isEqualTo("a373a0e667abb2604c1fd571eb4ad47fe8cc0878");
+ assertThat(cols.get("salt")).isEqualTo("48bc4b0d93179b5103fd3885ea9119498e9d161b");
+ assertThat(cols.get("created_at")).isEqualTo(NOW);
+ assertThat(cols.get("updated_at")).isEqualTo(NOW);
+ assertThat(cols.get("remember_token")).isNull();
+ assertThat(cols.get("remember_token_expires_at")).isNull();
+ }
+
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchemaTest/empty.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchemaTest/empty.sql
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v56/CreateInitialSchemaTest/empty.sql
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchemaTest/v56.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchemaTest/v56.sql
new file mode 100644
index 00000000000..d0c61c969ac
--- /dev/null
+++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchemaTest/v56.sql
@@ -0,0 +1,47 @@
+CREATE TABLE "GROUPS_USERS" (
+ "USER_ID" INTEGER,
+ "GROUP_ID" INTEGER
+);
+CREATE INDEX "INDEX_GROUPS_USERS_ON_GROUP_ID" ON "GROUPS_USERS" ("GROUP_ID");
+CREATE INDEX "INDEX_GROUPS_USERS_ON_USER_ID" ON "GROUPS_USERS" ("USER_ID");
+CREATE UNIQUE INDEX "GROUPS_USERS_UNIQUE" ON "GROUPS_USERS" ("GROUP_ID", "USER_ID");
+
+
+CREATE TABLE "GROUPS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "NAME" VARCHAR(500),
+ "DESCRIPTION" VARCHAR(200),
+ "CREATED_AT" TIMESTAMP,
+ "UPDATED_AT" TIMESTAMP
+);
+
+
+CREATE TABLE "GROUP_ROLES" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "GROUP_ID" INTEGER,
+ "RESOURCE_ID" INTEGER,
+ "ROLE" VARCHAR(64) NOT NULL
+);
+CREATE UNIQUE INDEX "UNIQ_GROUP_ROLES" ON "GROUP_ROLES" ("GROUP_ID", "RESOURCE_ID", "ROLE");
+CREATE INDEX "GROUP_ROLES_RESOURCE" ON "GROUP_ROLES" ("RESOURCE_ID");
+
+
+CREATE TABLE "USERS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "LOGIN" VARCHAR(255),
+ "NAME" VARCHAR(200),
+ "EMAIL" VARCHAR(100),
+ "CRYPTED_PASSWORD" VARCHAR(40),
+ "SALT" VARCHAR(40),
+ "REMEMBER_TOKEN" VARCHAR(500),
+ "REMEMBER_TOKEN_EXPIRES_AT" TIMESTAMP,
+ "ACTIVE" BOOLEAN DEFAULT TRUE,
+ "SCM_ACCOUNTS" VARCHAR(4000),
+ "EXTERNAL_IDENTITY" VARCHAR(255),
+ "EXTERNAL_IDENTITY_PROVIDER" VARCHAR(100),
+ "USER_LOCAL" BOOLEAN,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT
+);
+CREATE UNIQUE INDEX "USERS_LOGIN" ON "USERS" ("LOGIN");
+CREATE INDEX "USERS_UPDATED_AT" ON "USERS" ("UPDATED_AT");
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