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);
"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 {
}
}
+ /**
+ * 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<DatabaseCharsetChecker.Flag> flags) {
if (flags.contains(AUTO_REPAIR_COLLATION)) {
LOGGER.info("Repair case-insensitive or accent-insensitive database columns");
}
@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);
@DataProvider
public static Object[][] combinationsOfCsAsAndSuffix() {
List<String[]> 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);
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<ColumnDef> columnDefs) throws SQLException {
when(selectExecutor.executeSelect(any(Connection.class), anyString(), eq(ColumnDef.ColumnDefRowConverter.INSTANCE))).thenReturn(columnDefs);
}