javaandroidsqliteandroid-room

Query in Room SQLite (Insensitive casing) ignoring accents


In a part of my Android application you can search for people by name. But I need that even if the name or surname is written incorrectly (without an accent for example) the result is displayed:

Example:

In database: Pérez Juan, Cooper Sheldon, Pérez Adrian

Search: perez

Show: Pérez Juan, Pérez Adrian (from database)

I was performing the query using LIKE and it works covering the insensitive casing, but it doesn't work for accents because I have to write the letter exactly the same (with or without an accent), here is my working code:

So I get the variable used in searchPerson

String name = searchEditText.getText().toString();
            if (!name.equals("")){
                name = "%" + name + "%";
            }

PersonDao

@Query("SELECT *, lastName || ' ' || name AS FullName\n" +
        "FROM Person\n" +
        "WHERE FullName LIKE :fn\n" +
        "ORDER BY FullName")
LiveData<List<Person>> searchPerson(String fn);

Possible solution found on StackOverflow


To solve the problem of the accents I found this answer that I am trying to implement without success

So I get the variable used in searchPerson

String name = searchEditText.getText().toString();
            name = addTildeOptions(name);

addTildeOptions function

private String addTildeOptions(String searchText) {
    return searchText.toLowerCase()
            .replaceAll("\\[aáàäâã]\\.*", "[aáàäâã]")
            .replaceAll("\\[eéèëê]\\.*", "[eéèëê]")
            .replaceAll("\\[iíìî]\\.*", "[iíìî]")
            .replaceAll("\\[oóòöôõ]\\.*", "[oóòöôõ]")
            .replaceAll("\\[uúùüû]\\.*", "[uúùüû]")
            .replace("*", "[*]")
            .replace("?", "[?]");
}

PersonDao

@Query("SELECT *, lastName || ' ' || name AS FullName\n" +
        "FROM Person\n" +
        "WHERE lower(FullName) GLOB :fn\n" +
        "ORDER BY FullName")
LiveData<List<Person>> searchPerson(String fn);

However this does not return any results, even if I type a single letter it never shows anything.

I've tried adding asterisks to the start and end when getting the text of the EditText, tried to enter the addTildeOptions function in my PersonDao query as the answer shows but failed to do so, tried some other non-relevant things but never got results.

What is wrong in my code?


Solution

  • Using GLOB was what I needed. However, I changed it a little bit to be a little more "fine-grained". @zen_of_kermit 's solution would also match "Poraz Jaen" for example; but this would not:

    String globPersonName(String fn) {
        return fn.replaceAll("[aáàäâã]", "[aáàäâã]")
                .replaceAll("[eéèëê]", "[eéèëê]")
                .replaceAll("[iíìî]", "[iíìî]")
                .replaceAll("[oóòöôõ]", "[oóòöôõ]")
                .replaceAll("[uúùüû]", "[uúùüû]");
    }
    

    This way each vowel is replaced by its respective regular expression, so it matches only known variants of each vowel.