]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7692 change table resource_index to use project uuids
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 6 Jun 2016 15:12:38 +0000 (17:12 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 13 Jun 2016 06:45:48 +0000 (08:45 +0200)
28 files changed:
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1201_add_columns_with_uuids_to_resource_index.rb [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1202_populate_uuid_columns_of_resource_index.rb [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1203_clean_orphan_rows_in_resource_index.rb [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1204_make_uuid_columns_not_null_on_resource_index.rb [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1205_drop_resource_index_rid_from_resource_index.rb [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1206_drop_id_columns_from_resource_index.rb [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java
sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java
sonar-db/src/main/java/org/sonar/db/version/VarcharColumnDef.java
sonar-db/src/main/java/org/sonar/db/version/v60/AddUuidColumnsToResourceIndex.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/version/v60/CleanOrphanRowsInResourceIndex.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/version/v60/DropIdColumnsFromResourceIndex.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/version/v60/MakeUuidColumnsNotNullOnResourceIndex.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/version/v60/PopulateUuidColumnsOfResourceIndex.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/version/v60/package-info.java [new file with mode: 0644]
sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql
sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl
sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java
sonar-db/src/test/java/org/sonar/db/version/v60/AddUuidColumnsToResourceIndexTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/version/v60/CleanOrphanRowsInResourceIndexTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/version/v60/DropIdColumnsFromResourceIndexTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/version/v60/MakeUuidColumnsNotNullOnResourceIndexTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/version/v60/PopulateUuidColumnsOfResourceIndexTest.java [new file with mode: 0644]
sonar-db/src/test/resources/org/sonar/db/version/v60/AddUuidColumnsToResourceIndexTest/old_resourceindex.sql [new file with mode: 0644]
sonar-db/src/test/resources/org/sonar/db/version/v60/CleanOrphanRowsInResourceIndexTest/in_progress_resourceindex.sql [new file with mode: 0644]
sonar-db/src/test/resources/org/sonar/db/version/v60/DropIdColumnsFromResourceIndexTest/in_progress_resourceindex.sql [new file with mode: 0644]
sonar-db/src/test/resources/org/sonar/db/version/v60/MakeUuidColumnsNotNullOnResourceIndexTest/in_progress_resourceindex.sql [new file with mode: 0644]
sonar-db/src/test/resources/org/sonar/db/version/v60/PopulateUuidColumnsOfResourceIndexTest/in_progress_resourceindex_with_projects.sql [new file with mode: 0644]

diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1201_add_columns_with_uuids_to_resource_index.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1201_add_columns_with_uuids_to_resource_index.rb
new file mode 100644 (file)
index 0000000..a4e23b0
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+
+#
+# SonarQube 6.0
+#
+class AddColumnsWithUuidsToResourceIndex < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.AddUuidColumnsToResourceIndex')
+  end
+end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1202_populate_uuid_columns_of_resource_index.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1202_populate_uuid_columns_of_resource_index.rb
new file mode 100644 (file)
index 0000000..46d47a2
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+
+#
+# SonarQube 6.0
+#
+class PopulateUuidColumnsOfResourceIndex < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.PopulateUuidColumnsOfResourceIndex')
+  end
+end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1203_clean_orphan_rows_in_resource_index.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1203_clean_orphan_rows_in_resource_index.rb
new file mode 100644 (file)
index 0000000..fff5fe0
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+
+#
+# SonarQube 6.0
+#
+class CleanOrphanRowsInResourceIndex < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.CleanOrphanRowsInResourceIndex')
+  end
+end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1204_make_uuid_columns_not_null_on_resource_index.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1204_make_uuid_columns_not_null_on_resource_index.rb
new file mode 100644 (file)
index 0000000..e1e9d7d
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+
+#
+# SonarQube 6.0
+#
+class MakeUuidColumnsNotNullOnResourceIndex < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.MakeUuidColumnsNotNullOnResourceIndex')
+
+    add_index :resource_index, :component_uuid, :name => 'resource_index_component'
+  end
+end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1205_drop_resource_index_rid_from_resource_index.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1205_drop_resource_index_rid_from_resource_index.rb
new file mode 100644 (file)
index 0000000..e44007e
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+
+#
+# SonarQube 6.0
+#
+class DropResourceIndexRidFromResourceIndex < ActiveRecord::Migration
+
+  def self.up
+    remove_index :resource_index, :name => 'resource_index_rid'
+  end
+end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1206_drop_id_columns_from_resource_index.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1206_drop_id_columns_from_resource_index.rb
new file mode 100644 (file)
index 0000000..08a0ebd
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+
+#
+# SonarQube 6.0
+#
+class DropIdColumnsFromResourceIndex < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.DropIdColumnsFromResourceIndex')
+  end
+end
index c6d0c3ea08fc035fc36314e151f2e0314bb143ef..92a8efd43bbb13603240b8da45a6a031e606b998 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.db.MyBatis;
 
 public class DatabaseVersion {
 
-  public static final int LAST_VERSION = 1_200;
+  public static final int LAST_VERSION = 1_206;
 
   /**
    * The minimum supported version which can be upgraded. Lower
index 2dcaea78e4ce26ebd9fb9faa199b14f58d46d4ad..31a7dfe683edbbdd11e4f88e25a11f023bb04a6a 100644 (file)
@@ -83,6 +83,11 @@ import org.sonar.db.version.v55.FeedRulesLongDateColumns;
 import org.sonar.db.version.v55.FeedRulesTypes;
 import org.sonar.db.version.v56.FixLengthOfIssuesMessageOnOracle;
 import org.sonar.db.version.v56.FixTypeOfRuleTypeOnMysql;
+import org.sonar.db.version.v60.AddUuidColumnsToResourceIndex;
+import org.sonar.db.version.v60.CleanOrphanRowsInResourceIndex;
+import org.sonar.db.version.v60.DropIdColumnsFromResourceIndex;
+import org.sonar.db.version.v60.MakeUuidColumnsNotNullOnResourceIndex;
+import org.sonar.db.version.v60.PopulateUuidColumnsOfResourceIndex;
 
 public class MigrationStepModule extends Module {
   @Override
@@ -165,6 +170,13 @@ public class MigrationStepModule extends Module {
 
       // 5.6
       FixTypeOfRuleTypeOnMysql.class,
-      FixLengthOfIssuesMessageOnOracle.class);
+      FixLengthOfIssuesMessageOnOracle.class,
+
+      // 6.0
+      AddUuidColumnsToResourceIndex.class,
+      PopulateUuidColumnsOfResourceIndex.class,
+      CleanOrphanRowsInResourceIndex.class,
+      MakeUuidColumnsNotNullOnResourceIndex.class,
+      DropIdColumnsFromResourceIndex.class);
   }
 }
index 83052bb83d0e6a5eaf613cc9dded2c864f5e5724..71c77a0cd1feac5d9eafa5cceda700545abc0e52 100644 (file)
@@ -31,6 +31,8 @@ import static org.sonar.db.version.ColumnDefValidation.validateColumnName;
  * Used to define VARCHAR column
  */
 public class VarcharColumnDef extends AbstractColumnDef {
+  public static final int UUID_VARCHAR_SIZE = 50;
+
   private final int columnSize;
 
   private VarcharColumnDef(Builder builder) {
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/AddUuidColumnsToResourceIndex.java b/sonar-db/src/main/java/org/sonar/db/version/v60/AddUuidColumnsToResourceIndex.java
new file mode 100644 (file)
index 0000000..784db31
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.version.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;
+
+public class AddUuidColumnsToResourceIndex extends DdlChange {
+
+  private static final String TABLE_RESOURCE_INDEX = "resource_index";
+
+  private final Database db;
+
+  public AddUuidColumnsToResourceIndex(Database db) {
+    super(db);
+    this.db = db;
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new AddColumnsBuilder(db.getDialect(), TABLE_RESOURCE_INDEX)
+      .addColumn(newVarcharColumnDefBuilder().setColumnName("component_uuid").setLimit(UUID_VARCHAR_SIZE).setIsNullable(true).build())
+      .addColumn(newVarcharColumnDefBuilder().setColumnName("root_component_uuid").setLimit(UUID_VARCHAR_SIZE).setIsNullable(true).build())
+      .build());
+  }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/CleanOrphanRowsInResourceIndex.java b/sonar-db/src/main/java/org/sonar/db/version/v60/CleanOrphanRowsInResourceIndex.java
new file mode 100644 (file)
index 0000000..e059448
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.version.BaseDataChange;
+import org.sonar.db.version.MassUpdate;
+
+public class CleanOrphanRowsInResourceIndex extends BaseDataChange {
+
+  public CleanOrphanRowsInResourceIndex(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    MassUpdate massUpdate = context.prepareMassUpdate();
+    massUpdate.select("SELECT ri.id, ri.resource_id, ri.root_project_id from resource_index ri where ri.component_uuid is null or ri.root_component_uuid is null");
+    massUpdate.update("DELETE from resource_index WHERE id=?");
+    massUpdate.rowPluralName("resource index entries");
+    massUpdate.execute((row, update) -> {
+      update.setLong(1, row.getLong(1));
+      return true;
+    });
+  }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/DropIdColumnsFromResourceIndex.java b/sonar-db/src/main/java/org/sonar/db/version/v60/DropIdColumnsFromResourceIndex.java
new file mode 100644 (file)
index 0000000..f7fe94c
--- /dev/null
@@ -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.db.version.v60;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.version.DdlChange;
+import org.sonar.db.version.DropColumnsBuilder;
+
+public class DropIdColumnsFromResourceIndex extends DdlChange {
+
+  private static final String TABLE_RESOURCE_INDEX = "resource_index";
+
+  private final Database db;
+
+  public DropIdColumnsFromResourceIndex(Database db) {
+    super(db);
+    this.db = db;
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(
+      new DropColumnsBuilder(
+        db.getDialect(), TABLE_RESOURCE_INDEX,
+        "resource_id", "root_project_id")
+          .build());
+  }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/MakeUuidColumnsNotNullOnResourceIndex.java b/sonar-db/src/main/java/org/sonar/db/version/v60/MakeUuidColumnsNotNullOnResourceIndex.java
new file mode 100644 (file)
index 0000000..16e01b3
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.version.AlterColumnsTypeBuilder;
+import org.sonar.db.version.DdlChange;
+
+import static org.sonar.db.version.VarcharColumnDef.UUID_VARCHAR_SIZE;
+import static org.sonar.db.version.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class MakeUuidColumnsNotNullOnResourceIndex extends DdlChange {
+
+  private static final String TABLE_RESOURCE_INDEX = "resource_index";
+
+  private final Database db;
+
+  public MakeUuidColumnsNotNullOnResourceIndex(Database db) {
+    super(db);
+    this.db = db;
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new AlterColumnsTypeBuilder(db.getDialect(), TABLE_RESOURCE_INDEX)
+      .updateColumn(newVarcharColumnDefBuilder().setColumnName("component_uuid").setLimit(UUID_VARCHAR_SIZE).setIsNullable(false).build())
+      .updateColumn(newVarcharColumnDefBuilder().setColumnName("root_component_uuid").setLimit(UUID_VARCHAR_SIZE).setIsNullable(false).build())
+      .build());
+  }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/PopulateUuidColumnsOfResourceIndex.java b/sonar-db/src/main/java/org/sonar/db/version/v60/PopulateUuidColumnsOfResourceIndex.java
new file mode 100644 (file)
index 0000000..e5be59b
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import org.sonar.db.Database;
+import org.sonar.db.version.BaseDataChange;
+import org.sonar.db.version.MassUpdate;
+import org.sonar.db.version.Select;
+import org.sonar.db.version.SqlStatement;
+
+public class PopulateUuidColumnsOfResourceIndex extends BaseDataChange {
+
+  public PopulateUuidColumnsOfResourceIndex(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    Map<Long, String> componentUuidById = buildComponentUuidMap(context);
+    if (componentUuidById.isEmpty()) {
+      return;
+    }
+
+    populateUuidColumns(context, componentUuidById);
+  }
+
+  private Map<Long, String> buildComponentUuidMap(Context context) throws SQLException {
+    Map<Long, String> componentUuidById = new HashMap<>();
+    context.prepareSelect("select distinct p.id, p.uuid from projects p" +
+      " join resource_index ri1 on ri1.resource_id = p.id and ri1.component_uuid is null")
+      .scroll(row -> componentUuidById.put(row.getLong(1), row.getString(2)));
+    context.prepareSelect("select distinct p.id, p.uuid from projects p" +
+      " join resource_index ri2 on ri2.root_project_id = p.id and ri2.root_component_uuid is null")
+      .scroll(row -> componentUuidById.put(row.getLong(1), row.getString(2)));
+    return componentUuidById;
+  }
+
+  private void populateUuidColumns(Context context, Map<Long, String> componentUuidById) throws SQLException {
+    MassUpdate massUpdate = context.prepareMassUpdate();
+    massUpdate.select("SELECT ri.id, ri.resource_id, ri.root_project_id from resource_index ri where ri.component_uuid is null or ri.root_component_uuid is null");
+    massUpdate.update("UPDATE resource_index SET component_uuid=?, root_component_uuid=? WHERE id=?");
+    massUpdate.rowPluralName("resource index entries");
+    massUpdate.execute((row, update) -> this.handle(componentUuidById, row, update));
+  }
+
+  public boolean handle(Map<Long, String> componentUuidById, Select.Row row, SqlStatement update) throws SQLException {
+    long id = row.getLong(1);
+    long componentId = row.getLong(2);
+    long rootProjectId = row.getLong(3);
+
+    String componentUuid = componentUuidById.get(componentId);
+    String rootComponentUuid = componentUuidById.get(rootProjectId);
+
+    if (componentUuid == null && rootComponentUuid == null) {
+      return false;
+    }
+
+    update.setString(1, componentUuid);
+    update.setString(2, rootComponentUuid);
+    update.setLong(3, id);
+
+    return true;
+  }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/package-info.java b/sonar-db/src/main/java/org/sonar/db/version/v60/package-info.java
new file mode 100644 (file)
index 0000000..4b742e6
--- /dev/null
@@ -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.db.version.v60;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
index c7c52e0b3327636796e6c7eb2919aa3f054eeb11..aa808f28acb891d16f59d44fbdd93d3486810146 100644 (file)
@@ -407,6 +407,12 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1151');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1152');
 
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1200');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1201');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1202');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1203');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1204');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1205');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1206');
 
 INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, EXTERNAL_IDENTITY, EXTERNAL_IDENTITY_PROVIDER, USER_LOCAL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'admin', 'sonarqube', true, 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '1418215735482', '1418215735482', null, null);
 ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
index d888aacbd4117e84990278a9d30656299f2cf85c..66739471b15a5b625979c4bc737ea337dfbc6767 100644 (file)
@@ -350,8 +350,8 @@ CREATE TABLE "RESOURCE_INDEX" (
   "KEE" VARCHAR(400) NOT NULL,
   "POSITION" INTEGER NOT NULL,
   "NAME_SIZE" INTEGER NOT NULL,
-  "RESOURCE_ID" INTEGER NOT NULL,
-  "ROOT_PROJECT_ID" INTEGER NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+  "ROOT_COMPONENT_UUID" VARCHAR(50) NOT NULL,
   "QUALIFIER" VARCHAR(10) NOT NULL
 );
 
@@ -614,7 +614,7 @@ CREATE INDEX "PROJECTS_QUALIFIER" ON "PROJECTS" ("QUALIFIER");
 
 CREATE INDEX "RESOURCE_INDEX_KEY" ON "RESOURCE_INDEX" ("KEE");
 
-CREATE INDEX "RESOURCE_INDEX_RID" ON "RESOURCE_INDEX" ("RESOURCE_ID");
+CREATE INDEX "RESOURCE_INDEX_COMPONENT" ON "RESOURCE_INDEX" ("COMPONENT_UUID");
 
 CREATE UNIQUE INDEX "UNIQ_AUTHOR_LOGINS" ON "AUTHORS" ("LOGIN");
 
index 91bda96d3de5462b16882e5d320df004b6661097..b5d866175026ac0add4ee3344315c854a74cf307 100644 (file)
@@ -29,6 +29,6 @@ public class MigrationStepModuleTest {
   public void verify_count_of_added_MigrationStep_types() {
     ComponentContainer container = new ComponentContainer();
     new MigrationStepModule().configure(container);
-    assertThat(container.size()).isEqualTo(65);
+    assertThat(container.size()).isEqualTo(70);
   }
 }
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/AddUuidColumnsToResourceIndexTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/AddUuidColumnsToResourceIndexTest.java
new file mode 100644 (file)
index 0000000..9fcd6a4
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+import static java.lang.String.valueOf;
+
+public class AddUuidColumnsToResourceIndexTest {
+
+  @Rule
+  public DbTester db = DbTester.createForSchema(System2.INSTANCE, AddUuidColumnsToResourceIndexTest.class, "old_resourceindex.sql");
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private AddUuidColumnsToResourceIndex underTest = new AddUuidColumnsToResourceIndex(db.database());
+
+  @Test
+  public void migration_adds_columns_to_empty_table() throws SQLException {
+    underTest.execute();
+
+    verifyAddedColumns();
+  }
+
+  @Test
+  public void migration_adds_columns_to_populated_table() throws SQLException {
+    for (int i = 0; i < 9; i++) {
+      db.executeInsert(
+        "resource_index",
+        "KEE", "key_" + i,
+        "POSITION", valueOf(i),
+        "NAME_SIZE", valueOf(i + 1),
+        "RESOURCE_ID", valueOf(i + 10),
+        "ROOT_PROJECT_ID", valueOf(i + 20),
+        "QUALIFIER", (i % 2 == 0 ? "FILE" : "PROJECT"));
+    }
+    db.commit();
+
+    underTest.execute();
+
+    verifyAddedColumns();
+  }
+
+  private void verifyAddedColumns() {
+    db.assertColumnDefinition("resource_index", "component_uuid", Types.VARCHAR, 50, true);
+    db.assertColumnDefinition("resource_index", "root_component_uuid", Types.VARCHAR, 50, true);
+  }
+
+  @Test
+  public void migration_is_not_reentrant() throws SQLException {
+    underTest.execute();
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Fail to execute ");
+    underTest.execute();
+  }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/CleanOrphanRowsInResourceIndexTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/CleanOrphanRowsInResourceIndexTest.java
new file mode 100644 (file)
index 0000000..ec42a13
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+import static java.lang.String.valueOf;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CleanOrphanRowsInResourceIndexTest {
+
+  @Rule
+  public DbTester db = DbTester.createForSchema(System2.INSTANCE, CleanOrphanRowsInResourceIndexTest.class,
+    "in_progress_resourceindex.sql");
+
+  private CleanOrphanRowsInResourceIndex underTest = new CleanOrphanRowsInResourceIndex(db.database());
+
+  @Test
+  public void migration_has_no_effect_on_empty_table() throws SQLException {
+    underTest.execute();
+
+    assertThat(db.countRowsOfTable("resource_index")).isEqualTo(0);
+  }
+
+  @Test
+  public void migration_deletes_any_row_with_a_null_uuid() throws SQLException {
+    insertResourceIndex(1, true, true);
+    insertResourceIndex(2, false, false);
+    insertResourceIndex(3, true, false);
+    insertResourceIndex(4, false, true);
+    insertResourceIndex(5, true, true);
+    db.commit();
+
+    underTest.execute();
+
+    assertThat(idsOfRowsInResourceIndex()).containsOnly(1l, 5l);
+  }
+
+  @Test
+  public void migration_is_reentrant() throws SQLException {
+    insertResourceIndex(1, true, true);
+    insertResourceIndex(2, false, false);
+
+    underTest.execute();
+
+    assertThat(idsOfRowsInResourceIndex()).containsOnly(1l);
+
+    underTest.execute();
+
+    assertThat(idsOfRowsInResourceIndex()).containsOnly(1l);
+  }
+
+  private List<Long> idsOfRowsInResourceIndex() {
+    return db.select("select ID from resource_index").stream().map(map -> (Long) map.get("ID")).collect(Collectors.toList());
+  }
+
+  private void insertResourceIndex(long id, boolean hasComponentUiid, boolean hasRootComponentUuid) {
+    db.executeInsert(
+      "resource_index",
+      "ID", valueOf(id),
+      "KEE", "key_" + id,
+      "POSITION", valueOf(id + 100),
+      "NAME_SIZE", valueOf(id + 1000),
+      "RESOURCE_ID", valueOf(id + 300),
+      "ROOT_PROJECT_ID", valueOf(id + 4000),
+      "QUALIFIER", "PROJECT");
+
+    if (hasComponentUiid) {
+      db.executeUpdateSql("update resource_index set COMPONENT_UUID=? where id=?", "uuid_" + id, valueOf(id));
+    }
+    if (hasRootComponentUuid) {
+      db.executeUpdateSql("update resource_index set ROOT_COMPONENT_UUID=? where id=?", "root_uuid_" + id, valueOf(id));
+    }
+  }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/DropIdColumnsFromResourceIndexTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/DropIdColumnsFromResourceIndexTest.java
new file mode 100644 (file)
index 0000000..c28670e
--- /dev/null
@@ -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.db.version.v60;
+
+import java.sql.SQLException;
+import org.junit.Test;
+import org.sonar.db.Database;
+import org.sonar.db.dialect.PostgreSql;
+import org.sonar.db.version.DdlChange;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class DropIdColumnsFromResourceIndexTest {
+
+  private Database database = mock(Database.class);
+
+  private DropIdColumnsFromResourceIndex underTest = new DropIdColumnsFromResourceIndex(database);
+
+  @Test
+  public void verify_generated_sql_on_postgresql() throws SQLException {
+    when(database.getDialect()).thenReturn(new PostgreSql());
+
+    DdlChange.Context context = mock(DdlChange.Context.class);
+    underTest.execute(context);
+
+    verify(context).execute("ALTER TABLE resource_index DROP COLUMN resource_id, DROP COLUMN root_project_id");
+  }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/MakeUuidColumnsNotNullOnResourceIndexTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/MakeUuidColumnsNotNullOnResourceIndexTest.java
new file mode 100644 (file)
index 0000000..f60e308
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+import static java.lang.String.valueOf;
+
+public class MakeUuidColumnsNotNullOnResourceIndexTest {
+
+  @Rule
+  public DbTester db = DbTester.createForSchema(System2.INSTANCE, MakeUuidColumnsNotNullOnResourceIndexTest.class,
+      "in_progress_resourceindex.sql");
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private MakeUuidColumnsNotNullOnResourceIndex underTest = new MakeUuidColumnsNotNullOnResourceIndex(db.database());
+
+  @Test
+  public void migration_sets_uuid_columns_not_nullable_on_empty_table() throws SQLException {
+    underTest.execute();
+
+    verifyColumnDefinitions();
+  }
+
+  @Test
+  public void migration_sets_uuid_columns_not_nullable_on_populated_table() throws SQLException {
+    insertResourceIndex(1, true, true);
+    insertResourceIndex(2, true, true);
+
+    underTest.execute();
+
+    verifyColumnDefinitions();
+  }
+
+  @Test
+  public void migration_fails_if_some_uuid_columns_are_null() throws SQLException {
+    insertResourceIndex(1, false, true);
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Fail to execute");
+
+    underTest.execute();
+  }
+
+  private void verifyColumnDefinitions() {
+    db.assertColumnDefinition("resource_index", "component_uuid", Types.VARCHAR, 50, false);
+    db.assertColumnDefinition("resource_index", "root_component_uuid", Types.VARCHAR, 50, false);
+  }
+
+  private void insertResourceIndex(long id, boolean hasComponentUiid, boolean hasRootComponentUuid) {
+    db.executeInsert(
+        "resource_index",
+        "ID", valueOf(id),
+        "KEE", "key_" + id,
+        "POSITION", valueOf(id + 100),
+        "NAME_SIZE", valueOf(id + 1000),
+        "RESOURCE_ID", valueOf(id + 300),
+        "ROOT_PROJECT_ID", valueOf(id + 4000),
+        "QUALIFIER", "PROJECT");
+
+    if (hasComponentUiid) {
+      db.executeUpdateSql("update resource_index set COMPONENT_UUID=? where id=?", "uuid_" + id, valueOf(id));
+    }
+    if (hasRootComponentUuid) {
+      db.executeUpdateSql("update resource_index set ROOT_COMPONENT_UUID=? where id=?", "root_uuid_" + id, valueOf(id));
+    }
+  }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/PopulateUuidColumnsOfResourceIndexTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/PopulateUuidColumnsOfResourceIndexTest.java
new file mode 100644 (file)
index 0000000..b5b24d2
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+import static java.lang.String.valueOf;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PopulateUuidColumnsOfResourceIndexTest {
+
+  @Rule
+  public DbTester db = DbTester.createForSchema(System2.INSTANCE, PopulateUuidColumnsOfResourceIndexTest.class,
+    "in_progress_resourceindex_with_projects.sql");
+
+  private PopulateUuidColumnsOfResourceIndex underTest = new PopulateUuidColumnsOfResourceIndex(db.database());
+
+  @Test
+  public void migration_has_no_effect_on_empty_tables() throws SQLException {
+    underTest.execute();
+
+    assertThat(db.countRowsOfTable("resource_index")).isEqualTo(0);
+    assertThat(db.countRowsOfTable("projects")).isEqualTo(0);
+  }
+
+  @Test
+  public void migration_updates_uuid_columns_with_values_from_table_projects_when_they_exist() throws SQLException {
+    String uuid1 = insertComponent(40);
+    String uuid2 = insertComponent(50);
+    String uuid3 = insertComponent(60);
+    String uuid4 = insertComponent(70);
+
+    insertResourceIndex(1, 40, 50);
+    insertResourceIndex(2, 60, 70);
+    insertResourceIndex(3, 90, 70); // 90 does not exist
+    insertResourceIndex(4, 40, 100); // 100 does not exist
+    insertResourceIndex(5, 110, 100); // 110 and 100 do not exist
+    db.commit();
+
+    underTest.execute();
+
+    verifyResourceIndex(1, 40, uuid1, 50, uuid2);
+    verifyResourceIndex(2, 60, uuid3, 70, uuid4);
+    verifyResourceIndex(3, 90, null, 70, uuid4);
+    verifyResourceIndex(4, 40, uuid1, 100, null);
+    verifyResourceIndex(5, 110, null, 100, null);
+  }
+
+  @Test
+  public void migration_is_reentrant() throws SQLException {
+    String uuid1 = insertComponent(40);
+    String uuid2 = insertComponent(50);
+    insertResourceIndex(1, 40, 50);
+
+    underTest.execute();
+    verifyResourceIndex(1, 40, uuid1, 50, uuid2);
+
+    underTest.execute();
+    verifyResourceIndex(1, 40, uuid1, 50, uuid2);
+
+  }
+
+  private void verifyResourceIndex(long id, long resourceId, @Nullable String componentUuid, long rootProjectId, @Nullable String rootComponentUuid) {
+    List<Map<String, Object>> rows = db.select("select RESOURCE_ID, COMPONENT_UUID, ROOT_PROJECT_ID, ROOT_COMPONENT_UUID from resource_index where ID=" + id);
+    assertThat(rows).hasSize(1);
+    Map<String, Object> row = rows.get(0);
+    assertThat(row.get("RESOURCE_ID")).isEqualTo(resourceId);
+    assertThat(row.get("COMPONENT_UUID")).isEqualTo(componentUuid);
+    assertThat(row.get("ROOT_PROJECT_ID")).isEqualTo(rootProjectId);
+    assertThat(row.get("ROOT_COMPONENT_UUID")).isEqualTo(rootComponentUuid);
+  }
+
+  private String insertComponent(long id) {
+    String uuid = "uuid_" + id;
+    db.executeInsert(
+      "projects",
+      "ID", valueOf(id),
+      "UUID", uuid);
+    return uuid;
+  }
+
+  private void insertResourceIndex(long id, long resourceId, long rootProjectId) {
+    db.executeInsert(
+      "resource_index",
+      "ID", valueOf(id),
+      "KEE", "key_" + id,
+      "POSITION", valueOf(id + 100),
+      "NAME_SIZE", valueOf(id + 1000),
+      "RESOURCE_ID", valueOf(resourceId),
+      "ROOT_PROJECT_ID", valueOf(rootProjectId),
+      "QUALIFIER", "PROJECT");
+  }
+}
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v60/AddUuidColumnsToResourceIndexTest/old_resourceindex.sql b/sonar-db/src/test/resources/org/sonar/db/version/v60/AddUuidColumnsToResourceIndexTest/old_resourceindex.sql
new file mode 100644 (file)
index 0000000..6037299
--- /dev/null
@@ -0,0 +1,9 @@
+CREATE TABLE "RESOURCE_INDEX" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "KEE" VARCHAR(400) NOT NULL,
+  "POSITION" INTEGER NOT NULL,
+  "NAME_SIZE" INTEGER NOT NULL,
+  "RESOURCE_ID" INTEGER NOT NULL,
+  "ROOT_PROJECT_ID" INTEGER NOT NULL,
+  "QUALIFIER" VARCHAR(10) NOT NULL
+);
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v60/CleanOrphanRowsInResourceIndexTest/in_progress_resourceindex.sql b/sonar-db/src/test/resources/org/sonar/db/version/v60/CleanOrphanRowsInResourceIndexTest/in_progress_resourceindex.sql
new file mode 100644 (file)
index 0000000..aab2040
--- /dev/null
@@ -0,0 +1,12 @@
+CREATE TABLE "RESOURCE_INDEX" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "KEE" VARCHAR(400) NOT NULL,
+  "POSITION" INTEGER NOT NULL,
+  "NAME_SIZE" INTEGER NOT NULL,
+  "RESOURCE_ID" INTEGER NOT NULL,
+  "ROOT_PROJECT_ID" INTEGER NOT NULL,
+  "QUALIFIER" VARCHAR(10) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50),
+  "ROOT_COMPONENT_UUID" VARCHAR(50)
+);
+
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v60/DropIdColumnsFromResourceIndexTest/in_progress_resourceindex.sql b/sonar-db/src/test/resources/org/sonar/db/version/v60/DropIdColumnsFromResourceIndexTest/in_progress_resourceindex.sql
new file mode 100644 (file)
index 0000000..aab2040
--- /dev/null
@@ -0,0 +1,12 @@
+CREATE TABLE "RESOURCE_INDEX" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "KEE" VARCHAR(400) NOT NULL,
+  "POSITION" INTEGER NOT NULL,
+  "NAME_SIZE" INTEGER NOT NULL,
+  "RESOURCE_ID" INTEGER NOT NULL,
+  "ROOT_PROJECT_ID" INTEGER NOT NULL,
+  "QUALIFIER" VARCHAR(10) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50),
+  "ROOT_COMPONENT_UUID" VARCHAR(50)
+);
+
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v60/MakeUuidColumnsNotNullOnResourceIndexTest/in_progress_resourceindex.sql b/sonar-db/src/test/resources/org/sonar/db/version/v60/MakeUuidColumnsNotNullOnResourceIndexTest/in_progress_resourceindex.sql
new file mode 100644 (file)
index 0000000..aab2040
--- /dev/null
@@ -0,0 +1,12 @@
+CREATE TABLE "RESOURCE_INDEX" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "KEE" VARCHAR(400) NOT NULL,
+  "POSITION" INTEGER NOT NULL,
+  "NAME_SIZE" INTEGER NOT NULL,
+  "RESOURCE_ID" INTEGER NOT NULL,
+  "ROOT_PROJECT_ID" INTEGER NOT NULL,
+  "QUALIFIER" VARCHAR(10) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50),
+  "ROOT_COMPONENT_UUID" VARCHAR(50)
+);
+
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v60/PopulateUuidColumnsOfResourceIndexTest/in_progress_resourceindex_with_projects.sql b/sonar-db/src/test/resources/org/sonar/db/version/v60/PopulateUuidColumnsOfResourceIndexTest/in_progress_resourceindex_with_projects.sql
new file mode 100644 (file)
index 0000000..2551ca9
--- /dev/null
@@ -0,0 +1,34 @@
+CREATE TABLE "RESOURCE_INDEX" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "KEE" VARCHAR(400) NOT NULL,
+  "POSITION" INTEGER NOT NULL,
+  "NAME_SIZE" INTEGER NOT NULL,
+  "RESOURCE_ID" INTEGER NOT NULL,
+  "ROOT_PROJECT_ID" INTEGER NOT NULL,
+  "QUALIFIER" VARCHAR(10) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50),
+  "ROOT_COMPONENT_UUID" VARCHAR(50)
+);
+
+CREATE TABLE "PROJECTS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "KEE" VARCHAR(400),
+  "ROOT_ID" INTEGER,
+  "UUID" VARCHAR(50),
+  "PROJECT_UUID" VARCHAR(50),
+  "MODULE_UUID" VARCHAR(50),
+  "MODULE_UUID_PATH" VARCHAR(4000),
+  "NAME" VARCHAR(2000),
+  "DESCRIPTION" VARCHAR(2000),
+  "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
+  "SCOPE" VARCHAR(3),
+  "QUALIFIER" VARCHAR(10),
+  "DEPRECATED_KEE" VARCHAR(400),
+  "PATH" VARCHAR(2000),
+  "LANGUAGE" VARCHAR(20),
+  "COPY_RESOURCE_ID" INTEGER,
+  "LONG_NAME" VARCHAR(2000),
+  "PERSON_ID" INTEGER,
+  "CREATED_AT" TIMESTAMP,
+  "AUTHORIZATION_UPDATED_AT" BIGINT
+);