CollationTest.java
package org.sqlite;
import static org.assertj.core.api.Assertions.assertThat;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/** Tests User Defined Collations. */
public class CollationTest {
    private Connection conn;
    private Statement stat;
    private static String valStr1 = "";
    private static String valStr2 = "";
    @BeforeEach
    public void connect() throws Exception {
        conn = DriverManager.getConnection("jdbc:sqlite:");
        stat = conn.createStatement();
    }
    @AfterEach
    public void close() throws SQLException {
        stat.close();
        conn.close();
    }
    @Test
    public void reverseCollation() throws SQLException {
        ArrayList<String> received = new ArrayList<>();
        Collation.create(
                conn,
                "REVERSE",
                new Collation() {
                    @Override
                    protected int xCompare(String str1, String str2) {
                        received.add(str1);
                        received.add(str2);
                        return str1.compareTo(str2) * -1;
                    }
                });
        stat.executeUpdate("create table t (c1);");
        stat.executeUpdate("insert into t values ('aaa');");
        stat.executeUpdate("insert into t values ('aba');");
        stat.executeUpdate("insert into t values ('aca');");
        ResultSet rs = stat.executeQuery("select c1 from t order by c1 collate REVERSE;");
        assertThat(rs.next()).isTrue();
        assertThat(rs.getString(1)).isEqualTo("aca");
        assertThat(rs.next()).isTrue();
        assertThat(rs.getString(1)).isEqualTo("aba");
        assertThat(rs.next()).isTrue();
        assertThat(rs.getString(1)).isEqualTo("aaa");
        String[] expected = {"aba", "aca", "aaa"};
        assertThat(received.stream().distinct().sorted().toArray())
                .isEqualTo(Arrays.stream(expected).distinct().sorted().toArray());
    }
    @Test
    public void unicodeCollation() throws SQLException {
        ArrayList<String> received = new ArrayList<>();
        Collation.create(
                conn,
                "UNICODE",
                new Collation() {
                    @Override
                    protected int xCompare(String str1, String str2) {
                        received.add(str1);
                        received.add(str2);
                        Collator collator = Collator.getInstance();
                        collator.setDecomposition(Collator.TERTIARY);
                        collator.setStrength(Collator.CANONICAL_DECOMPOSITION);
                        return collator.compare(str1, str2);
                    }
                });
        stat.executeUpdate("create table t (c1);");
        stat.executeUpdate("insert into t values ('aec');");
        stat.executeUpdate("insert into t values ('aea');");
        stat.executeUpdate("insert into t values ('a��b');");
        ResultSet rs = stat.executeQuery("select c1 from t order by c1 collate UNICODE;");
        assertThat(rs.next()).isTrue();
        assertThat(rs.getString(1)).isEqualTo("aea");
        assertThat(rs.next()).isTrue();
        assertThat(rs.getString(1)).isEqualTo("a��b");
        assertThat(rs.next()).isTrue();
        assertThat(rs.getString(1)).isEqualTo("aec");
        String[] expected = {"aea", "a��b", "aec"};
        assertThat(received.stream().distinct().sorted().toArray())
                .isEqualTo(Arrays.stream(expected).distinct().sorted().toArray());
    }
    @Test
    public void twoCollationsNoConflict() throws SQLException {
        Collation.create(
                conn,
                "REVERSE",
                new Collation() {
                    @Override
                    protected int xCompare(String str1, String str2) {
                        return str1.compareTo(str2) * -1;
                    }
                });
        Collation.create(
                conn,
                "NORMAL",
                new Collation() {
                    @Override
                    protected int xCompare(String str1, String str2) {
                        return str1.compareTo(str2);
                    }
                });
        stat.executeUpdate("create table t (c1);");
        stat.executeUpdate("insert into t values ('a');");
        stat.executeUpdate("insert into t values ('b');");
        stat.executeUpdate("insert into t values ('c');");
        ResultSet rs = stat.executeQuery("select c1 from t order by c1 collate REVERSE;");
        assertThat(rs.next()).isTrue();
        assertThat(rs.getString(1)).isEqualTo("c");
        assertThat(rs.next()).isTrue();
        assertThat(rs.getString(1)).isEqualTo("b");
        assertThat(rs.next()).isTrue();
        assertThat(rs.getString(1)).isEqualTo("a");
        ResultSet rs2 = stat.executeQuery("select c1 from t order by c1 collate NORMAL;");
        assertThat(rs2.next()).isTrue();
        assertThat(rs2.getString(1)).isEqualTo("a");
        assertThat(rs2.next()).isTrue();
        assertThat(rs2.getString(1)).isEqualTo("b");
        assertThat(rs2.next()).isTrue();
        assertThat(rs2.getString(1)).isEqualTo("c");
        ResultSet rs3 = stat.executeQuery("select c1 from t order by c1 collate REVERSE;");
        assertThat(rs3.next()).isTrue();
        assertThat(rs3.getString(1)).isEqualTo("c");
        assertThat(rs3.next()).isTrue();
        assertThat(rs3.getString(1)).isEqualTo("b");
        assertThat(rs3.next()).isTrue();
        assertThat(rs3.getString(1)).isEqualTo("a");
    }
    @Test
    public void validateSpecialCharactersAreCorrectlyPassedToJava() throws SQLException {
        ArrayList<String> received = new ArrayList<>();
        Collation.create(
                conn,
                "UNICODE",
                new Collation() {
                    @Override
                    protected int xCompare(String str1, String str2) {
                        received.add(str1);
                        received.add(str2);
                        Collator collator = Collator.getInstance();
                        collator.setDecomposition(Collator.TERTIARY);
                        collator.setStrength(Collator.CANONICAL_DECOMPOSITION);
                        return collator.compare(str1, str2);
                    }
                });
        stat.executeUpdate("create table t (c1);");
        stat.executeUpdate("insert into t values ('����');");
        stat.executeUpdate("insert into t values ('������������');");
        stat.executeUpdate("insert into t values ('������');");
        stat.executeUpdate("insert into t values ('���������������');");
        stat.executeQuery("select c1 from t order by c1 collate UNICODE;");
        String[] expected = {"����", "������������", "������", "���������������"};
        assertThat(received.stream().distinct().sorted().toArray())
                .isEqualTo(Arrays.stream(expected).distinct().sorted().toArray());
    }
    @Test
    public void destroy() throws SQLException {
        Collation.create(
                conn,
                "c1",
                new Collation() {
                    @Override
                    protected int xCompare(String str1, String str2) {
                        valStr1 = str1;
                        valStr2 = str2;
                        return str1.compareTo(str2) * -1;
                    }
                });
        stat.executeUpdate("create table t (c1);");
        stat.executeUpdate("insert into t values ('a');");
        stat.executeUpdate("insert into t values ('b');");
        stat.executeQuery("select c1 from t order by c1 collate c1;");
        assertThat(valStr1).isEqualTo("a");
        assertThat(valStr2).isEqualTo("b");
        Collation.destroy(conn, "c1");
        Collation.destroy(conn, "c1");
    }
}