aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-db/src/test
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2016-04-14 22:59:18 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2016-04-25 17:32:48 +0200
commitc87a69b77de990c7efdf506b5a269e7facdb00b9 (patch)
tree4d99630581b94dc53857ebb8600d7846790fc416 /sonar-db/src/test
parented81b6c7f2596a13068dbcddea71162cc69aaa8f (diff)
downloadsonarqube-c87a69b77de990c7efdf506b5a269e7facdb00b9.tar.gz
sonarqube-c87a69b77de990c7efdf506b5a269e7facdb00b9.zip
SONAR-7549 Automatic repair of MSSQL and MySQL case-insensitive columns
Diffstat (limited to 'sonar-db/src/test')
-rw-r--r--sonar-db/src/test/java/org/sonar/db/charset/DatabaseCharsetCheckerTest.java77
-rw-r--r--sonar-db/src/test/java/org/sonar/db/charset/MssqlCharsetHandlerTest.java70
-rw-r--r--sonar-db/src/test/java/org/sonar/db/charset/MysqlCharsetHandlerTest.java49
-rw-r--r--sonar-db/src/test/java/org/sonar/db/charset/MysqlCollationEditorTest.java30
-rw-r--r--sonar-db/src/test/java/org/sonar/db/charset/OracleCharsetHandlerTest.java5
-rw-r--r--sonar-db/src/test/java/org/sonar/db/charset/PostgresCharsetHandlerTest.java5
-rw-r--r--sonar-db/src/test/java/org/sonar/db/charset/SelectExecutorTest.java4
-rw-r--r--sonar-db/src/test/java/org/sonar/db/charset/SqlExecutorTest.java75
8 files changed, 237 insertions, 78 deletions
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 54b166d7d99..88e47d4af2e 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
@@ -19,22 +19,93 @@
*/
package org.sonar.db.charset;
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.mockito.Mockito;
import org.sonar.db.Database;
+import org.sonar.db.dialect.Dialect;
import org.sonar.db.dialect.H2;
+import org.sonar.db.dialect.MsSql;
+import org.sonar.db.dialect.MySql;
+import org.sonar.db.dialect.Oracle;
+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.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;
public class DatabaseCharsetCheckerTest {
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
Database db = mock(Database.class, Mockito.RETURNS_MOCKS);
- DatabaseCharsetChecker underTest = new DatabaseCharsetChecker(db);
+ CharsetHandler handler = mock(CharsetHandler.class);
+ DatabaseCharsetChecker underTest = spy(new DatabaseCharsetChecker(db));
@Test
- public void does_nothing_if_h2() throws Exception {
- when(db.getDialect()).thenReturn(new H2());
+ public void executes_handler() throws Exception {
+ Oracle dialect = new Oracle();
+ when(underTest.getHandler(dialect)).thenReturn(handler);
+ when(db.getDialect()).thenReturn(dialect);
+
+ underTest.check(true);
+ verify(handler).handle(any(Connection.class), eq(true));
+ }
+
+ @Test
+ public void throws_ISE_if_handler_fails() throws Exception {
+ 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());
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("failure");
underTest.check(true);
}
+
+ @Test
+ public void does_nothing_if_h2() throws Exception {
+ assertThat(underTest.getHandler(new H2())).isNull();
+ }
+
+ @Test
+ public void getHandler_returns_MysqlCharsetHandler_if_mysql() throws Exception {
+ assertThat(underTest.getHandler(new MySql())).isInstanceOf(MysqlCharsetHandler.class);
+ }
+
+ @Test
+ public void getHandler_returns_MssqlCharsetHandler_if_mssql() throws Exception {
+ assertThat(underTest.getHandler(new MsSql())).isInstanceOf(MssqlCharsetHandler.class);
+ }
+
+ @Test
+ public void getHandler_returns_OracleCharsetHandler_if_oracle() throws Exception {
+ assertThat(underTest.getHandler(new Oracle())).isInstanceOf(OracleCharsetHandler.class);
+ }
+
+ @Test
+ public void getHandler_returns_PostgresCharsetHandler_if_postgres() throws Exception {
+ assertThat(underTest.getHandler(new PostgreSql())).isInstanceOf(PostgresCharsetHandler.class);
+ }
+
+ @Test
+ public void getHandler_throws_IAE_if_unsupported_db() throws Exception {
+ Dialect unsupportedDialect = mock(Dialect.class);
+ when(unsupportedDialect.getId()).thenReturn("foo");
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Database not supported: foo");
+ underTest.getHandler(unsupportedDialect);
+ }
}
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 5f9b8c6dad8..2712b66b274 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
@@ -21,17 +21,18 @@ package org.sonar.db.charset;
import java.sql.Connection;
import java.sql.SQLException;
+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 static java.util.Arrays.asList;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class MssqlCharsetHandlerTest {
@@ -44,32 +45,67 @@ public class MssqlCharsetHandlerTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
- CharsetHandler.SelectExecutor selectExecutor = mock(CharsetHandler.SelectExecutor.class);
+ SqlExecutor selectExecutor = mock(SqlExecutor.class);
MssqlCharsetHandler underTest = new MssqlCharsetHandler(selectExecutor);
@Test
- public void checks_case_sensibility() throws Exception {
- answerSql(asList(
- new String[] {TABLE_ISSUES, COLUMN_KEE, "Latin1_General_CS_AS"},
- new String[] {TABLE_PROJECTS, COLUMN_NAME, "Latin1_General_CS_AS"}));
+ public void does_not_fail_if_charsets_of_all_columns_are_utf8() 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);
}
@Test
- public void fails_if_case_insensitive() throws Exception {
- answerSql(asList(
- new String[] {TABLE_ISSUES, COLUMN_KEE, "Latin1_General_CS_AS"},
- new String[] {TABLE_PROJECTS, COLUMN_KEE, "Latin1_General_CI_AI"},
- new String[] {TABLE_PROJECTS, COLUMN_NAME, "Latin1_General_CI_AI"}));
+ public void repairs_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)));
- expectedException.expect(MessageException.class);
- expectedException.expectMessage("Case-sensitive and accent-sensitive collation (CS_AS) is required for database columns [projects.kee, projects.name]");
+ Connection connection = mock(Connection.class);
+ underTest.handle(connection, false);
- underTest.handle(mock(Connection.class), true);
+ 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 {
+ 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)));
+ answerIndices(asList(
+ new MssqlCharsetHandler.ColumnIndex("projects_name", false, "name"),
+ // This index is on two columns. Note that it does not make sense for table "projects" !
+ new MssqlCharsetHandler.ColumnIndex("projects_login_and_name", true, "login,name")));
+
+ Connection connection = mock(Connection.class);
+ underTest.handle(connection, false);
+
+ verify(selectExecutor).executeUpdate(connection, "DROP INDEX projects.projects_name");
+ verify(selectExecutor).executeUpdate(connection, "DROP INDEX projects.projects_login_and_name");
+ verify(selectExecutor).executeUpdate(connection, "ALTER TABLE projects ALTER COLUMN name varchar(10) COLLATE Latin1_General_CS_AS NOT NULL");
+ verify(selectExecutor).executeUpdate(connection, "CREATE INDEX projects_name ON projects (name)");
+ verify(selectExecutor).executeUpdate(connection, "CREATE UNIQUE INDEX projects_login_and_name ON projects (login,name)");
+ }
+
+ @Test
+ public void support_the_max_size_of_varchar_column() throws Exception {
+ // returned size is -1
+ answerColumns(asList(new ColumnDef(TABLE_PROJECTS, COLUMN_NAME, "Latin1_General", "Latin1_General_CI_AI", "nvarchar", -1, false)));
+ answerIndices(Collections.<MssqlCharsetHandler.ColumnIndex>emptyList());
+
+ Connection connection = mock(Connection.class);
+ underTest.handle(connection, false);
+
+ verify(selectExecutor).executeUpdate(connection, "ALTER TABLE projects ALTER COLUMN name nvarchar(max) COLLATE Latin1_General_CS_AS NOT NULL");
+ }
+
+ private void answerColumns(List<ColumnDef> columnDefs) throws SQLException {
+ when(selectExecutor.executeSelect(any(Connection.class), anyString(), eq(ColumnDef.ColumnDefRowConverter.INSTANCE))).thenReturn(columnDefs);
}
- private void answerSql(List<String[]> firstRequest, List<String[]>... otherRequests) throws SQLException {
- when(selectExecutor.executeQuery(any(Connection.class), anyString(), anyInt())).thenReturn(firstRequest, otherRequests);
+ private void answerIndices(List<MssqlCharsetHandler.ColumnIndex> indices) throws SQLException {
+ when(selectExecutor.executeSelect(any(Connection.class), anyString(), eq(MssqlCharsetHandler.ColumnIndexConverter.INSTANCE))).thenReturn(indices);
}
}
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 3727419b0e3..9e9687a2bfd 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
@@ -30,8 +30,8 @@ import org.sonar.api.utils.MessageException;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -46,42 +46,51 @@ public class MysqlCharsetHandlerTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
- CharsetHandler.SelectExecutor selectExecutor = mock(CharsetHandler.SelectExecutor.class);
- MysqlCharsetHandler.CollationEditor collationEditor = mock(MysqlCharsetHandler.CollationEditor.class);
- MysqlCharsetHandler underTest = new MysqlCharsetHandler(selectExecutor, collationEditor);
+ SqlExecutor selectExecutor = mock(SqlExecutor.class);
+ MysqlCharsetHandler underTest = new MysqlCharsetHandler(selectExecutor);
@Test
- public void checks_utf8() throws Exception {
- answerSql(asList(
- new String[] {TABLE_ISSUES, COLUMN_KEE, "utf8", "utf8_bin"},
- new String[] {TABLE_PROJECTS, COLUMN_NAME, "utf8", "utf8_bin"}));
+ public void does_not_fail_if_charsets_of_all_columns_are_utf8() 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);
}
@Test
public void fails_if_not_utf8() throws Exception {
- answerSql(asList(
- new String[] {TABLE_ISSUES, COLUMN_KEE, "utf8", "utf8_bin"},
- new String[] {TABLE_PROJECTS, COLUMN_KEE, "latin1", "utf8_bin"},
- new String[] {TABLE_PROJECTS, COLUMN_NAME, "latin1", "utf8_bin"}));
+ 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),
+ new ColumnDef(TABLE_PROJECTS, COLUMN_NAME, "latin1", "latin1_swedish_ci", "varchar", 20, false)));
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);
}
@Test
public void repairs_case_insensitive_column() throws Exception {
- answerSql(asList(
- new String[] {TABLE_ISSUES, COLUMN_KEE, "utf8", "utf8_bin"},
- new String[] {TABLE_PROJECTS, COLUMN_NAME, "utf8", "latin1_swedish_ci"}));
+ 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);
+
+ verify(selectExecutor).executeUpdate(connection, "ALTER TABLE projects MODIFY name varchar(10) CHARACTER SET 'latin1' COLLATE 'latin1_bin' NOT NULL");
+ }
+
+ @Test
+ public void size_should_be_ignored_on_longtext_column() throws Exception {
+ 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, true);
+ underTest.handle(connection, false);
- verify(collationEditor).alter(connection, TABLE_PROJECTS, COLUMN_NAME, "latin1_bin");
+ verify(selectExecutor).executeUpdate(connection, "ALTER TABLE " + TABLE_ISSUES + " MODIFY " + COLUMN_KEE + " longtext CHARACTER SET 'latin1' COLLATE 'latin1_bin' NOT NULL");
}
@Test
@@ -89,7 +98,7 @@ public class MysqlCharsetHandlerTest {
assertThat(MysqlCharsetHandler.toCaseSensitive("big5_chinese_ci")).isEqualTo("big5_bin");
}
- private void answerSql(List<String[]> firstRequest, List<String[]>... otherRequests) throws SQLException {
- when(selectExecutor.executeQuery(any(Connection.class), anyString(), anyInt())).thenReturn(firstRequest, otherRequests);
+ private void answerColumnDef(List<ColumnDef> columnDefs) throws SQLException {
+ when(selectExecutor.executeSelect(any(Connection.class), anyString(), eq(ColumnDef.ColumnDefRowConverter.INSTANCE))).thenReturn(columnDefs);
}
}
diff --git a/sonar-db/src/test/java/org/sonar/db/charset/MysqlCollationEditorTest.java b/sonar-db/src/test/java/org/sonar/db/charset/MysqlCollationEditorTest.java
deleted file mode 100644
index a5bf4a1a2da..00000000000
--- a/sonar-db/src/test/java/org/sonar/db/charset/MysqlCollationEditorTest.java
+++ /dev/null
@@ -1,30 +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.db.charset;
-
-import org.junit.Rule;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbTester;
-
-public class MysqlCollationEditorTest {
- @Rule
- public DbTester db = DbTester.createForSchema(System2.INSTANCE, MysqlCollationEditorTest.class, "schema.sql");
-
-}
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 acda3df6cc4..0d39cdb598d 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
@@ -30,7 +30,6 @@ import org.sonar.api.utils.MessageException;
import static java.util.Collections.singletonList;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -40,7 +39,7 @@ public class OracleCharsetHandlerTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
- CharsetHandler.SelectExecutor selectExecutor = mock(CharsetHandler.SelectExecutor.class);
+ SqlExecutor selectExecutor = mock(SqlExecutor.class);
OracleCharsetHandler underTest = new OracleCharsetHandler(selectExecutor);
@Test
@@ -96,6 +95,6 @@ public class OracleCharsetHandlerTest {
}
private void answerSql(List<String[]> firstRequest, List<String[]>... otherRequests) throws SQLException {
- when(selectExecutor.executeQuery(any(Connection.class), anyString(), anyInt())).thenReturn(firstRequest, otherRequests);
+ when(selectExecutor.executeSelect(any(Connection.class), anyString(), any(SqlExecutor.StringsConverter.class))).thenReturn(firstRequest, otherRequests);
}
}
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 57ba731ec95..de30b65f63a 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
@@ -30,7 +30,6 @@ import org.sonar.api.utils.MessageException;
import static java.util.Arrays.asList;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -45,7 +44,7 @@ public class PostgresCharsetHandlerTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
- CharsetHandler.SelectExecutor selectExecutor = mock(CharsetHandler.SelectExecutor.class);
+ SqlExecutor selectExecutor = mock(SqlExecutor.class);
PostgresCharsetHandler underTest = new PostgresCharsetHandler(selectExecutor);
@Test
@@ -108,6 +107,6 @@ public class PostgresCharsetHandlerTest {
}
private void answerSql(List<String[]> firstRequest, List<String[]>... otherRequests) throws SQLException {
- when(selectExecutor.executeQuery(any(Connection.class), anyString(), anyInt())).thenReturn(firstRequest, otherRequests);
+ when(selectExecutor.executeSelect(any(Connection.class), anyString(), any(SqlExecutor.StringsConverter.class))).thenReturn(firstRequest, otherRequests);
}
}
diff --git a/sonar-db/src/test/java/org/sonar/db/charset/SelectExecutorTest.java b/sonar-db/src/test/java/org/sonar/db/charset/SelectExecutorTest.java
index bfa0a48943b..5c36b5f6cb8 100644
--- a/sonar-db/src/test/java/org/sonar/db/charset/SelectExecutorTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/charset/SelectExecutorTest.java
@@ -35,7 +35,7 @@ public class SelectExecutorTest {
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
- CharsetHandler.SelectExecutor underTest = new CharsetHandler.SelectExecutor();
+ SqlExecutor underTest = new SqlExecutor();
@Test
public void testExecuteQuery() throws Exception {
@@ -45,7 +45,7 @@ public class SelectExecutorTest {
session.commit();
try (Connection connection = dbTester.openConnection()) {
- List<String[]> rows = underTest.executeQuery(connection, "select login, name from users order by login", 2);
+ List<String[]> rows = underTest.executeSelect(connection, "select login, name from users order by login", new SqlExecutor.StringsConverter(2));
assertThat(rows).hasSize(2);
assertThat(rows.get(0)[0]).isEqualTo("her");
assertThat(rows.get(0)[1]).isEqualTo("Her");
diff --git a/sonar-db/src/test/java/org/sonar/db/charset/SqlExecutorTest.java b/sonar-db/src/test/java/org/sonar/db/charset/SqlExecutorTest.java
new file mode 100644
index 00000000000..0ca4dc561c2
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/charset/SqlExecutorTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.charset;
+
+import com.google.common.collect.ImmutableMap;
+import java.sql.Connection;
+import java.util.List;
+import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SqlExecutorTest {
+
+ private static final String LOGIN_DB_COLUMN = "login";
+ private static final String NAME_DB_COLUMN = "name";
+ private static final String USERS_DB_TABLE = "users";
+
+ SqlExecutor underTest = new SqlExecutor();
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ @Test
+ public void executeSelect_executes_PreparedStatement() throws Exception {
+ dbTester.executeInsert(USERS_DB_TABLE, ImmutableMap.of(LOGIN_DB_COLUMN, "login1", NAME_DB_COLUMN, "name one"));
+ dbTester.executeInsert(USERS_DB_TABLE, ImmutableMap.of(LOGIN_DB_COLUMN, "login2", NAME_DB_COLUMN, "name two"));
+
+ dbTester.commit();
+
+ try (Connection connection = dbTester.openConnection()) {
+ List<String[]> users = underTest.executeSelect(connection, "select " + LOGIN_DB_COLUMN + ", " + NAME_DB_COLUMN + " from users order by id", new SqlExecutor.StringsConverter(
+ 2));
+ assertThat(users).hasSize(2);
+ assertThat(users.get(0)[0]).isEqualTo("login1");
+ assertThat(users.get(0)[1]).isEqualTo("name one");
+ assertThat(users.get(1)[0]).isEqualTo("login2");
+ assertThat(users.get(1)[1]).isEqualTo("name two");
+ }
+ }
+
+ @Test
+ public void executeUpdate_executes_PreparedStatement() throws Exception {
+ dbTester.executeInsert(USERS_DB_TABLE, ImmutableMap.of(LOGIN_DB_COLUMN, "the_login", NAME_DB_COLUMN, "the name"));
+ dbTester.commit();
+
+ try (Connection connection = dbTester.openConnection()) {
+ underTest.executeUpdate(connection, "update users set " + NAME_DB_COLUMN + "='new name' where " + LOGIN_DB_COLUMN + "='the_login'");
+ connection.commit();
+ }
+ Map<String, Object> row = dbTester.selectFirst("select " + NAME_DB_COLUMN + " from users where " + LOGIN_DB_COLUMN + "='the_login'");
+ assertThat(row.get("NAME")).isEqualTo("new name");
+ }
+
+}