]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7649 do not repair db collation outside migration
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Wed, 18 May 2016 14:02:12 +0000 (16:02 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 19 May 2016 13:35:58 +0000 (15:35 +0200)
19 files changed:
server/sonar-server/src/main/java/org/sonar/server/db/CheckDatabaseCharsetAfterMigration.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/db/CheckDatabaseCharsetAtStartup.java
server/sonar-server/src/main/java/org/sonar/server/db/CheckDatabaseCollationDuringMigration.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel3.java
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java
server/sonar-server/src/test/java/org/sonar/server/db/CheckDatabaseCharsetAfterMigrationTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/db/CheckDatabaseCharsetAtStartupTest.java
server/sonar-server/src/test/java/org/sonar/server/db/CheckDatabaseCollationDuringMigrationTest.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/charset/CharsetHandler.java
sonar-db/src/main/java/org/sonar/db/charset/DatabaseCharsetChecker.java
sonar-db/src/main/java/org/sonar/db/charset/MssqlCharsetHandler.java
sonar-db/src/main/java/org/sonar/db/charset/MysqlCharsetHandler.java
sonar-db/src/main/java/org/sonar/db/charset/OracleCharsetHandler.java
sonar-db/src/main/java/org/sonar/db/charset/PostgresCharsetHandler.java
sonar-db/src/test/java/org/sonar/db/charset/DatabaseCharsetCheckerTest.java
sonar-db/src/test/java/org/sonar/db/charset/MssqlCharsetHandlerTest.java
sonar-db/src/test/java/org/sonar/db/charset/MysqlCharsetHandlerTest.java
sonar-db/src/test/java/org/sonar/db/charset/OracleCharsetHandlerTest.java
sonar-db/src/test/java/org/sonar/db/charset/PostgresCharsetHandlerTest.java

diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/CheckDatabaseCharsetAfterMigration.java b/server/sonar-server/src/main/java/org/sonar/server/db/CheckDatabaseCharsetAfterMigration.java
deleted file mode 100644 (file)
index ce7c2ea..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.db;
-
-import org.sonar.api.platform.ServerUpgradeStatus;
-import org.sonar.db.charset.DatabaseCharsetChecker;
-
-/**
- * Checks charset of all database columns when at least one db migration has been executed. This requires
- * to be defined in platform level 3 ({@link org.sonar.server.platform.platformlevel.PlatformLevel3}).
- */
-public class CheckDatabaseCharsetAfterMigration extends CheckDatabaseCharsetAtStartup {
-
-  public CheckDatabaseCharsetAfterMigration(ServerUpgradeStatus upgradeStatus, DatabaseCharsetChecker charsetChecker) {
-    super(upgradeStatus, charsetChecker);
-  }
-
-  @Override
-  public void start() {
-    if (getUpgradeStatus().isFreshInstall() || getUpgradeStatus().isUpgraded()) {
-      check();
-    }
-  }
-}
index 966e676a50993e9294911b55efd1c677849c639f..91da7bd33c0296ee66a38cbefc94a68fdf49d3b3 100644 (file)
@@ -23,6 +23,8 @@ import org.picocontainer.Startable;
 import org.sonar.api.platform.ServerUpgradeStatus;
 import org.sonar.db.charset.DatabaseCharsetChecker;
 
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.ENFORCE_UTF8;
+
 /**
  * Checks charset of all existing database columns at startup, before executing db migrations. This requires
  * to be defined in platform level 2 ({@link org.sonar.server.platform.platformlevel.PlatformLevel2}).
@@ -48,11 +50,10 @@ public class CheckDatabaseCharsetAtStartup implements Startable {
   }
 
   protected final void check() {
-    boolean enforceUtf8 = getUpgradeStatus().isFreshInstall();
-    charsetChecker.check(enforceUtf8);
-  }
-
-  protected final ServerUpgradeStatus getUpgradeStatus() {
-    return upgradeStatus;
+    if (upgradeStatus.isFreshInstall()) {
+      charsetChecker.check(ENFORCE_UTF8);
+    } else if (!upgradeStatus.isUpgraded()) {
+      charsetChecker.check();
+    }
   }
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/CheckDatabaseCollationDuringMigration.java b/server/sonar-server/src/main/java/org/sonar/server/db/CheckDatabaseCollationDuringMigration.java
new file mode 100644 (file)
index 0000000..ebb5a59
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.db;
+
+import org.picocontainer.Startable;
+import org.sonar.api.platform.ServerUpgradeStatus;
+import org.sonar.db.charset.DatabaseCharsetChecker;
+
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.AUTO_REPAIR_COLLATION;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.ENFORCE_UTF8;
+
+/**
+ * Checks charset of all database columns when at least one db migration has been executed. 
+ */
+public class CheckDatabaseCollationDuringMigration implements Startable {
+
+  private final ServerUpgradeStatus upgradeStatus;
+  private final DatabaseCharsetChecker charsetChecker;
+
+  public CheckDatabaseCollationDuringMigration(ServerUpgradeStatus upgradeStatus, DatabaseCharsetChecker charsetChecker) {
+    this.upgradeStatus = upgradeStatus;
+    this.charsetChecker = charsetChecker;
+  }
+
+  @Override
+  public void start() {
+    if (upgradeStatus.isFreshInstall()) {
+      charsetChecker.check(ENFORCE_UTF8, AUTO_REPAIR_COLLATION);
+    } else if (upgradeStatus.isUpgraded()) {
+      charsetChecker.check(AUTO_REPAIR_COLLATION);
+    }
+  }
+
+  @Override
+  public void stop() {
+    // do nothing
+  }
+}
index 060eae8ee9c8832ea54c11a9b81b4e66b09a8f26..74c62e0d6d1a0f07b28655d92d825eb15435497d 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.server.platform.platformlevel;
 
 import org.sonar.api.utils.UriReader;
 import org.sonar.core.util.DefaultHttpDownloader;
-import org.sonar.server.db.CheckDatabaseCharsetAfterMigration;
 import org.sonar.server.platform.PersistentSettings;
 import org.sonar.server.platform.ServerIdGenerator;
 import org.sonar.server.platform.ServerIdLoader;
@@ -35,7 +34,6 @@ public class PlatformLevel3 extends PlatformLevel {
   @Override
   protected void configureLevel() {
     add(
-      CheckDatabaseCharsetAfterMigration.class,
       PersistentSettings.class,
       ServerMetadataPersister.class,
       DefaultHttpDownloader.class,
index 662d46becabf4a787c0e41277b36839c3adf291d..ae8a6c8ee431a8ed9b37ba5424ff964def602480 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.server.platform.platformlevel;
 
 import org.sonar.server.app.ProcessCommandWrapper;
+import org.sonar.server.db.CheckDatabaseCollationDuringMigration;
 import org.sonar.server.es.IndexerStartupTask;
 import org.sonar.server.issue.filter.RegisterIssueFilters;
 import org.sonar.server.platform.ServerLifecycleNotifier;
@@ -49,6 +50,7 @@ public class PlatformLevelStartup extends PlatformLevel {
   @Override
   protected void configureLevel() {
     add(
+      CheckDatabaseCollationDuringMigration.class,
       IndexerStartupTask.class,
       RegisterMetrics.class,
       RegisterQualityGates.class,
diff --git a/server/sonar-server/src/test/java/org/sonar/server/db/CheckDatabaseCharsetAfterMigrationTest.java b/server/sonar-server/src/test/java/org/sonar/server/db/CheckDatabaseCharsetAfterMigrationTest.java
deleted file mode 100644 (file)
index f2f014a..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.db;
-
-import org.junit.Test;
-import org.sonar.api.platform.ServerUpgradeStatus;
-import org.sonar.db.charset.DatabaseCharsetChecker;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-public class CheckDatabaseCharsetAfterMigrationTest {
-  ServerUpgradeStatus upgradeStatus = mock(ServerUpgradeStatus.class);
-  DatabaseCharsetChecker charsetChecker = mock(DatabaseCharsetChecker.class);
-  CheckDatabaseCharsetAfterMigration underTest = new CheckDatabaseCharsetAfterMigration(upgradeStatus, charsetChecker);
-
-  @Test
-  public void enforces_utf8_if_fresh_install() {
-    when(upgradeStatus.isFreshInstall()).thenReturn(true);
-    underTest.start();
-    verify(charsetChecker).check(true);
-
-    underTest.stop();
-    verifyNoMoreInteractions(charsetChecker);
-  }
-
-  @Test
-  public void checks_charset_but_does_not_enforce_utf8_if_db_upgrade() {
-    when(upgradeStatus.isFreshInstall()).thenReturn(false);
-    when(upgradeStatus.isUpgraded()).thenReturn(true);
-    underTest.start();
-    verify(charsetChecker).check(false);
-
-    underTest.stop();
-    verifyNoMoreInteractions(charsetChecker);
-  }
-
-  @Test
-  public void does_nothing_if_no_db_changes() {
-    when(upgradeStatus.isFreshInstall()).thenReturn(false);
-    when(upgradeStatus.isUpgraded()).thenReturn(false);
-
-    underTest.start();
-    underTest.stop();
-    verifyZeroInteractions(charsetChecker);
-  }
-
-}
index 4b2d4dd903b0fc91bdc97c48feb6c253392eb5e2..16d7ec302b8b3f5f4cead7623165e3f2c9670807 100644 (file)
  */
 package org.sonar.server.db;
 
+import org.junit.After;
 import org.junit.Test;
 import org.sonar.api.platform.ServerUpgradeStatus;
 import org.sonar.db.charset.DatabaseCharsetChecker;
 
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.ENFORCE_UTF8;
 
 public class CheckDatabaseCharsetAtStartupTest {
 
@@ -34,23 +35,26 @@ public class CheckDatabaseCharsetAtStartupTest {
   DatabaseCharsetChecker charsetChecker = mock(DatabaseCharsetChecker.class);
   CheckDatabaseCharsetAtStartup underTest = new CheckDatabaseCharsetAtStartup(upgradeStatus, charsetChecker);
 
+  @After
+  public void tearDown() {
+    underTest.stop();
+  }
+
   @Test
-  public void enforces_utf8_if_fresh_install() {
+  public void enforce_utf8_if_fresh_install() {
     when(upgradeStatus.isFreshInstall()).thenReturn(true);
+
     underTest.start();
-    verify(charsetChecker).check(true);
 
-    underTest.stop();
-    verifyNoMoreInteractions(charsetChecker);
+    verify(charsetChecker).check(ENFORCE_UTF8);
   }
 
   @Test
-  public void does_not_enforce_utf8_if_not_fresh_install() {
+  public void do_not_enforce_utf8_and_do_not_repair_at_startup_if_not_fresh_install() {
     when(upgradeStatus.isFreshInstall()).thenReturn(false);
+
     underTest.start();
-    verify(charsetChecker).check(false);
 
-    underTest.stop();
-    verifyNoMoreInteractions(charsetChecker);
+    verify(charsetChecker).check();
   }
 }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/db/CheckDatabaseCollationDuringMigrationTest.java b/server/sonar-server/src/test/java/org/sonar/server/db/CheckDatabaseCollationDuringMigrationTest.java
new file mode 100644 (file)
index 0000000..fdb4ef2
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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.db;
+
+import org.junit.After;
+import org.junit.Test;
+import org.sonar.api.platform.ServerUpgradeStatus;
+import org.sonar.db.charset.DatabaseCharsetChecker;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.AUTO_REPAIR_COLLATION;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.ENFORCE_UTF8;
+
+public class CheckDatabaseCollationDuringMigrationTest {
+  ServerUpgradeStatus upgradeStatus = mock(ServerUpgradeStatus.class);
+  DatabaseCharsetChecker charsetChecker = mock(DatabaseCharsetChecker.class);
+  CheckDatabaseCollationDuringMigration underTest = new CheckDatabaseCollationDuringMigration(upgradeStatus, charsetChecker);
+
+  @After
+  public void tearDown() {
+    underTest.stop();
+  }
+
+  @Test
+  public void enforce_utf8_and_optionally_repair_collation_if_fresh_install() {
+    when(upgradeStatus.isFreshInstall()).thenReturn(true);
+
+    underTest.start();
+
+    verify(charsetChecker).check(ENFORCE_UTF8, AUTO_REPAIR_COLLATION);
+  }
+
+  @Test
+  public void repair_collation_but_do_not_enforce_utf8_if_db_upgrade() {
+    when(upgradeStatus.isFreshInstall()).thenReturn(false);
+    when(upgradeStatus.isUpgraded()).thenReturn(true);
+
+    underTest.start();
+
+    verify(charsetChecker).check(AUTO_REPAIR_COLLATION);
+  }
+
+  @Test
+  public void do_nothing_if_no_db_changes() {
+    when(upgradeStatus.isFreshInstall()).thenReturn(false);
+    when(upgradeStatus.isUpgraded()).thenReturn(false);
+
+    underTest.start();
+
+    verifyZeroInteractions(charsetChecker);
+  }
+
+}
index 233cb14b5a84e6cc7b9dc87da94bc8780d75e173..df8d2d4fa3ca470c638834638f15682dd17805f5 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.db.charset;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.List;
+import java.util.Set;
 import javax.annotation.CheckForNull;
 
 abstract class CharsetHandler {
@@ -34,7 +35,7 @@ abstract class CharsetHandler {
     this.selectExecutor = selectExecutor;
   }
 
-  abstract void handle(Connection connection, boolean enforceUtf8) throws SQLException;
+  abstract void handle(Connection connection, Set<DatabaseCharsetChecker.Flag> flags) throws SQLException;
 
   protected SqlExecutor getSqlExecutor() {
     return selectExecutor;
@@ -61,5 +62,4 @@ abstract class CharsetHandler {
   protected final <T> List<T> select(Connection connection, String sql, SqlExecutor.RowConverter<T> rowConverter) throws SQLException {
     return selectExecutor.executeSelect(connection, sql, rowConverter);
   }
-
 }
index cdc87bc3b2dd60e7e375de5c5ea0b5c207c5cb09..2e89e2d3a97a14f021fae51eecefd712eeff7088 100644 (file)
@@ -31,6 +31,9 @@ import org.sonar.db.dialect.MySql;
 import org.sonar.db.dialect.Oracle;
 import org.sonar.db.dialect.PostgreSql;
 
+import static com.google.common.collect.Sets.immutableEnumSet;
+import static java.util.Arrays.asList;
+
 /**
  * On fresh installations, checks that all db columns are UTF8. On all installations on MySQL or MSSQL,
  * whatever fresh or upgrade, fixes case-insensitive columns by converting them to
@@ -40,6 +43,10 @@ import org.sonar.db.dialect.PostgreSql;
  */
 public class DatabaseCharsetChecker {
 
+  public enum Flag {
+    ENFORCE_UTF8, AUTO_REPAIR_COLLATION
+  }
+
   private final Database db;
   private final SqlExecutor selectExecutor;
 
@@ -53,12 +60,12 @@ public class DatabaseCharsetChecker {
     this.selectExecutor = selectExecutor;
   }
 
-  public void check(boolean enforceUtf8) {
+  public void check(Flag... flags) {
     try {
       try (Connection connection = db.getDataSource().getConnection()) {
         CharsetHandler handler = getHandler(db.getDialect());
         if (handler != null) {
-          handler.handle(connection, enforceUtf8);
+          handler.handle(connection, immutableEnumSet(asList(flags)));
         }
       }
     } catch (SQLException e) {
@@ -85,5 +92,4 @@ public class DatabaseCharsetChecker {
         throw new IllegalArgumentException("Database not supported: " + dialect.getId());
     }
   }
-
 }
index 774251771eba4c5337739d8f7be7abf362d42bed..cbac5a3d59a33c6883c9dbd7479b85f8912e8cd3 100644 (file)
 package org.sonar.db.charset;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Set;
+import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 
 import static com.google.common.collect.FluentIterable.from;
 import static java.lang.String.format;
 import static org.apache.commons.lang.StringUtils.endsWithIgnoreCase;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.AUTO_REPAIR_COLLATION;
 
 class MssqlCharsetHandler extends CharsetHandler {
 
@@ -40,15 +45,13 @@ class MssqlCharsetHandler extends CharsetHandler {
   }
 
   @Override
-  void handle(Connection connection, boolean enforceUtf8) throws SQLException {
-    LOGGER.info("Verify that database collation is case-sensitive and accent-sensitive");
-    checkCollation(connection);
-  }
+  void handle(Connection connection, Set<DatabaseCharsetChecker.Flag> flags) throws SQLException {
+    logInit(flags);
 
-  private void checkCollation(Connection connection) throws SQLException {
     // All VARCHAR columns are returned. No need to check database general collation.
     // Example of row:
     // issues | kee | Latin1_General_CS_AS
+    Set<String> errors = new LinkedHashSet<>();
     List<ColumnDef> columns = select(connection,
       ColumnDef.SELECT_COLUMNS +
         "FROM [INFORMATION_SCHEMA].[COLUMNS] " +
@@ -56,9 +59,26 @@ class MssqlCharsetHandler extends CharsetHandler {
         "ORDER BY table_name,column_name", ColumnDef.ColumnDefRowConverter.INSTANCE);
     for (ColumnDef column : from(columns).filter(ColumnDef.IsInSonarQubeTablePredicate.INSTANCE)) {
       if (!endsWithIgnoreCase(column.getCollation(), "_CS_AS")) {
-        repairColumnCollation(connection, column);
+        if (flags.contains(AUTO_REPAIR_COLLATION)) {
+          repairColumnCollation(connection, column);
+        } else {
+          errors.add(format("%s.%s", column.getTable(), column.getColumn()));
+        }
       }
     }
+
+    if (!errors.isEmpty()) {
+      throw MessageException.of(format("Case-sensitive and accent-sensitive collation is required for database columns [%s]",
+        Joiner.on(", ").join(errors)));
+    }
+  }
+
+  private static void logInit(Set<DatabaseCharsetChecker.Flag> flags) {
+    if (flags.contains(AUTO_REPAIR_COLLATION)) {
+      LOGGER.info("Repair case-insensitive or accent-insensitive database columns");
+    } else {
+      LOGGER.info("Verify that database columns are case-sensitive and accent-sensitive");
+    }
   }
 
   private void repairColumnCollation(Connection connection, ColumnDef column) throws SQLException {
index 43bec2d9ffc8b9952606bf16c4e00c9b2e9b13b9..4f003aba7356a684c6ffd8f01e8821791a8533e6 100644 (file)
@@ -23,8 +23,9 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Joiner;
 import java.sql.Connection;
 import java.sql.SQLException;
-import java.util.ArrayList;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Set;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.log.Logger;
@@ -34,6 +35,8 @@ import static com.google.common.collect.FluentIterable.from;
 import static java.lang.String.format;
 import static org.apache.commons.lang.StringUtils.containsIgnoreCase;
 import static org.apache.commons.lang.StringUtils.endsWithIgnoreCase;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.AUTO_REPAIR_COLLATION;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.ENFORCE_UTF8;
 
 class MysqlCharsetHandler extends CharsetHandler {
 
@@ -45,20 +48,22 @@ class MysqlCharsetHandler extends CharsetHandler {
   }
 
   @Override
-  void handle(Connection connection, boolean enforceUtf8) throws SQLException {
-    logInit(enforceUtf8);
-    checkCollation(connection, enforceUtf8);
+  void handle(Connection connection, Set<DatabaseCharsetChecker.Flag> flags) throws SQLException {
+    logInit(flags);
+    checkCollation(connection, flags);
   }
 
-  private static void logInit(boolean enforceUtf8) {
-    String message = "Verify that database collation is case-sensitive";
-    if (enforceUtf8) {
-      message = "Verify that database collation is UTF8";
+  private static void logInit(Set<DatabaseCharsetChecker.Flag> flags) {
+    if (flags.contains(AUTO_REPAIR_COLLATION)) {
+      LOGGER.info("Repair case-insensitive database columns");
+    } else if (flags.contains(ENFORCE_UTF8)) {
+      LOGGER.info("Verify that database collation is UTF8");
+    } else {
+      LOGGER.info("Verify that database collation is case-sensitive");
     }
-    LOGGER.info(message);
   }
 
-  private void checkCollation(Connection connection, boolean enforceUtf8) throws SQLException {
+  private void checkCollation(Connection connection, Set<DatabaseCharsetChecker.Flag> flags) throws SQLException {
     // All VARCHAR columns are returned. No need to check database general collation.
     // Example of row:
     // issues | kee | utf8 | utf8_bin
@@ -66,16 +71,21 @@ class MysqlCharsetHandler extends CharsetHandler {
       ColumnDef.SELECT_COLUMNS +
         "FROM INFORMATION_SCHEMA.columns " +
         "WHERE table_schema=database() and character_set_name is not null and collation_name is not null", ColumnDef.ColumnDefRowConverter.INSTANCE);
-    List<String> utf8Errors = new ArrayList<>();
+    Set<String> errors = new LinkedHashSet<>();
     for (ColumnDef column : from(columns).filter(ColumnDef.IsInSonarQubeTablePredicate.INSTANCE)) {
-      if (enforceUtf8 && !containsIgnoreCase(column.getCharset(), UTF8)) {
-        utf8Errors.add(format("%s.%s", column.getTable(), column.getColumn()));
-      } else if (endsWithIgnoreCase(column.getCollation(), "_ci")) {
-        repairCaseInsensitiveColumn(connection, column);
+      if (flags.contains(ENFORCE_UTF8) && !containsIgnoreCase(column.getCharset(), UTF8)) {
+        errors.add(format("%s.%s", column.getTable(), column.getColumn()));
+      }
+      if (endsWithIgnoreCase(column.getCollation(), "_ci")) {
+        if (flags.contains(AUTO_REPAIR_COLLATION)) {
+          repairCaseInsensitiveColumn(connection, column);
+        } else {
+          errors.add(format("%s.%s", column.getTable(), column.getColumn()));
+        }
       }
     }
-    if (!utf8Errors.isEmpty()) {
-      throw MessageException.of(format("UTF8 case-sensitive collation is required for database columns [%s]", Joiner.on(", ").join(utf8Errors)));
+    if (!errors.isEmpty()) {
+      throw MessageException.of(format("UTF8 case-sensitive collation is required for database columns [%s]", Joiner.on(", ").join(errors)));
     }
   }
 
index 179d7c2f796cfd685d3f4a1528e75bc029f5809b..1ff377175cf67b44d1dd67156df44185f64e872e 100644 (file)
@@ -21,11 +21,13 @@ package org.sonar.db.charset;
 
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.util.Set;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.log.Loggers;
 
 import static java.lang.String.format;
 import static org.apache.commons.lang.StringUtils.containsIgnoreCase;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.ENFORCE_UTF8;
 
 class OracleCharsetHandler extends CharsetHandler {
 
@@ -34,9 +36,9 @@ class OracleCharsetHandler extends CharsetHandler {
   }
 
   @Override
-  public void handle(Connection connection, boolean enforceUtf8) throws SQLException {
+  public void handle(Connection connection, Set<DatabaseCharsetChecker.Flag> flags) throws SQLException {
     // Oracle does not allow to override character set on tables. Only global charset is verified.
-    if (enforceUtf8) {
+    if (flags.contains(ENFORCE_UTF8)) {
       Loggers.get(getClass()).info("Verify that database charset is UTF8");
       checkUtf8(connection);
     }
index 1452750ae1f1036c2111acd8062009f083356ac4..81cd5bcc1a3635f4954962d22321c9b5179f7d98 100644 (file)
@@ -22,14 +22,16 @@ package org.sonar.db.charset;
 import com.google.common.base.Joiner;
 import java.sql.Connection;
 import java.sql.SQLException;
-import java.util.ArrayList;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Set;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.log.Loggers;
 
 import static java.lang.String.format;
 import static org.apache.commons.lang.StringUtils.containsIgnoreCase;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.ENFORCE_UTF8;
 
 class PostgresCharsetHandler extends CharsetHandler {
 
@@ -38,9 +40,9 @@ class PostgresCharsetHandler extends CharsetHandler {
   }
 
   @Override
-  void handle(Connection connection, boolean enforceUtf8) throws SQLException {
+  void handle(Connection connection, Set<DatabaseCharsetChecker.Flag> flags) throws SQLException {
     // PostgreSQL does not support case-insensitive collations. Only charset must be verified.
-    if (enforceUtf8) {
+    if (flags.contains(ENFORCE_UTF8)) {
       Loggers.get(getClass()).info("Verify that database collation supports UTF8");
       checkUtf8(connection);
     }
@@ -58,7 +60,7 @@ class PostgresCharsetHandler extends CharsetHandler {
       "and udt_name='varchar' " +
       "order by table_name, column_name", new SqlExecutor.StringsConverter(3 /* columns returned by SELECT */));
     boolean mustCheckGlobalCollation = false;
-    List<String> errors = new ArrayList<>();
+    Set<String> errors = new LinkedHashSet<>();
     for (String[] row : rows) {
       if (StringUtils.isBlank(row[2])) {
         mustCheckGlobalCollation = true;
index 88e47d4af2e7db8c36b4b716286659825c93c907..41c87e6b28fc90d0888d079bad30bad2b44c2482 100644 (file)
@@ -21,6 +21,9 @@ package org.sonar.db.charset;
 
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.util.Set;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -35,13 +38,15 @@ import org.sonar.db.dialect.PostgreSql;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.anySet;
+import static org.mockito.Matchers.argThat;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.AUTO_REPAIR_COLLATION;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.ENFORCE_UTF8;
 
 public class DatabaseCharsetCheckerTest {
 
@@ -58,8 +63,17 @@ public class DatabaseCharsetCheckerTest {
     when(underTest.getHandler(dialect)).thenReturn(handler);
     when(db.getDialect()).thenReturn(dialect);
 
-    underTest.check(true);
-    verify(handler).handle(any(Connection.class), eq(true));
+    underTest.check(ENFORCE_UTF8);
+    verify(handler).handle(any(Connection.class), argThat(new TypeSafeMatcher<Set<DatabaseCharsetChecker.Flag>>() {
+      @Override
+      protected boolean matchesSafely(Set<DatabaseCharsetChecker.Flag> flags) {
+        return flags.contains(ENFORCE_UTF8) && flags.size() == 1;
+      }
+
+      @Override
+      public void describeTo(Description description) {
+      }
+    }));
   }
 
   @Test
@@ -67,11 +81,11 @@ public class DatabaseCharsetCheckerTest {
     Oracle dialect = new Oracle();
     when(underTest.getHandler(dialect)).thenReturn(handler);
     when(db.getDialect()).thenReturn(dialect);
-    doThrow(new SQLException("failure")).when(handler).handle(any(Connection.class), anyBoolean());
+    doThrow(new SQLException("failure")).when(handler).handle(any(Connection.class), anySet());
 
     expectedException.expect(IllegalStateException.class);
     expectedException.expectMessage("failure");
-    underTest.check(true);
+    underTest.check(AUTO_REPAIR_COLLATION);
   }
 
   @Test
index f3748576380aa2f8d460bb7319734b7982937982..a81bf41ddda91df47dfe8b5bfebbd425069cc5e5 100644 (file)
@@ -26,7 +26,9 @@ import java.util.List;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.MessageException;
 
+import static com.google.common.collect.Sets.immutableEnumSet;
 import static java.util.Arrays.asList;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
@@ -35,6 +37,7 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.AUTO_REPAIR_COLLATION;
 
 public class MssqlCharsetHandlerTest {
 
@@ -50,28 +53,42 @@ public class MssqlCharsetHandlerTest {
   MssqlCharsetHandler underTest = new MssqlCharsetHandler(selectExecutor);
 
   @Test
-  public void does_not_fail_if_charsets_of_all_columns_are_utf8() throws Exception {
+  public void do_not_fail_if_charsets_of_all_columns_are_CS_AS() throws Exception {
     answerColumns(asList(
       new ColumnDef(TABLE_ISSUES, COLUMN_KEE, "Latin1_General", "Latin1_General_CS_AS", "varchar", 10, false),
       new ColumnDef(TABLE_PROJECTS, COLUMN_NAME, "Latin1_General", "Latin1_General_CS_AS", "varchar", 10, false)));
 
-    underTest.handle(mock(Connection.class), true);
+    underTest.handle(mock(Connection.class), Collections.<DatabaseCharsetChecker.Flag>emptySet());
   }
 
   @Test
-  public void repairs_case_insensitive_column_without_index() throws Exception {
+  public void fail_if_a_column_is_case_insensitive_and_repair_is_disabled() throws Exception {
     answerColumns(asList(
       new ColumnDef(TABLE_ISSUES, COLUMN_KEE, "Latin1_General", "Latin1_General_CS_AS", "varchar", 10, false),
       new ColumnDef(TABLE_PROJECTS, COLUMN_NAME, "Latin1_General", "Latin1_General_CI_AI", "varchar", 10, false)));
 
+    expectedException.expect(MessageException.class);
+    expectedException.expectMessage("Case-sensitive and accent-sensitive collation is required for database columns [projects.name]");
     Connection connection = mock(Connection.class);
-    underTest.handle(connection, false);
+    underTest.handle(connection, Collections.<DatabaseCharsetChecker.Flag>emptySet());
+
+    verify(selectExecutor, never()).executeUpdate(any(Connection.class), anyString());
+  }
+
+  @Test
+  public void repair_case_insensitive_column_without_index() throws Exception {
+    answerColumns(asList(
+      new ColumnDef(TABLE_ISSUES, COLUMN_KEE, "Latin1_General", "Latin1_General_CS_AS", "varchar", 10, false),
+      new ColumnDef(TABLE_PROJECTS, COLUMN_NAME, "Latin1_General", "Latin1_General_CI_AI", "varchar", 10, false)));
+
+    Connection connection = mock(Connection.class);
+    underTest.handle(connection, immutableEnumSet(AUTO_REPAIR_COLLATION));
 
     verify(selectExecutor).executeUpdate(connection, "ALTER TABLE projects ALTER COLUMN name varchar(10) COLLATE Latin1_General_CS_AS NOT NULL");
   }
 
   @Test
-  public void repairs_case_insensitive_column_with_indices() throws Exception {
+  public void repair_case_insensitive_column_with_indices() throws Exception {
     answerColumns(asList(
       new ColumnDef(TABLE_ISSUES, COLUMN_KEE, "Latin1_General", "Latin1_General_CS_AS", "varchar", 10, false),
       new ColumnDef(TABLE_PROJECTS, COLUMN_NAME, "Latin1_General", "Latin1_General_CI_AI", "varchar", 10, false)));
@@ -81,7 +98,7 @@ public class MssqlCharsetHandlerTest {
       new MssqlCharsetHandler.ColumnIndex("projects_login_and_name", true, "login,name")));
 
     Connection connection = mock(Connection.class);
-    underTest.handle(connection, false);
+    underTest.handle(connection, immutableEnumSet(AUTO_REPAIR_COLLATION));
 
     verify(selectExecutor).executeUpdate(connection, "DROP INDEX projects.projects_name");
     verify(selectExecutor).executeUpdate(connection, "DROP INDEX projects.projects_login_and_name");
@@ -97,7 +114,7 @@ public class MssqlCharsetHandlerTest {
     answerIndices(Collections.<MssqlCharsetHandler.ColumnIndex>emptyList());
 
     Connection connection = mock(Connection.class);
-    underTest.handle(connection, false);
+    underTest.handle(connection, immutableEnumSet(AUTO_REPAIR_COLLATION));
 
     verify(selectExecutor).executeUpdate(connection, "ALTER TABLE projects ALTER COLUMN name nvarchar(max) COLLATE Latin1_General_CS_AS NOT NULL");
   }
@@ -107,7 +124,7 @@ public class MssqlCharsetHandlerTest {
     answerColumns(asList(new ColumnDef("sys.sysusers", COLUMN_NAME, "Latin1_General", "Latin1_General_CI_AI", "varchar", 10, false)));
 
     Connection connection = mock(Connection.class);
-    underTest.handle(connection, false);
+    underTest.handle(connection, immutableEnumSet(AUTO_REPAIR_COLLATION));
 
     verify(selectExecutor, never()).executeUpdate(any(Connection.class), anyString());
   }
index 9e9687a2bfdf9bf7a68718987e103e5a8dc0fca2..d050fbedf3cfbecca53fc49218c60af15bceebcf 100644 (file)
@@ -27,6 +27,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.MessageException;
 
+import static com.google.common.collect.Sets.immutableEnumSet;
 import static java.util.Arrays.asList;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Matchers.any;
@@ -35,6 +36,8 @@ import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.AUTO_REPAIR_COLLATION;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.ENFORCE_UTF8;
 
 public class MysqlCharsetHandlerTest {
 
@@ -50,17 +53,29 @@ public class MysqlCharsetHandlerTest {
   MysqlCharsetHandler underTest = new MysqlCharsetHandler(selectExecutor);
 
   @Test
-  public void does_not_fail_if_charsets_of_all_columns_are_utf8() throws Exception {
+  public void do_not_fail_if_charsets_of_all_columns_are_utf8_and_case_sensitive() throws Exception {
     answerColumnDef(asList(
       new ColumnDef(TABLE_ISSUES, COLUMN_KEE, "utf8", "utf8_bin", "varchar", 10, false),
       new ColumnDef(TABLE_PROJECTS, COLUMN_NAME, "utf8", "utf8_bin", "varchar", 10, false)));
 
     // all columns are utf8
-    underTest.handle(mock(Connection.class), true);
+    underTest.handle(mock(Connection.class), immutableEnumSet(ENFORCE_UTF8));
   }
 
   @Test
-  public void fails_if_not_utf8() throws Exception {
+  public void fail_if_charsets_of_a_column_is_utf8_but_case_insensitive() throws Exception {
+    answerColumnDef(asList(
+      new ColumnDef(TABLE_ISSUES, COLUMN_KEE, "utf8", "utf8_bin", "varchar", 10, false),
+      new ColumnDef(TABLE_PROJECTS, COLUMN_NAME, "utf8", "utf8_general_ci", "varchar", 10, false)));
+
+    expectedException.expect(MessageException.class);
+    expectedException.expectMessage("UTF8 case-sensitive collation is required for database columns [projects.name]");
+
+    underTest.handle(mock(Connection.class), immutableEnumSet(ENFORCE_UTF8));
+  }
+
+  @Test
+  public void fail_if_not_utf8() throws Exception {
     answerColumnDef(asList(
       new ColumnDef(TABLE_ISSUES, COLUMN_KEE, "utf8", "utf8_bin", "varchar", 10, false),
       new ColumnDef(TABLE_PROJECTS, COLUMN_KEE, "latin1", "latin1_german1_ci", "varchar", 10, false),
@@ -68,17 +83,17 @@ public class MysqlCharsetHandlerTest {
 
     expectedException.expect(MessageException.class);
     expectedException.expectMessage("UTF8 case-sensitive collation is required for database columns [projects.kee, projects.name]");
-    underTest.handle(mock(Connection.class), true);
+    underTest.handle(mock(Connection.class), immutableEnumSet(ENFORCE_UTF8));
   }
 
   @Test
-  public void repairs_case_insensitive_column() throws Exception {
+  public void repair_case_insensitive_column() throws Exception {
     answerColumnDef(asList(
       new ColumnDef(TABLE_ISSUES, COLUMN_KEE, "utf8", "utf8_bin", "varchar", 10, false),
       new ColumnDef(TABLE_PROJECTS, COLUMN_NAME, "latin1", "latin1_swedish_ci", "varchar", 10, false)));
 
     Connection connection = mock(Connection.class);
-    underTest.handle(connection, false);
+    underTest.handle(connection, immutableEnumSet(AUTO_REPAIR_COLLATION));
 
     verify(selectExecutor).executeUpdate(connection, "ALTER TABLE projects MODIFY name varchar(10) CHARACTER SET 'latin1' COLLATE 'latin1_bin' NOT NULL");
   }
@@ -88,7 +103,7 @@ public class MysqlCharsetHandlerTest {
     answerColumnDef(asList(new ColumnDef(TABLE_ISSUES, COLUMN_KEE, "latin1", "latin1_german1_ci", "longtext", 4_294_967_295L, false)));
 
     Connection connection = mock(Connection.class);
-    underTest.handle(connection, false);
+    underTest.handle(connection, immutableEnumSet(AUTO_REPAIR_COLLATION));
 
     verify(selectExecutor).executeUpdate(connection, "ALTER TABLE " + TABLE_ISSUES + " MODIFY " + COLUMN_KEE + " longtext CHARACTER SET 'latin1' COLLATE 'latin1_bin' NOT NULL");
   }
index 0d39cdb598d1a10e07efae6da4a6156393ebe7d1..76be06e7f21fe9c07120ae991812f2e9980e1d09 100644 (file)
@@ -23,19 +23,25 @@ import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.MessageException;
+import org.sonar.db.charset.DatabaseCharsetChecker.Flag;
 
+import static com.google.common.collect.Sets.immutableEnumSet;
 import static java.util.Collections.singletonList;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.ENFORCE_UTF8;
 
 public class OracleCharsetHandlerTest {
 
+  private static final Set<Flag> ENFORCE_UTF8_FLAGS = immutableEnumSet(ENFORCE_UTF8);
+
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
 
@@ -47,7 +53,7 @@ public class OracleCharsetHandlerTest {
     answerSql(
       singletonList(new String[] {"UTF8"}), singletonList(new String[] {"BINARY"}));
 
-    underTest.handle(mock(Connection.class), true);
+    underTest.handle(mock(Connection.class), ENFORCE_UTF8_FLAGS);
   }
 
   @Test
@@ -55,7 +61,7 @@ public class OracleCharsetHandlerTest {
     answerSql(
       singletonList(new String[] {"AL32UTF8"}), singletonList(new String[] {"BINARY"}));
 
-    underTest.handle(mock(Connection.class), true);
+    underTest.handle(mock(Connection.class), ENFORCE_UTF8_FLAGS);
   }
 
   @Test
@@ -66,7 +72,7 @@ public class OracleCharsetHandlerTest {
     expectedException.expect(MessageException.class);
     expectedException.expectMessage("Oracle must be have UTF8 charset and BINARY sort. NLS_CHARACTERSET is LATIN and NLS_SORT is BINARY.");
 
-    underTest.handle(mock(Connection.class), true);
+    underTest.handle(mock(Connection.class), ENFORCE_UTF8_FLAGS);
   }
 
   @Test
@@ -77,7 +83,7 @@ public class OracleCharsetHandlerTest {
     expectedException.expect(MessageException.class);
     expectedException.expectMessage("Oracle must be have UTF8 charset and BINARY sort. NLS_CHARACTERSET is UTF8 and NLS_SORT is LINGUISTIC.");
 
-    underTest.handle(mock(Connection.class), true);
+    underTest.handle(mock(Connection.class), ENFORCE_UTF8_FLAGS);
   }
 
   @Test
@@ -86,12 +92,12 @@ public class OracleCharsetHandlerTest {
 
     expectedException.expect(MessageException.class);
 
-    underTest.handle(mock(Connection.class), true);
+    underTest.handle(mock(Connection.class), ENFORCE_UTF8_FLAGS);
   }
 
   @Test
   public void does_nothing_if_utf8_must_not_verified() throws Exception {
-    underTest.handle(mock(Connection.class), false);
+    underTest.handle(mock(Connection.class), Collections.<Flag>emptySet());
   }
 
   private void answerSql(List<String[]> firstRequest, List<String[]>... otherRequests) throws SQLException {
index de30b65f63a4f151e83c97e354be1c08631e2965..d348e31117e499a1b40b744ce91b15760f9d35db 100644 (file)
@@ -22,17 +22,21 @@ package org.sonar.db.charset;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.MessageException;
+import org.sonar.db.charset.DatabaseCharsetChecker.Flag;
 
+import static com.google.common.collect.Sets.immutableEnumSet;
 import static java.util.Arrays.asList;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
+import static org.sonar.db.charset.DatabaseCharsetChecker.Flag.ENFORCE_UTF8;
 
 public class PostgresCharsetHandlerTest {
 
@@ -53,7 +57,7 @@ public class PostgresCharsetHandlerTest {
       new String[] {TABLE_ISSUES, COLUMN_KEE, "utf8"},
       new String[] {TABLE_PROJECTS, COLUMN_NAME, "utf8"}));
 
-    underTest.handle(mock(Connection.class), true);
+    underTest.handle(mock(Connection.class), immutableEnumSet(ENFORCE_UTF8));
   }
 
   @Test
@@ -68,7 +72,7 @@ public class PostgresCharsetHandlerTest {
       Arrays.<String[]>asList(new String[] {"utf8"}));
 
     // no error
-    underTest.handle(mock(Connection.class), true);
+    underTest.handle(mock(Connection.class), immutableEnumSet(ENFORCE_UTF8));
   }
 
   @Test
@@ -81,7 +85,7 @@ public class PostgresCharsetHandlerTest {
     expectedException.expect(MessageException.class);
     expectedException.expectMessage("Database columns [projects.kee, projects.name] must support UTF8 collation.");
 
-    underTest.handle(mock(Connection.class), true);
+    underTest.handle(mock(Connection.class), immutableEnumSet(ENFORCE_UTF8));
   }
 
   @Test
@@ -98,12 +102,12 @@ public class PostgresCharsetHandlerTest {
     expectedException.expect(MessageException.class);
     expectedException.expectMessage("Database collation is latin. It must support UTF8.");
 
-    underTest.handle(mock(Connection.class), true);
+    underTest.handle(mock(Connection.class), immutableEnumSet(ENFORCE_UTF8));
   }
 
   @Test
   public void does_nothing_if_utf8_must_not_verified() throws Exception {
-    underTest.handle(mock(Connection.class), false);
+    underTest.handle(mock(Connection.class), Collections.<Flag>emptySet());
   }
 
   private void answerSql(List<String[]> firstRequest, List<String[]>... otherRequests) throws SQLException {