aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-db
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2016-05-18 16:02:12 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2016-05-19 15:35:58 +0200
commit4478d4093e636acf7811e96b08fb9ecdbe22eb0f (patch)
tree18af88b01b82f3d655becd07a87106f5dfb3dfba /sonar-db
parentbc9b9edb7c887a74c47c59d615c48ae7024ab392 (diff)
downloadsonarqube-4478d4093e636acf7811e96b08fb9ecdbe22eb0f.tar.gz
sonarqube-4478d4093e636acf7811e96b08fb9ecdbe22eb0f.zip
SONAR-7649 do not repair db collation outside migration
Diffstat (limited to 'sonar-db')
-rw-r--r--sonar-db/src/main/java/org/sonar/db/charset/CharsetHandler.java4
-rw-r--r--sonar-db/src/main/java/org/sonar/db/charset/DatabaseCharsetChecker.java12
-rw-r--r--sonar-db/src/main/java/org/sonar/db/charset/MssqlCharsetHandler.java32
-rw-r--r--sonar-db/src/main/java/org/sonar/db/charset/MysqlCharsetHandler.java44
-rw-r--r--sonar-db/src/main/java/org/sonar/db/charset/OracleCharsetHandler.java6
-rw-r--r--sonar-db/src/main/java/org/sonar/db/charset/PostgresCharsetHandler.java10
-rw-r--r--sonar-db/src/test/java/org/sonar/db/charset/DatabaseCharsetCheckerTest.java26
-rw-r--r--sonar-db/src/test/java/org/sonar/db/charset/MssqlCharsetHandlerTest.java33
-rw-r--r--sonar-db/src/test/java/org/sonar/db/charset/MysqlCharsetHandlerTest.java29
-rw-r--r--sonar-db/src/test/java/org/sonar/db/charset/OracleCharsetHandlerTest.java18
-rw-r--r--sonar-db/src/test/java/org/sonar/db/charset/PostgresCharsetHandlerTest.java14
11 files changed, 162 insertions, 66 deletions
diff --git a/sonar-db/src/main/java/org/sonar/db/charset/CharsetHandler.java b/sonar-db/src/main/java/org/sonar/db/charset/CharsetHandler.java
index 233cb14b5a8..df8d2d4fa3c 100644
--- a/sonar-db/src/main/java/org/sonar/db/charset/CharsetHandler.java
+++ b/sonar-db/src/main/java/org/sonar/db/charset/CharsetHandler.java
@@ -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);
}
-
}
diff --git a/sonar-db/src/main/java/org/sonar/db/charset/DatabaseCharsetChecker.java b/sonar-db/src/main/java/org/sonar/db/charset/DatabaseCharsetChecker.java
index cdc87bc3b2d..2e89e2d3a97 100644
--- a/sonar-db/src/main/java/org/sonar/db/charset/DatabaseCharsetChecker.java
+++ b/sonar-db/src/main/java/org/sonar/db/charset/DatabaseCharsetChecker.java
@@ -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());
}
}
-
}
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 774251771eb..cbac5a3d59a 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
@@ -20,16 +20,21 @@
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 {
diff --git a/sonar-db/src/main/java/org/sonar/db/charset/MysqlCharsetHandler.java b/sonar-db/src/main/java/org/sonar/db/charset/MysqlCharsetHandler.java
index 43bec2d9ffc..4f003aba735 100644
--- a/sonar-db/src/main/java/org/sonar/db/charset/MysqlCharsetHandler.java
+++ b/sonar-db/src/main/java/org/sonar/db/charset/MysqlCharsetHandler.java
@@ -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)));
}
}
diff --git a/sonar-db/src/main/java/org/sonar/db/charset/OracleCharsetHandler.java b/sonar-db/src/main/java/org/sonar/db/charset/OracleCharsetHandler.java
index 179d7c2f796..1ff377175cf 100644
--- a/sonar-db/src/main/java/org/sonar/db/charset/OracleCharsetHandler.java
+++ b/sonar-db/src/main/java/org/sonar/db/charset/OracleCharsetHandler.java
@@ -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);
}
diff --git a/sonar-db/src/main/java/org/sonar/db/charset/PostgresCharsetHandler.java b/sonar-db/src/main/java/org/sonar/db/charset/PostgresCharsetHandler.java
index 1452750ae1f..81cd5bcc1a3 100644
--- a/sonar-db/src/main/java/org/sonar/db/charset/PostgresCharsetHandler.java
+++ b/sonar-db/src/main/java/org/sonar/db/charset/PostgresCharsetHandler.java
@@ -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;
diff --git a/sonar-db/src/test/java/org/sonar/db/charset/DatabaseCharsetCheckerTest.java b/sonar-db/src/test/java/org/sonar/db/charset/DatabaseCharsetCheckerTest.java
index 88e47d4af2e..41c87e6b28f 100644
--- a/sonar-db/src/test/java/org/sonar/db/charset/DatabaseCharsetCheckerTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/charset/DatabaseCharsetCheckerTest.java
@@ -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
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 f3748576380..a81bf41ddda 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
@@ -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());
}
diff --git a/sonar-db/src/test/java/org/sonar/db/charset/MysqlCharsetHandlerTest.java b/sonar-db/src/test/java/org/sonar/db/charset/MysqlCharsetHandlerTest.java
index 9e9687a2bfd..d050fbedf3c 100644
--- a/sonar-db/src/test/java/org/sonar/db/charset/MysqlCharsetHandlerTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/charset/MysqlCharsetHandlerTest.java
@@ -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");
}
diff --git a/sonar-db/src/test/java/org/sonar/db/charset/OracleCharsetHandlerTest.java b/sonar-db/src/test/java/org/sonar/db/charset/OracleCharsetHandlerTest.java
index 0d39cdb598d..76be06e7f21 100644
--- a/sonar-db/src/test/java/org/sonar/db/charset/OracleCharsetHandlerTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/charset/OracleCharsetHandlerTest.java
@@ -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 {
diff --git a/sonar-db/src/test/java/org/sonar/db/charset/PostgresCharsetHandlerTest.java b/sonar-db/src/test/java/org/sonar/db/charset/PostgresCharsetHandlerTest.java
index de30b65f63a..d348e31117e 100644
--- a/sonar-db/src/test/java/org/sonar/db/charset/PostgresCharsetHandlerTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/charset/PostgresCharsetHandlerTest.java
@@ -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 {