From: Sébastien Lesaint Date: Fri, 24 Jun 2016 16:11:42 +0000 (+0200) Subject: SONAR-7798 support BIN and BIN2 collation on MsSQL X-Git-Tag: 6.0-RC1~247^2 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=refs%2Fpull%2F1062%2Fhead;p=sonarqube.git SONAR-7798 support BIN and BIN2 collation on MsSQL --- diff --git a/sonar-db/src/main/java/org/sonar/db/charset/MssqlCharsetHandler.java b/sonar-db/src/main/java/org/sonar/db/charset/MssqlCharsetHandler.java index 6eb18364796..6b3cef60d1f 100644 --- a/sonar-db/src/main/java/org/sonar/db/charset/MssqlCharsetHandler.java +++ b/sonar-db/src/main/java/org/sonar/db/charset/MssqlCharsetHandler.java @@ -43,6 +43,8 @@ class MssqlCharsetHandler extends CharsetHandler { private static final String CASE_INSENSITIVE_ACCENT_INSENSITIVE = "_CI_AI"; private static final String CASE_INSENSITIVE_ACCENT_SENSITIVE = "_CI_AS"; private static final String CASE_SENSITIVE_ACCENT_INSENSITIVE = "_CS_AI"; + private static final String BIN = "BIN"; + private static final String BIN2 = "BIN2"; protected MssqlCharsetHandler(SqlExecutor selectExecutor) { super(selectExecutor); @@ -63,7 +65,7 @@ class MssqlCharsetHandler extends CharsetHandler { "ORDER BY table_name,column_name", ColumnDef.ColumnDefRowConverter.INSTANCE); for (ColumnDef column : from(columns).filter(ColumnDef.IsInSonarQubeTablePredicate.INSTANCE)) { - if (!containsIgnoreCase(column.getCollation(), CASE_SENSITIVE_ACCENT_SENSITIVE)) { + if (!isCollationCorrect(column)) { if (flags.contains(AUTO_REPAIR_COLLATION)) { repairColumnCollation(connection, column); } else { @@ -78,6 +80,16 @@ class MssqlCharsetHandler extends CharsetHandler { } } + /** + * Collation is correct if is contains {@link #CASE_SENSITIVE_ACCENT_SENSITIVE} or {@link #BIN} or {@link #BIN2}. + */ + private static boolean isCollationCorrect(ColumnDef column) { + String collation = column.getCollation(); + return containsIgnoreCase(collation, CASE_SENSITIVE_ACCENT_SENSITIVE) + || containsIgnoreCase(collation, BIN) + || containsIgnoreCase(collation, BIN2); + } + private static void logInit(Set flags) { if (flags.contains(AUTO_REPAIR_COLLATION)) { LOGGER.info("Repair case-insensitive or accent-insensitive database columns"); @@ -136,9 +148,9 @@ class MssqlCharsetHandler extends CharsetHandler { } @VisibleForTesting - static String toCaseSensitive(String ciCollation) { + static String toCaseSensitive(String collation) { // Example: Latin1_General_CI_AI --> Latin1_General_CS_AS or Latin1_General_100_CI_AS_KS_WS --> Latin1_General_100_CS_AS_KS_WS - return ciCollation + return collation .replace(CASE_INSENSITIVE_ACCENT_INSENSITIVE, CASE_SENSITIVE_ACCENT_SENSITIVE) .replace(CASE_INSENSITIVE_ACCENT_SENSITIVE, CASE_SENSITIVE_ACCENT_SENSITIVE) .replace(CASE_SENSITIVE_ACCENT_INSENSITIVE, CASE_SENSITIVE_ACCENT_SENSITIVE); diff --git a/sonar-db/src/test/java/org/sonar/db/charset/MssqlCharsetHandlerTest.java b/sonar-db/src/test/java/org/sonar/db/charset/MssqlCharsetHandlerTest.java index f097436adf0..bd81b60afd2 100644 --- a/sonar-db/src/test/java/org/sonar/db/charset/MssqlCharsetHandlerTest.java +++ b/sonar-db/src/test/java/org/sonar/db/charset/MssqlCharsetHandlerTest.java @@ -129,16 +129,12 @@ public class MssqlCharsetHandlerTest { @DataProvider public static Object[][] combinationsOfCsAsAndSuffix() { List res = new ArrayList<>(); - for (String caseSensitivity : Arrays.asList("CS", "CI")) { - for (String accentSensitivity : Arrays.asList("AS", "AI")) { - if (caseSensitivity.equals("CI") || accentSensitivity.equals("AI")) { - for (String suffix : Arrays.asList("", "_KS_WS")) { - res.add(new String[] { - format("Latin1_General_%s_%s%s", caseSensitivity, accentSensitivity, suffix), - format("Latin1_General_CS_AS%s", suffix) - }); - } - } + for (String sensitivity : Arrays.asList("CI_AI", "CI_AS", "CS_AI")) { + for (String suffix : Arrays.asList("", "_KS_WS")) { + res.add(new String[] { + format("Latin1_General_%s%s", sensitivity, suffix), + format("Latin1_General_CS_AS%s", suffix) + }); } } return res.stream().toArray(Object[][]::new); @@ -166,6 +162,44 @@ public class MssqlCharsetHandlerTest { verify(selectExecutor, never()).executeUpdate(any(Connection.class), anyString()); } + @Test + @UseDataProvider("combinationOfBinAndSuffix") + public void do_not_repair_if_collation_contains_BIN(String collation) throws Exception { + answerColumns(asList(new ColumnDef(TABLE_PROJECTS, COLUMN_NAME, "Latin1_General", collation, "varchar", 10, false))); + + Connection connection = mock(Connection.class); + underTest.handle(connection, immutableEnumSet(AUTO_REPAIR_COLLATION)); + + verify(selectExecutor, never()).executeUpdate(any(Connection.class), anyString()); + } + + @DataProvider + public static Object[][] combinationOfBinAndSuffix() { + return Arrays.asList("", "_KS_WS") + .stream() + .map(suffix -> new String[] {format("Latin1_General_BIN%s", suffix)}) + .toArray(Object[][]::new); + } + + @Test + @UseDataProvider("combinationOfBin2AndSuffix") + public void do_not_repair_if_collation_contains_BIN2(String collation) throws Exception { + answerColumns(asList(new ColumnDef(TABLE_PROJECTS, COLUMN_NAME, "Latin1_General", collation, "varchar", 10, false))); + + Connection connection = mock(Connection.class); + underTest.handle(connection, immutableEnumSet(AUTO_REPAIR_COLLATION)); + + verify(selectExecutor, never()).executeUpdate(any(Connection.class), anyString()); + } + + @DataProvider + public static Object[][] combinationOfBin2AndSuffix() { + return Arrays.asList("", "_KS_WS") + .stream() + .map(suffix -> new String[] {format("Latin1_General_BIN2%s", suffix)}) + .toArray(Object[][]::new); + } + private void answerColumns(List columnDefs) throws SQLException { when(selectExecutor.executeSelect(any(Connection.class), anyString(), eq(ColumnDef.ColumnDefRowConverter.INSTANCE))).thenReturn(columnDefs); }